From 5d8ac3a8ebbd7f65ca189442aef868ccac04334f Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 16 Oct 2026 22:27:34 +0200 Subject: [PATCH] u --- src/api/article.js | 12 ++++----- src/api/globalHistory.js | 10 +++----- src/api/ledger.js | 22 ++++------------ src/api/stock.js | 20 +++++++++++++++ src/automats/sseAutomat.js | 6 ++--- src/utils/deliveryLedger.js | 50 ++++++++++++++++++------------------- 6 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/api/article.js b/src/api/article.js index 6c2a86c..36ecf5b 100644 --- a/src/api/article.js +++ b/src/api/article.js @@ -30,15 +30,14 @@ export const article = { /** * GET /api/article/history?offset=0&limit=50&search=...&seekMonths=-1 - * @param {{ offset?: number, limit?: number, search?: string, seekMonths?: number, startRow?: number, endRow?: number }} [params] + * @param {{ offset?: number, limit?: number, search?: string, seekMonths?: number, sortModel?: Array, filterModel?: object }} [params] * → { history: ArticleHistoryEntry[], total: number, unfilteredTotal?: number } */ - getHistory({ offset = 0, limit = 50, search, seekMonths, startRow, endRow, sortModel, filterModel } = {}) { + // #region GET /api/article/history — getHistory + getHistory({ offset = 0, limit = 50, search, seekMonths, sortModel, filterModel } = {}) { const params = new URLSearchParams(); - const finalOffset = offset != null ? offset : (startRow != null ? startRow : 0); - const finalLimit = limit != null ? limit : (endRow != null && startRow != null ? endRow - startRow : 50); - params.set('offset', String(Math.max(0, Math.floor(Number(finalOffset) || 0)))); - params.set('limit', String(Math.max(1, Math.floor(Number(finalLimit) || 50)))); + params.set('offset', String(Math.max(0, Math.floor(Number(offset) || 0)))); + params.set('limit', String(Math.max(1, Math.floor(Number(limit) || 50)))); if (search && String(search).trim()) params.set('search', String(search).trim()); if (seekMonths != null && Number(seekMonths) < 0) { params.set('seekMonths', String(Math.floor(Number(seekMonths)))); @@ -48,6 +47,7 @@ export const article = { const qs = params.toString(); return http(`/api/article/history${qs ? `?${qs}` : ''}`); }, + // #endregion /** * GET /api/article/:sku/history diff --git a/src/api/globalHistory.js b/src/api/globalHistory.js index ad5377e..611908f 100644 --- a/src/api/globalHistory.js +++ b/src/api/globalHistory.js @@ -4,16 +4,14 @@ export const globalHistory = { /** * GET /api/history?offset=0&limit=50&search=...&seekMonths=-1 * Global system/entity history with chunk paging and search/seek filtering - * @param {{ offset?: number, limit?: number, search?: string, seekMonths?: number, startRow?: number, endRow?: number }} [params] + * @param {{ offset?: number, limit?: number, search?: string, seekMonths?: number, sortModel?: Array, filterModel?: object }} [params] * → { history: GlobalHistoryEntry[], total: number, unfilteredTotal?: number } */ // #region GET /api/history — list - list({ offset = 0, limit = 50, search, seekMonths, startRow, endRow, sortModel, filterModel } = {}) { + list({ offset = 0, limit = 50, search, seekMonths, sortModel, filterModel } = {}) { const params = new URLSearchParams(); - const finalOffset = offset != null ? offset : (startRow != null ? startRow : 0); - const finalLimit = limit != null ? limit : (endRow != null && startRow != null ? endRow - startRow : 50); - params.set('offset', String(Math.max(0, Math.floor(Number(finalOffset) || 0)))); - params.set('limit', String(Math.max(1, Math.floor(Number(finalLimit) || 50)))); + params.set('offset', String(Math.max(0, Math.floor(Number(offset) || 0)))); + params.set('limit', String(Math.max(1, Math.floor(Number(limit) || 50)))); if (search && String(search).trim()) params.set('search', String(search).trim()); if (seekMonths != null && Number(seekMonths) < 0) { params.set('seekMonths', String(Math.floor(Number(seekMonths)))); diff --git a/src/api/ledger.js b/src/api/ledger.js index b5bd340..a421c61 100644 --- a/src/api/ledger.js +++ b/src/api/ledger.js @@ -6,16 +6,6 @@ import { http } from './http.js'; * Input = { manifestarticle_id, transaction_type, amount, transaction_text } */ export const ledger = { - /** - * POST /api/ledger - * Body: { manifestarticle_id, transaction_type, amount, transaction_text } - * → 201 { ledger: LedgerEntry } - */ - // #region POST /api/ledger — add - add(body) { - return http('/api/ledger', { method: 'POST', body }); - }, - // #endregion /** * GET /api/ledger/manifestarticle/:manifestarticleId @@ -32,17 +22,15 @@ export const ledger = { /** * GET /api/ledger - * Query: { manifestarticle_id?, sku?, transaction_type? } + * Query: { manifestarticleId?, sku?, transactionType? } * → 200 { ledger: LedgerEntry[] } */ // #region GET /api/ledger — list - list(query) { + list({ manifestarticleId, sku, transactionType } = {}) { const params = new URLSearchParams(); - if (query?.manifestarticle_id != null) params.set('manifestarticle_id', query.manifestarticle_id); - if (query?.manifestarticleId != null) params.set('manifestarticle_id', query.manifestarticleId); - if (query?.sku != null) params.set('sku', query.sku); - if (query?.transaction_type != null) params.set('transaction_type', query.transaction_type); - if (query?.transactionType != null) params.set('transaction_type', query.transactionType); + if (manifestarticleId != null) params.set('manifestarticle_id', String(manifestarticleId)); + if (sku != null) params.set('sku', String(sku)); + if (transactionType != null) params.set('transaction_type', String(transactionType)); const qs = params.toString(); return http(`/api/ledger${qs ? `?${qs}` : ''}`); }, diff --git a/src/api/stock.js b/src/api/stock.js index e43bf81..e08136e 100644 --- a/src/api/stock.js +++ b/src/api/stock.js @@ -13,4 +13,24 @@ export const stock = { return http('/api/stock/adjust', { method: 'POST', body }); }, // #endregion + + /** + * POST /api/stock/accept + * Body: { manifestarticleId, warehouseId?, text? } or { items: [...] } or { deliveryId, warehouseId? } + */ + // #region POST /api/stock/accept — accept + accept(body) { + return http('/api/stock/accept', { method: 'POST', body }); + }, + // #endregion + + /** + * POST /api/stock/ship + * Body: { manifestarticleId, warehouseId?, text? } or { items: [...] } or { shipmentId, warehouseId? } + */ + // #region POST /api/stock/ship — ship + ship(body) { + return http('/api/stock/ship', { method: 'POST', body }); + }, + // #endregion }; diff --git a/src/automats/sseAutomat.js b/src/automats/sseAutomat.js index 2f511ff..5bdbe2d 100644 --- a/src/automats/sseAutomat.js +++ b/src/automats/sseAutomat.js @@ -274,9 +274,9 @@ function connect() { addTrackedListener(es, 'message', () => {}); // EventSource reconnects on its own; only surface the state. - es.onerror = () => { - console.error('[sse] event stream error'); - recordEvent({ type: 'error', data: '', lastEventId: '' }); + es.onerror = (e) => { + console.error('[sse] event stream error', e); + recordEvent(e || { type: 'error', data: '', lastEventId: '' }); sseAutomat.setState({ status: 'error' }); }; diff --git a/src/utils/deliveryLedger.js b/src/utils/deliveryLedger.js index 7a66560..8e9e7a2 100644 --- a/src/utils/deliveryLedger.js +++ b/src/utils/deliveryLedger.js @@ -1,4 +1,4 @@ -import { delivery as defaultDeliveryApi, ledger as defaultLedgerApi } from '../api'; +import { delivery as defaultDeliveryApi, ledger as defaultLedgerApi, stock as defaultStockApi } from '../api'; import artikelAutomat, { getArticle } from '../automats/artikelAutomat'; import articleIndexAutomat from '../automats/articleIndexAutomat'; @@ -92,7 +92,7 @@ export async function fetchDeliveryLedgerSummary(deliveryId, { deliveryApi = def let article = null; const promises = [ - ledgerApi.listByManifestarticleId(line.id, 'DELIVERY').catch((err) => { + ledgerApi.listByManifestarticleId(line.id).catch((err) => { console.error(`[deliveryLedger] Failed to fetch ledger for line ${line.id}:`, err); return null; }), @@ -118,9 +118,10 @@ export async function fetchDeliveryLedgerSummary(deliveryId, { deliveryApi = def const trackStock = isLineStockTracked(line, article); - const deliveryEntries = ledgerEntries.filter( - (e) => String(e.transaction_type).toUpperCase() === 'DELIVERY' - ); + const deliveryEntries = ledgerEntries.filter((e) => { + const t = String(e.transaction_type).toUpperCase(); + return t === 'ACCEPTANCE' || t === 'RETURN' || t === 'DELIVERY'; + }); const bookedAmount = deliveryEntries.reduce((sum, e) => sum + Number(e.amount || 0), 0); const targetAmount = Number(line.amount || 0); const remainingAmount = trackStock ? Math.max(0, targetAmount - bookedAmount) : 0; @@ -171,13 +172,13 @@ export async function fetchDeliveryLedgerSummary(deliveryId, { deliveryApi = def } /** - * Books specified delivery lines to the ledger as goods receipts (DELIVERY). + * Books specified delivery lines to the ledger as goods receipts via /stock/accept. * * @param {Object} params * @param {Object} params.delivery - The delivery object (used for transaction memo and fallback) * @param {Array<{ manifestarticleId?: number, id?: number, amount: number, sku?: string }>} params.linesToBook * @param {number|string} params.warehouseId - Mandatory warehouse ID - * @param {Object} [params.ledgerApi] + * @param {Object} [params.stockApi] * @param {string} [params.transactionText] * @returns {Promise>} */ @@ -185,7 +186,7 @@ export async function bookDeliveryLines({ delivery, linesToBook, warehouseId, - ledgerApi = defaultLedgerApi, + stockApi = defaultStockApi, transactionText, }) { const numericWarehouseId = Number(warehouseId); @@ -203,28 +204,25 @@ export async function bookDeliveryLines({ : `Lieferung ${delivery?.number || delivery?.id || ''}` ).trim(); - const results = []; + const items = linesToBook + .map((item) => ({ + manifestarticleId: Number(item.manifestarticleId ?? item.id), + warehouseId: numericWarehouseId, + text: memo, + })) + .filter((item) => item.manifestarticleId && Number.isInteger(item.manifestarticleId) && item.manifestarticleId > 0); + + if (items.length === 0) { + return []; + } + + const res = await stockApi.accept({ items }); + for (const item of linesToBook) { - const manifestarticleId = Number(item.manifestarticleId ?? item.id); - const amount = Number(item.amount); - - if (!manifestarticleId || !Number.isFinite(amount) || amount <= 0) { - continue; - } - - const res = await ledgerApi.add({ - manifestarticle_id: manifestarticleId, - warehouse_id: numericWarehouseId, - transaction_type: 'DELIVERY', - amount, - transaction_text: memo, - }); - results.push(res?.ledger ?? res); - if (item.sku) { void artikelAutomat.actions.reloadArticle(item.sku).catch(() => {}); } } - return results; + return Array.isArray(res?.accepted) ? res.accepted : (res ? [res] : []); }