import { queriesFor, requireId, requireText } from '../logistics/helpers.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import nextNumber from '../numbers/nextNumber.js'; import makeRunner from '../runner.js'; function optionalText(value) { if (value == null) return null; const s = String(value).trim(); return s || null; } function shape(row) { return { id: row.id, shippingId: row.shipping_id, entityaddressId: row.entityaddress_id, number: row.number, type: row.type, state: row.state, details: row.details ?? null, }; } export default function create(provider) { const access = resolveSelectedCompanyAccess(provider); const allocateNumber = nextNumber(provider); const q = queriesFor(provider); /** * Creates a package for a shipping. The number is allocated from the `package` * numbers sequence (own prefix + counter). The package must target an entity address. * * @param {number} googleAuthId - The id of the Google auth user. * @param {object} input - Package input. * @param {number} input.shippingId - The shipping id. * @param {number} input.entityaddressId - The target entity address id (required). * @param {string} input.type - Package type. * @param {string} input.state - Package state. * @param {string} [input.details] - Optional details. * @param {object} [tx] - Optional transaction to run within. * @returns {Promise<{id: number, shippingId: number, entityaddressId: number, number: string, type: string, state: string, details: string|null}>} * @throws {Error} If shipping or entity address is not found, or input is invalid. * * @example * await store.package.create(googleAuthId, { shippingId: 9, entityaddressId: 3, type: 'box', state: 'packed' }); */ return async (googleAuthId, input = {}, tx) => { const shippingId = requireId(input.shippingId, 'Shipping'); const entityaddressId = requireId(input.entityaddressId, 'Entity address'); const type = requireText(input.type, 'Package type'); const state = requireText(input.state, 'Package state'); const details = optionalText(input.details); const run = async (runner, innerTx) => { const { companyId } = await access(googleAuthId, runner); const shippingRes = await runner.query(q.CHECK_SHIPPING_COMPANY, { shippingId, companyId }); if (!shippingRes.rows[0]) { throw new Error('Shipping not found'); } const addressRes = await runner.query(q.CHECK_ENTITYADDRESS_COMPANY, { entityaddressId, companyId }); if (!addressRes.rows[0]) { throw new Error('Entity address not found'); } const number = await allocateNumber(companyId, 'package', innerTx); const result = await runner.query(q.PACKAGE_CREATE, { shippingId, entityaddressId, number, type, state, details, }); const row = result.rows[0] ?? { id: result.insertId, shipping_id: shippingId, entityaddress_id: entityaddressId, number, type, state, details, }; return shape(row); }; if (typeof provider?.transaction === 'function') { return provider.transaction((runner, innerTx) => run(runner, innerTx)); } return run(makeRunner(provider, tx)); }; }