import { CREATE_MANIFEST as MSSQL_CREATE_MANIFEST, QUOTE_TYPE as MSSQL_QUOTE_TYPE, } from '../../providers/mssql/queries/manifestDoc.js'; import { CREATE_MANIFEST as SQLITE_CREATE_MANIFEST, QUOTE_TYPE as SQLITE_QUOTE_TYPE, } from '../../providers/sqlite3/queries/manifestDoc.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import taxEnsure from '../tax/ensure.js'; import { insertLines, normalizeLines, parseDate } from '../manifestLines.js'; import { assertCustomerEntity, loadDoc } from '../manifestDoc/helpers.js'; import makeRunner from '../runner.js'; export default function create(provider) { const access = resolveSelectedCompanyAccess(provider); const ensureTax = taxEnsure(provider); const isSqlite = provider?.dialect === 'sqlite3'; const createManifestSql = isSqlite ? SQLITE_CREATE_MANIFEST : MSSQL_CREATE_MANIFEST; const quoteType = isSqlite ? SQLITE_QUOTE_TYPE : MSSQL_QUOTE_TYPE; /** * Creates a new quote for the user's selected company with its lines. * * @param {number} googleAuthId - The id of the Google auth user. * @param {object} body - The quote input. * @param {string} body.number - The quote number. * @param {string} body.date - The quote date. * @param {number} [body.entityId] - The id of the customer entity. * @param {string} [body.externalNumber] - An external (customer) reference number. * @param {Array<{sku?: string, name?: string, pu?: number, amount: number, net: number, rebate?: number, taxrate: number, comment?: string|null}>} [body.lines] - The quote lines. * @param {object} [tx] - Optional transaction to run within. * @returns {Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>} The created quote. * @throws {Error} If the quote is invalid. * * @example * const quote = await store.quote.create(42, { number: 'A-2026-001', date: '2026-09-01', entityId: 12, lines: [...] }); * // => { id, number, type, entityId, externalNumber, date, lines: [...] } */ return async (googleAuthId, body = {}, tx) => { const number = body.number?.trim?.() ? body.number.trim() : null; const date = parseDate(body.date); if (!number || !date) { throw new Error('Invalid quote'); } const createdAt = body.createdAt ? parseDate(body.createdAt) : new Date(); if (body.createdAt && !createdAt) { throw new Error('Invalid quote'); } const externalNumber = body.externalNumber?.trim?.() ? body.externalNumber.trim() : null; const lines = normalizeLines(body.lines ?? []); const runCreate = async (runner) => { const { companyId } = await access(googleAuthId, runner); const entityId = await assertCustomerEntity( runner, companyId, body.entityId ?? null, ); const created = await runner.query(createManifestSql, { companyId, number, type: quoteType, entityId, externalNumber, date, createdAt, }); const manifestId = created.rows[0]?.id ?? created.insertId; await insertLines(runner, { manifestId, lines, ensureTax, }); const doc = await loadDoc(runner, { type: quoteType, companyId, id: manifestId, }); return doc; }; if (tx) { return runCreate(makeRunner(provider, tx)); } if (typeof provider?.transaction === 'function') { return provider.transaction(runCreate); } return runCreate(makeRunner(provider)); }; }