38 lines
1.7 KiB
TypeScript
38 lines
1.7 KiB
TypeScript
|
|
import "server-only";
|
||
|
|
import type PocketBase from "pocketbase";
|
||
|
|
import { supplierKey, type Terms } from "./supplier";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The supplier a purchase order or slip belongs to — found, or created.
|
||
|
|
*
|
||
|
|
* Match order: the supplier's CODE from the PO ("09YTS001") when there is one, then the folded
|
||
|
|
* NAME. A new supplier takes `terms` (a till slip is "cash"; a PO supplier nobody has classified
|
||
|
|
* yet is left "" so the list shows it as needing terms). An existing supplier's terms are never
|
||
|
|
* overwritten here — only a person changes those.
|
||
|
|
*/
|
||
|
|
export async function resolveSupplier(
|
||
|
|
pb: PocketBase,
|
||
|
|
input: { name: string; code?: string; terms?: Terms; source: string },
|
||
|
|
): Promise<string> {
|
||
|
|
const name = (input.name || "").trim();
|
||
|
|
const key = supplierKey(name);
|
||
|
|
if (!name || !key) return "";
|
||
|
|
const code = (input.code || "").trim().toUpperCase();
|
||
|
|
|
||
|
|
const all = await pb.collection("suppliers").getFullList({ fields: "id,key,code" });
|
||
|
|
const hit = (code && all.find((s) => (s.code || "").toUpperCase() === code)) || all.find((s) => s.key === key);
|
||
|
|
if (hit) {
|
||
|
|
// Learn a code we did not have, without disturbing anything a person set.
|
||
|
|
if (code && !(hit.code || "").trim()) await pb.collection("suppliers").update(hit.id, { code }).catch(() => {});
|
||
|
|
return hit.id;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
const created = await pb.collection("suppliers").create({ name, key, code, terms: input.terms ?? "", source: input.source });
|
||
|
|
return created.id;
|
||
|
|
} catch {
|
||
|
|
// Lost a race to the unique key: someone created it a moment ago.
|
||
|
|
const again = (await pb.collection("suppliers").getFullList({ fields: "id,key" })).find((s) => s.key === key);
|
||
|
|
return again?.id ?? "";
|
||
|
|
}
|
||
|
|
}
|