import { queriesFor, requireId, requireText } from '../logistics/helpers.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import resolveManifestAccess from '../manifestattachment/resolveManifestAccess.js'; import { syncOrderSummary } from '../order/syncSummary.js'; import { syncRetoureSummary } from '../retoure/syncSummary.js'; import makeRunner from '../runner.js'; function shape(row) { return { id: row.id, accountId: row.account_id, manifestId: row.manifest_id, type: row.type, amount: row.amount, createdAt: row.createdAt ?? row.created_at ?? null, date: row.date ?? row.createdAt ?? row.created_at ?? null, }; } export default function create(provider) { const access = resolveSelectedCompanyAccess(provider); const manifestAccess = resolveManifestAccess(provider); const q = queriesFor(provider); /** * Adds a payment to a manifest (order) using an account of the selected company. * * @param {number} googleAuthId - The id of the Google auth user. * @param {object} input - Payment input. * @param {number} input.accountId - The account id. * @param {number} input.manifestId - The manifest (order) id. * @param {string} input.type - Payment type. * @param {number} input.amount - Payment amount. * @param {object} [tx] - Optional transaction to run within. * @returns {Promise<{id: number, accountId: number, manifestId: number, type: string, amount: number}>} * @throws {Error} If account or manifest is not found, or input is invalid. * * @example * await store.payment.create(googleAuthId, { accountId: 1, manifestId: 42, type: 'cash', amount: 19.9 }); */ return async (googleAuthId, input = {}, tx) => { const accountId = requireId(input.accountId, 'Account'); const manifestId = requireId(input.manifestId, 'Manifest'); const type = requireText(input.type, 'Payment type'); if (!Number.isFinite(input.amount)) { throw new Error('Invalid payment amount'); } const run = async (runner, innerTx) => { const { companyId } = await access(googleAuthId, runner); const accountRes = await runner.query(q.CHECK_ACCOUNT_COMPANY, { accountId, companyId }); if (!accountRes.rows[0]) { throw new Error('Account not found'); } await manifestAccess(companyId, manifestId, innerTx); const result = await runner.query(q.PAYMENT_CREATE, { accountId, manifestId, type, amount: input.amount, }); const row = result.rows[0] ?? { id: result.insertId, account_id: accountId, manifest_id: manifestId, type, amount: input.amount, }; const mTypeRes = await runner.query( runner.dialect === 'sqlite3' ? 'SELECT "type" FROM manifest WHERE id = @manifestId' : 'SELECT [type] FROM manifest WHERE id = @manifestId', { manifestId }, ); if (mTypeRes.rows[0]?.type === 'retoure') { await syncRetoureSummary(runner, { companyId, manifestId }); } else { await syncOrderSummary(runner, { companyId, manifestId }); } return shape(row); }; if (tx) { return run(makeRunner(provider, tx), tx); } if (typeof provider?.transaction === 'function') { return provider.transaction((runner, innerTx) => run(runner, innerTx)); } return run(makeRunner(provider, tx)); }; }