feat(freight): shop freight templates, server-side checkout fees, company dictionary (add-freight-templates)

This commit is contained in:
Chengdong Zhang
2026-09-24 15:03:51 +08:00
parent 5b426486ac
commit 473d19d089
44 changed files with 2409 additions and 67 deletions
+34 -4
View File
@@ -16,10 +16,40 @@ export function useMoney() {
}
}
function fmt(amountMinor: number, currency: string): string {
const exponent = currencies.value.find((c) => c.code === currency)?.exponent ?? 2;
return formatMoney(amountMinor, currency, exponent, locale.value);
function exponentOf(currency: string): number {
return currencies.value.find((c) => c.code === currency)?.exponent ?? 2;
}
return { currencies, load, fmt };
function fmt(amountMinor: number, currency: string): string {
return formatMoney(amountMinor, currency, exponentOf(currency), locale.value);
}
/** Currency for money fields without an explicit currency: the table's base. */
const shopCurrency = computed(
() => currencies.value.find((c) => c.is_base)?.code ?? currencies.value[0]?.code ?? "USD",
);
/** Parse a major-unit decimal string into integer minor units; null when invalid. */
function majorToMinor(value: string, currency: string): number | null {
const clean = value.trim();
if (!/^\d+(?:\.\d+)?$/.test(clean)) return null;
const exponent = exponentOf(currency);
const [whole, fraction = ""] = clean.split(".");
if (fraction.length > exponent) return null;
const minor = Number(whole) * 10 ** exponent + Number(fraction.padEnd(exponent, "0") || 0);
return Number.isSafeInteger(minor) ? minor : null;
}
/** Render integer minor units as a major-unit string for form inputs. */
function minorToMajor(minor: number, currency: string): string {
const exponent = exponentOf(currency);
const sign = minor < 0 ? "-" : "";
const abs = Math.abs(minor);
const whole = Math.trunc(abs / 10 ** exponent);
if (exponent === 0) return `${sign}${whole}`;
const fraction = (abs % 10 ** exponent).toString().padStart(exponent, "0");
return `${sign}${whole}.${fraction}`;
}
return { currencies, load, fmt, shopCurrency, majorToMinor, minorToMajor };
}