55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
import type { Locale } from "@conusai-kit/i18n"
|
|
import { parseDecimalInput } from "@conusai-kit/i18n/values"
|
|
import { type InvoiceTerms, invoiceTerms } from "../contract/index.js"
|
|
/**
|
|
* Merge edited fields, retaining all unedited terms/identifiers/notes/extensions. No float coercion: a price or a
|
|
* rate is read as the person typed it in `locale` (`12,50` in LT) into the service's exact text; text that is not a
|
|
* number is passed on as typed, so the contract refuses it by name.
|
|
*/
|
|
export function draftData(
|
|
values: Record<string, string>,
|
|
count: number,
|
|
locale: Locale,
|
|
prior?: InvoiceTerms,
|
|
): InvoiceTerms {
|
|
const exact = (text: string | undefined) => (text ? (parseDecimalInput(text, locale)?.toString() ?? text) : text)
|
|
const party = (side: "seller" | "buyer") => ({
|
|
...prior?.[side],
|
|
reference: values[`${side}.reference`],
|
|
name: values[`${side}.name`],
|
|
vat_identifier: values[`${side}.vatValue`]
|
|
? { scheme: values[`${side}.vatScheme`], value: values[`${side}.vatValue`] }
|
|
: null,
|
|
endpoint: { scheme: values[`${side}.scheme`], value: values[`${side}.endpoint`] },
|
|
address: {
|
|
...prior?.[side].address,
|
|
country: values[`${side}.country`],
|
|
street: values[`${side}.street`] || null,
|
|
city: values[`${side}.city`] || null,
|
|
postal_code: values[`${side}.postcode`] || null,
|
|
},
|
|
})
|
|
return invoiceTerms.parse({
|
|
...prior,
|
|
type_code: prior?.type_code ?? "380",
|
|
series_id: values.series,
|
|
currency: values.currency,
|
|
issue_date: values.issueDate,
|
|
due_date: values.dueDate || null,
|
|
buyer_reference: values.buyerReference,
|
|
seller: party("seller"),
|
|
buyer: party("buyer"),
|
|
lines: Array.from({ length: count }, (_, i) => ({
|
|
...prior?.lines[i],
|
|
item_name: values[`line.${i}.name`],
|
|
quantity: values[`line.${i}.quantity`],
|
|
unit: values[`line.${i}.unit`],
|
|
net_price: { currency: values.currency, amount: exact(values[`line.${i}.price`]) },
|
|
vat_category: values[`line.${i}.category`],
|
|
vat_rate: exact(values[`line.${i}.rate`]) || null,
|
|
exemption_reason: values[`line.${i}.exemption`] || null,
|
|
})),
|
|
})
|
|
}
|