fix(dn-batches): add uploaded_at so ordering works
PocketBase's created is empty on every dn_batches record, making the board's -created sort a no-op and the tick's oldest-first meaningless. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
b1ce964f39
commit
06311c6de2
5 changed files with 100 additions and 2 deletions
95
scripts/pb-add-dn-batch-uploaded-at.py
Normal file
95
scripts/pb-add-dn-batch-uploaded-at.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Adds dn_batches.uploaded_at and backfills it.
|
||||
|
||||
PocketBase's own `created` is an empty string on every dn_batches record —
|
||||
the collection was created without autodate — so the board's "-created"
|
||||
sort is a no-op and the tick's "oldest first" means nothing. The rest of
|
||||
this codebase already works around the same quirk (delivery_notes sorts by
|
||||
date_received), so an explicit field is the consistent fix.
|
||||
|
||||
Backfill uses the batch's earliest dn_batch_notes date where one exists.
|
||||
Batches with nothing to go on are LEFT EMPTY rather than given an invented
|
||||
timestamp; they sort last.
|
||||
|
||||
Idempotent.
|
||||
"""
|
||||
import sys
|
||||
|
||||
from pb_env import PB, http, superuser_token
|
||||
|
||||
|
||||
def get_all(token, coll, fields=None, filt=None):
|
||||
out, page = [], 1
|
||||
while True:
|
||||
q = f"?page={page}&perPage=200"
|
||||
if fields:
|
||||
q += f"&fields={fields}"
|
||||
if filt:
|
||||
q += f"&filter={filt}"
|
||||
code, resp = http("GET", f"/api/collections/{coll}/records{q}", token=token)
|
||||
if code != 200:
|
||||
sys.exit(f"GET {coll} failed: {code} {resp}")
|
||||
out.extend(resp["items"])
|
||||
if page >= resp["totalPages"]:
|
||||
return out
|
||||
page += 1
|
||||
|
||||
|
||||
def main():
|
||||
token = superuser_token()
|
||||
print(f"\n→ dn_batches on {PB}")
|
||||
|
||||
code, coll = http("GET", "/api/collections/dn_batches", token=token)
|
||||
if code != 200:
|
||||
sys.exit(f"GET collection failed: {code} {coll}")
|
||||
fields = list(coll.get("fields", []))
|
||||
if any(f.get("name") == "uploaded_at" for f in fields):
|
||||
print(" • uploaded_at already exists")
|
||||
else:
|
||||
code, resp = http(
|
||||
"PATCH",
|
||||
f"/api/collections/{coll['id']}",
|
||||
{"fields": fields + [{"name": "uploaded_at", "type": "date", "required": False}]},
|
||||
token,
|
||||
)
|
||||
if code != 200:
|
||||
sys.exit(f"PATCH failed: {code} {resp}")
|
||||
print(" ✓ added uploaded_at")
|
||||
|
||||
notes = get_all(token, "dn_batch_notes", "batch,date")
|
||||
earliest = {}
|
||||
for n in notes:
|
||||
d = (n.get("date") or "").strip()
|
||||
b = n.get("batch")
|
||||
if not d or not b:
|
||||
continue
|
||||
if b not in earliest or d < earliest[b]:
|
||||
earliest[b] = d
|
||||
|
||||
batches = get_all(token, "dn_batches", "id,uploaded_at")
|
||||
filled = skipped = blank = 0
|
||||
for b in batches:
|
||||
if (b.get("uploaded_at") or "").strip():
|
||||
skipped += 1
|
||||
continue
|
||||
d = earliest.get(b["id"])
|
||||
if not d:
|
||||
blank += 1
|
||||
continue
|
||||
code, resp = http(
|
||||
"PATCH",
|
||||
f"/api/collections/dn_batches/records/{b['id']}",
|
||||
{"uploaded_at": d},
|
||||
token,
|
||||
)
|
||||
if code != 200:
|
||||
sys.exit(f"PATCH {b['id']} failed: {code} {resp}")
|
||||
filled += 1
|
||||
|
||||
print(f" backfilled {filled}, already set {skipped}, left empty {blank}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
print("\nDone.")
|
||||
|
|
@ -180,6 +180,7 @@ export async function POST(request: Request) {
|
|||
source: "web",
|
||||
uploaded_by: "web-upload",
|
||||
status: "inbox",
|
||||
uploaded_at: new Date().toISOString(),
|
||||
page_count: 0,
|
||||
notes_detected: 0,
|
||||
notes_promoted: 0,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export async function POST(request: Request) {
|
|||
candidates = await pb.collection("dn_batches").getFullList({
|
||||
filter: `status='inbox'`,
|
||||
fields: "id",
|
||||
sort: "created",
|
||||
sort: "uploaded_at",
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[dn-tick] list failed", err);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default async function InboxPage({
|
|||
|
||||
const batches = await pb.collection("dn_batches").getFullList({
|
||||
expand: "site",
|
||||
sort: "-created",
|
||||
sort: "-uploaded_at",
|
||||
...filterOpt(siteFilter(scope)),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -381,6 +381,8 @@ export interface DnBatchRecord extends RecordModel {
|
|||
claimed_at: string;
|
||||
/** Last error message from n8n. Empty when the batch is healthy. */
|
||||
last_error: string;
|
||||
/** Set explicitly at upload — PocketBase's `created` is unusable here. */
|
||||
uploaded_at: string;
|
||||
expand?: { site?: SiteRecord };
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue