This commit is contained in:
seb
2026-10-21 11:55:21 +02:00
parent e085bcaeba
commit eb1e9e2eb9
8 changed files with 67 additions and 42 deletions

View File

@@ -13,11 +13,12 @@ export default function createShipment(provider) {
* @param {Array<{sku: string, amount?: number, name?: string, pu?: number, net?: number, rebate?: number, taxrate?: number, comment?: string}>} input.lines - Positions to ship.
* @param {string|Date} [input.date] - Optional shipment date.
* @param {string} [input.externalNumber] - Optional external delivery reference.
* @param {object} input.shipping - Required shipping ({carrierId, type, state, trackingCode?, warehouseId?}); see shipment.create.
* @param {object} [tx] - Optional transaction.
* @returns {Promise<object>} The created shipment.
*
* @example
* const shipment = await store.order.createShipment(googleAuthId, 10, { lines: [{ sku: 'ITEM-A', amount: 5 }] });
* const shipment = await store.order.createShipment(googleAuthId, 10, { lines: [{ sku: 'ITEM-A', amount: 5 }], shipping: { carrierId: 1, type: 'parcel', state: 'draft' } });
*/
return async (googleAuthId, orderId, input = {}, tx) => {
return create(googleAuthId, { ...input, orderId }, tx);

View File

@@ -3,6 +3,7 @@ import taxEnsure from '../tax/ensure.js';
import { insertLines, parseDate } from '../manifestLines.js';
import { assertUniqueManifestNumber } from '../manifestDoc/helpers.js';
import makeRunner from '../runner.js';
import shippingCreate from '../shipping/create.js';
import { loadShipment, queriesFor } from './helpers.js';
import { syncOrderSummary } from '../order/syncSummary.js';
import { syncShipmentSummary } from './syncSummary.js';
@@ -24,6 +25,7 @@ function requireId(val, name) {
export default function create(provider) {
const access = resolveSelectedCompanyAccess(provider);
const ensureTax = taxEnsure(provider);
const createShipping = shippingCreate(provider);
const q = queriesFor(provider);
/**
@@ -37,14 +39,21 @@ export default function create(provider) {
* @param {string|Date} [input.date] - Optional shipment date (defaults to current date).
* @param {'new'|'delivered'|'returned'} [input.state='new'] - Optional delivery state (defaults to 'new').
* @param {string} [input.externalNumber] - Optional external delivery note number (defaults to order.externalNumber or order.number).
* @param {object} input.shipping - Required shipping (package) created atomically with the shipment, so a shipment never exists without a carrier.
* @param {number} input.shipping.carrierId - The carrier id.
* @param {string} input.shipping.type - Shipping type.
* @param {string} input.shipping.state - Shipping state ('shipped' or other).
* @param {string} [input.shipping.trackingCode] - Carrier tracking code.
* @param {number} [input.shipping.warehouseId] - Optional warehouse ID for stock deduction when state is 'shipped'.
* @param {object} [tx] - Optional transaction.
* @returns {Promise<object>} The created shipment manifest.
* @throws {Error} If order not found, invalid lines, or article ceiling invariant exceeded.
* @throws {Error} If order not found, invalid lines, shipping/carrier missing or invalid, or article ceiling invariant exceeded.
*
* @example
* const shipment = await store.shipment.create(googleAuthId, {
* orderId: 10,
* lines: [{ sku: 'ITEM-A', amount: 5 }]
* lines: [{ sku: 'ITEM-A', amount: 5 }],
* shipping: { carrierId: 1, type: 'parcel', state: 'draft' }
* });
*/
return async (googleAuthId, input = {}, tx) => {
@@ -54,6 +63,11 @@ export default function create(provider) {
throw new Error('Invalid lines');
}
if (!input.shipping || typeof input.shipping !== 'object') {
throw new Error('Shipping is required');
}
requireId(input.shipping.carrierId, 'Carrier');
const shipmentDate = parseDate(input.date) || new Date();
const run = async (runner, innerTx) => {
@@ -289,6 +303,9 @@ export default function create(provider) {
state: validState,
});
// 10. Create the shipping (carrier) atomically with the shipment
await createShipping(googleAuthId, { ...input.shipping, manifestId }, innerTx);
return loadShipment(runner, q, companyId, manifestId);
};