u
This commit is contained in:
@@ -30,15 +30,14 @@ export const article = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/article/history?offset=0&limit=50&search=...&seekMonths=-1
|
* 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 }
|
* → { 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 params = new URLSearchParams();
|
||||||
const finalOffset = offset != null ? offset : (startRow != null ? startRow : 0);
|
params.set('offset', String(Math.max(0, Math.floor(Number(offset) || 0))));
|
||||||
const finalLimit = limit != null ? limit : (endRow != null && startRow != null ? endRow - startRow : 50);
|
params.set('limit', String(Math.max(1, Math.floor(Number(limit) || 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))));
|
|
||||||
if (search && String(search).trim()) params.set('search', String(search).trim());
|
if (search && String(search).trim()) params.set('search', String(search).trim());
|
||||||
if (seekMonths != null && Number(seekMonths) < 0) {
|
if (seekMonths != null && Number(seekMonths) < 0) {
|
||||||
params.set('seekMonths', String(Math.floor(Number(seekMonths))));
|
params.set('seekMonths', String(Math.floor(Number(seekMonths))));
|
||||||
@@ -48,6 +47,7 @@ export const article = {
|
|||||||
const qs = params.toString();
|
const qs = params.toString();
|
||||||
return http(`/api/article/history${qs ? `?${qs}` : ''}`);
|
return http(`/api/article/history${qs ? `?${qs}` : ''}`);
|
||||||
},
|
},
|
||||||
|
// #endregion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/article/:sku/history
|
* GET /api/article/:sku/history
|
||||||
|
|||||||
@@ -4,16 +4,14 @@ export const globalHistory = {
|
|||||||
/**
|
/**
|
||||||
* GET /api/history?offset=0&limit=50&search=...&seekMonths=-1
|
* GET /api/history?offset=0&limit=50&search=...&seekMonths=-1
|
||||||
* Global system/entity history with chunk paging and search/seek filtering
|
* 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 }
|
* → { history: GlobalHistoryEntry[], total: number, unfilteredTotal?: number }
|
||||||
*/
|
*/
|
||||||
// #region GET /api/history — list
|
// #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 params = new URLSearchParams();
|
||||||
const finalOffset = offset != null ? offset : (startRow != null ? startRow : 0);
|
params.set('offset', String(Math.max(0, Math.floor(Number(offset) || 0))));
|
||||||
const finalLimit = limit != null ? limit : (endRow != null && startRow != null ? endRow - startRow : 50);
|
params.set('limit', String(Math.max(1, Math.floor(Number(limit) || 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))));
|
|
||||||
if (search && String(search).trim()) params.set('search', String(search).trim());
|
if (search && String(search).trim()) params.set('search', String(search).trim());
|
||||||
if (seekMonths != null && Number(seekMonths) < 0) {
|
if (seekMonths != null && Number(seekMonths) < 0) {
|
||||||
params.set('seekMonths', String(Math.floor(Number(seekMonths))));
|
params.set('seekMonths', String(Math.floor(Number(seekMonths))));
|
||||||
|
|||||||
@@ -6,16 +6,6 @@ import { http } from './http.js';
|
|||||||
* Input = { manifestarticle_id, transaction_type, amount, transaction_text }
|
* Input = { manifestarticle_id, transaction_type, amount, transaction_text }
|
||||||
*/
|
*/
|
||||||
export const ledger = {
|
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
|
* GET /api/ledger/manifestarticle/:manifestarticleId
|
||||||
@@ -32,17 +22,15 @@ export const ledger = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/ledger
|
* GET /api/ledger
|
||||||
* Query: { manifestarticle_id?, sku?, transaction_type? }
|
* Query: { manifestarticleId?, sku?, transactionType? }
|
||||||
* → 200 { ledger: LedgerEntry[] }
|
* → 200 { ledger: LedgerEntry[] }
|
||||||
*/
|
*/
|
||||||
// #region GET /api/ledger — list
|
// #region GET /api/ledger — list
|
||||||
list(query) {
|
list({ manifestarticleId, sku, transactionType } = {}) {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (query?.manifestarticle_id != null) params.set('manifestarticle_id', query.manifestarticle_id);
|
if (manifestarticleId != null) params.set('manifestarticle_id', String(manifestarticleId));
|
||||||
if (query?.manifestarticleId != null) params.set('manifestarticle_id', query.manifestarticleId);
|
if (sku != null) params.set('sku', String(sku));
|
||||||
if (query?.sku != null) params.set('sku', query.sku);
|
if (transactionType != null) params.set('transaction_type', String(transactionType));
|
||||||
if (query?.transaction_type != null) params.set('transaction_type', query.transaction_type);
|
|
||||||
if (query?.transactionType != null) params.set('transaction_type', query.transactionType);
|
|
||||||
const qs = params.toString();
|
const qs = params.toString();
|
||||||
return http(`/api/ledger${qs ? `?${qs}` : ''}`);
|
return http(`/api/ledger${qs ? `?${qs}` : ''}`);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,4 +13,24 @@ export const stock = {
|
|||||||
return http('/api/stock/adjust', { method: 'POST', body });
|
return http('/api/stock/adjust', { method: 'POST', body });
|
||||||
},
|
},
|
||||||
// #endregion
|
// #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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -274,9 +274,9 @@ function connect() {
|
|||||||
addTrackedListener(es, 'message', () => {});
|
addTrackedListener(es, 'message', () => {});
|
||||||
|
|
||||||
// EventSource reconnects on its own; only surface the state.
|
// EventSource reconnects on its own; only surface the state.
|
||||||
es.onerror = () => {
|
es.onerror = (e) => {
|
||||||
console.error('[sse] event stream error');
|
console.error('[sse] event stream error', e);
|
||||||
recordEvent({ type: 'error', data: '', lastEventId: '' });
|
recordEvent(e || { type: 'error', data: '', lastEventId: '' });
|
||||||
sseAutomat.setState({ status: 'error' });
|
sseAutomat.setState({ status: 'error' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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 artikelAutomat, { getArticle } from '../automats/artikelAutomat';
|
||||||
import articleIndexAutomat from '../automats/articleIndexAutomat';
|
import articleIndexAutomat from '../automats/articleIndexAutomat';
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ export async function fetchDeliveryLedgerSummary(deliveryId, { deliveryApi = def
|
|||||||
let article = null;
|
let article = null;
|
||||||
|
|
||||||
const promises = [
|
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);
|
console.error(`[deliveryLedger] Failed to fetch ledger for line ${line.id}:`, err);
|
||||||
return null;
|
return null;
|
||||||
}),
|
}),
|
||||||
@@ -118,9 +118,10 @@ export async function fetchDeliveryLedgerSummary(deliveryId, { deliveryApi = def
|
|||||||
|
|
||||||
const trackStock = isLineStockTracked(line, article);
|
const trackStock = isLineStockTracked(line, article);
|
||||||
|
|
||||||
const deliveryEntries = ledgerEntries.filter(
|
const deliveryEntries = ledgerEntries.filter((e) => {
|
||||||
(e) => String(e.transaction_type).toUpperCase() === 'DELIVERY'
|
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 bookedAmount = deliveryEntries.reduce((sum, e) => sum + Number(e.amount || 0), 0);
|
||||||
const targetAmount = Number(line.amount || 0);
|
const targetAmount = Number(line.amount || 0);
|
||||||
const remainingAmount = trackStock ? Math.max(0, targetAmount - bookedAmount) : 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
|
||||||
* @param {Object} params.delivery - The delivery object (used for transaction memo and fallback)
|
* @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 {Array<{ manifestarticleId?: number, id?: number, amount: number, sku?: string }>} params.linesToBook
|
||||||
* @param {number|string} params.warehouseId - Mandatory warehouse ID
|
* @param {number|string} params.warehouseId - Mandatory warehouse ID
|
||||||
* @param {Object} [params.ledgerApi]
|
* @param {Object} [params.stockApi]
|
||||||
* @param {string} [params.transactionText]
|
* @param {string} [params.transactionText]
|
||||||
* @returns {Promise<Array<Object>>}
|
* @returns {Promise<Array<Object>>}
|
||||||
*/
|
*/
|
||||||
@@ -185,7 +186,7 @@ export async function bookDeliveryLines({
|
|||||||
delivery,
|
delivery,
|
||||||
linesToBook,
|
linesToBook,
|
||||||
warehouseId,
|
warehouseId,
|
||||||
ledgerApi = defaultLedgerApi,
|
stockApi = defaultStockApi,
|
||||||
transactionText,
|
transactionText,
|
||||||
}) {
|
}) {
|
||||||
const numericWarehouseId = Number(warehouseId);
|
const numericWarehouseId = Number(warehouseId);
|
||||||
@@ -203,28 +204,25 @@ export async function bookDeliveryLines({
|
|||||||
: `Lieferung ${delivery?.number || delivery?.id || ''}`
|
: `Lieferung ${delivery?.number || delivery?.id || ''}`
|
||||||
).trim();
|
).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) {
|
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) {
|
if (item.sku) {
|
||||||
void artikelAutomat.actions.reloadArticle(item.sku).catch(() => {});
|
void artikelAutomat.actions.reloadArticle(item.sku).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return Array.isArray(res?.accepted) ? res.accepted : (res ? [res] : []);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user