import { DELETE_LINES_BY_MANIFEST, DELIVERY_TYPE, GET_DELIVERY_HEADER, UPDATE_MANIFEST, } from '../../sql/delivery.js'; import request from '../request.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import taxEnsure from '../tax/ensure.js'; import { loadDelivery, normalizeLines, parseDeliveryDate, shapeSummary, } from './helpers.js'; import { assertSupplier, insertLines } from './writeLines.js'; /** * Updates a delivery's header and/or lines. * * @param {object} pool - The mssql connection pool. * @returns {Function} An async function that updates a delivery. * * @example * const fn = update(pool); * const delivery = await fn(42, 5, { number: 'D-2', lines: [...] }); * // => { id, number, type, entityId, date, lines: [...] } */ export default function update(pool) { const access = resolveSelectedCompanyAccess(pool); const ensureTax = taxEnsure(pool); return async (googleAuthId, id, patch = {}) => { if (!Number.isFinite(id)) { throw new Error('Delivery not found'); } const hasNumber = Object.prototype.hasOwnProperty.call(patch, 'number'); const hasDate = Object.prototype.hasOwnProperty.call(patch, 'date'); const hasSupplierId = Object.prototype.hasOwnProperty.call( patch, 'supplierId', ); const hasLines = Object.prototype.hasOwnProperty.call(patch, 'lines'); if (!hasNumber && !hasDate && !hasSupplierId && !hasLines) { throw new Error('Invalid delivery'); } let normalizedLines; if (hasLines) { normalizedLines = normalizeLines(patch.lines); } const { companyId, rootCategoryId } = await access(googleAuthId); const tx = pool.transaction(); await tx.begin(); try { const existing = await request(pool, tx) .input('id', id) .input('companyId', companyId) .input('type', DELIVERY_TYPE) .query(GET_DELIVERY_HEADER); const current = existing.recordset[0]; if (!current) { throw new Error('Delivery not found'); } const summary = shapeSummary(current); let number = summary.number; if (hasNumber) { number = patch.number?.trim?.() ? patch.number.trim() : null; if (!number) { throw new Error('Invalid delivery'); } } let date = summary.date; if (hasDate) { date = parseDeliveryDate(patch.date); if (!date) { throw new Error('Invalid delivery'); } } let supplierId = summary.supplierId; if (hasSupplierId) { supplierId = await assertSupplier( pool, tx, companyId, patch.supplierId ?? null, ); } await request(pool, tx) .input('id', id) .input('companyId', companyId) .input('type', DELIVERY_TYPE) .input('number', number) .input('entityId', supplierId) .input('date', date) .query(UPDATE_MANIFEST); if (hasLines) { await request(pool, tx) .input('manifestId', id) .query(DELETE_LINES_BY_MANIFEST); await insertLines(pool, tx, { manifestId: id, rootCategoryId, lines: normalizedLines, ensureTax, }); } const delivery = await loadDelivery(pool, tx, companyId, id); await tx.commit(); return delivery; } catch (err) { try { await tx.rollback(); } catch { // ignore } throw err; } }; }