From 8ee080b744fddc2ff15d61b71b65e3d717429f14 Mon Sep 17 00:00:00 2001 From: seb Date: Sat, 17 Oct 2026 00:52:45 +0200 Subject: [PATCH] u --- src/providers/mssql/queries/delivery.js | 32 ++++----- src/store/delivery/helpers.js | 61 ++++++++++++---- src/store/delivery/list.js | 22 ------ src/store/delivery/syncSummary.js | 96 +++++++++++++++++++------ 4 files changed, 132 insertions(+), 79 deletions(-) diff --git a/src/providers/mssql/queries/delivery.js b/src/providers/mssql/queries/delivery.js index 105fd72..b1f8aaa 100644 --- a/src/providers/mssql/queries/delivery.js +++ b/src/providers/mssql/queries/delivery.js @@ -43,29 +43,23 @@ SELECT m.external_number AS externalNumber, m.[date], m.created_at AS createdAt, - COUNT(ma.id) AS totalPositions, - COUNT(CASE WHEN ma.id IS NOT NULL AND ( - (ma.amount > 0 AND COALESCE(ma_ledger.booked_amount, 0) >= ma.amount) OR - (ma.amount <= 0 AND COALESCE(ma_ledger.booked_amount, 0) > 0) - ) THEN 1 END) AS completelyOnLedgerPositions + ds.positions, + ds.gross_total AS grossTotal, + ds.net_total AS netTotal, + ds.total_quantity AS totalQuantity, + ds.stock_positions AS stockPositions, + ds.booked_positions AS bookedPositions, + ds.unbooked_positions AS unbookedPositions, + ds.stock_quantity AS stockQuantity, + ds.booked_quantity AS bookedQuantity, + ds.unbooked_quantity AS unbookedQuantity, + ds.is_booked AS isBooked, + ds.supplier_name AS supplierName FROM manifest m -LEFT JOIN manifestarticle ma ON ma.manifest_id = m.id -LEFT JOIN ( - SELECT manifestarticle_id, SUM(amount) AS booked_amount - FROM ledger - GROUP BY manifestarticle_id -) ma_ledger ON ma_ledger.manifestarticle_id = ma.id +LEFT JOIN deliverysummary ds ON ds.manifest_id = m.id WHERE m.id = @id AND m.company_id = @companyId AND m.[type] = @type -GROUP BY - m.id, - m.[number], - m.[type], - m.entity_id, - m.external_number, - m.[date], - m.created_at `; export const GET_DELIVERY_LINES = ` diff --git a/src/store/delivery/helpers.js b/src/store/delivery/helpers.js index 5fcb578..65bdf41 100644 --- a/src/store/delivery/helpers.js +++ b/src/store/delivery/helpers.js @@ -3,33 +3,54 @@ import * as sqliteQueries from '../../providers/sqlite3/queries/delivery.js'; import makeRunner from '../runner.js'; import { shapeLine } from '../manifestLines.js'; import { loadAttachments } from './attachments.js'; +import { syncDeliverySummary } from './syncSummary.js'; export const DELIVERY_TYPE = mssqlQueries.DELIVERY_TYPE; export function shapeSummary(row) { + const stockPositions = Number(row.stockPositions ?? 0); + const totalPositions = Number(row.stockPositions ?? row.totalPositions ?? row.positions ?? 0); + const bookedPositions = Number(row.bookedPositions ?? row.completelyOnLedgerPositions ?? 0); + const unbookedPositions = Number(row.unbookedPositions ?? Math.max(0, totalPositions - bookedPositions)); + + const totalQuantity = Number(row.totalQuantity ?? row.stockQuantity ?? 0); + const stockQuantity = Number(row.stockQuantity ?? 0); + const bookedQuantity = Number(row.bookedQuantity ?? 0); + const unbookedQuantity = Number(row.unbookedQuantity ?? Math.max(0, (stockQuantity || totalQuantity) - bookedQuantity)); + const isBooked = row.isBooked !== undefined && row.isBooked !== null + ? Boolean(row.isBooked) + : (totalPositions > 0 && bookedPositions >= totalPositions); + const summary = { id: row.id, number: row.number, type: DELIVERY_TYPE, supplierId: row.supplierId ?? null, + supplierName: row.supplierName ?? undefined, externalNumber: row.externalNumber ?? null, date: row.date, createdAt: row.createdAt ?? row.created_at ?? null, - }; - - const totalPositions = Number(row.stockPositions ?? row.totalPositions ?? row.positions ?? 0); - const bookedPositions = Number(row.completelyOnLedgerPositions ?? row.bookedPositions ?? 0); - const unbookedPositions = Number(row.unbookedPositions ?? Math.max(0, totalPositions - bookedPositions)); - - summary.ledger = { - totalPositions, - completelyOnLedgerPositions: bookedPositions, + positions: Number(row.positions ?? totalPositions), + grossTotal: row.grossTotal !== undefined && row.grossTotal !== null ? Number(row.grossTotal) : 0, + netTotal: row.netTotal !== undefined && row.netTotal !== null ? Number(row.netTotal) : 0, + totalQuantity, + stockPositions, bookedPositions, unbookedPositions, - totalQuantity: Number(row.stockQuantity ?? row.totalQuantity ?? 0), - bookedQuantity: Number(row.bookedQuantity ?? 0), - unbookedQuantity: Number(row.unbookedQuantity ?? 0), - isBooked: row.isBooked !== undefined ? Boolean(row.isBooked) : (totalPositions > 0 && bookedPositions >= totalPositions), + stockQuantity, + bookedQuantity, + unbookedQuantity, + isBooked, + ledger: { + totalPositions, + completelyOnLedgerPositions: bookedPositions, + bookedPositions, + unbookedPositions, + totalQuantity: stockQuantity || totalQuantity, + bookedQuantity, + unbookedQuantity, + isBooked, + }, }; return summary; @@ -40,17 +61,27 @@ export async function loadDelivery(provider, tx, companyId, id) { const isSqlite = provider?.dialect === 'sqlite3'; const queries = isSqlite ? sqliteQueries : mssqlQueries; - const header = await runner(queries.GET_DELIVERY_HEADER, { + let header = await runner(queries.GET_DELIVERY_HEADER, { id, companyId, type: DELIVERY_TYPE, }); - const row = header.rows[0]; + let row = header.rows[0]; if (!row) { return null; } + if (row.positions === null || row.positions === undefined) { + await syncDeliverySummary(runner, { companyId, manifestId: id }); + header = await runner(queries.GET_DELIVERY_HEADER, { + id, + companyId, + type: DELIVERY_TYPE, + }); + row = header.rows[0]; + } + const lines = await runner(queries.GET_DELIVERY_LINES, { manifestId: id, }); diff --git a/src/store/delivery/list.js b/src/store/delivery/list.js index 70200ae..20c56ec 100644 --- a/src/store/delivery/list.js +++ b/src/store/delivery/list.js @@ -286,28 +286,6 @@ export default function list(provider) { const deliveries = manifestRows.map((row) => ({ ...shapeSummary(row), - positions: row.positions !== undefined && row.positions !== null ? Number(row.positions) : 0, - grossTotal: row.grossTotal !== undefined && row.grossTotal !== null ? Number(row.grossTotal) : 0, - netTotal: row.netTotal !== undefined && row.netTotal !== null ? Number(row.netTotal) : 0, - totalQuantity: row.totalQuantity !== undefined && row.totalQuantity !== null ? Number(row.totalQuantity) : 0, - stockPositions: row.stockPositions !== undefined && row.stockPositions !== null ? Number(row.stockPositions) : 0, - bookedPositions: row.bookedPositions !== undefined && row.bookedPositions !== null ? Number(row.bookedPositions) : 0, - unbookedPositions: row.unbookedPositions !== undefined && row.unbookedPositions !== null ? Number(row.unbookedPositions) : 0, - stockQuantity: row.stockQuantity !== undefined && row.stockQuantity !== null ? Number(row.stockQuantity) : 0, - bookedQuantity: row.bookedQuantity !== undefined && row.bookedQuantity !== null ? Number(row.bookedQuantity) : 0, - unbookedQuantity: row.unbookedQuantity !== undefined && row.unbookedQuantity !== null ? Number(row.unbookedQuantity) : 0, - isBooked: row.isBooked !== undefined && row.isBooked !== null ? Boolean(row.isBooked) : false, - supplierName: row.supplierName ?? undefined, - ledger: { - totalPositions: Number(row.stockPositions ?? row.totalPositions ?? 0), - completelyOnLedgerPositions: Number(row.bookedPositions ?? row.completelyOnLedgerPositions ?? 0), - bookedPositions: Number(row.bookedPositions ?? 0), - unbookedPositions: Number(row.unbookedPositions ?? 0), - totalQuantity: Number(row.stockQuantity ?? 0), - bookedQuantity: Number(row.bookedQuantity ?? 0), - unbookedQuantity: Number(row.unbookedQuantity ?? 0), - isBooked: Boolean(row.isBooked), - }, files: filesByManifest.get(row.id) ?? [], })); diff --git a/src/store/delivery/syncSummary.js b/src/store/delivery/syncSummary.js index 52c9573..624fbb1 100644 --- a/src/store/delivery/syncSummary.js +++ b/src/store/delivery/syncSummary.js @@ -70,9 +70,11 @@ const SQL_DELIVERY_TOTALS_SQLITE = ` COALESCE(SUM(line_net), 0) AS net_total, COALESCE(SUM(amount), 0) AS total_quantity, COALESCE(SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END), 0) AS stock_positions, - COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS booked_positions, + COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS stock_booked_positions, COALESCE(SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END), 0) AS stock_quantity, - COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS booked_quantity + COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS stock_booked_quantity, + COALESCE(SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS all_booked_positions, + COALESCE(SUM(booked_amount), 0) AS all_booked_quantity FROM line_data `; @@ -105,9 +107,11 @@ const SQL_DELIVERY_TOTALS_MSSQL = ` COALESCE(SUM(line_net), 0) AS net_total, COALESCE(SUM(amount), 0) AS total_quantity, COALESCE(SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END), 0) AS stock_positions, - COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS booked_positions, + COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS stock_booked_positions, COALESCE(SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END), 0) AS stock_quantity, - COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS booked_quantity + COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS stock_booked_quantity, + COALESCE(SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS all_booked_positions, + COALESCE(SUM(booked_amount), 0) AS all_booked_quantity FROM line_data `; @@ -237,12 +241,22 @@ export async function syncDeliverySummary(runner, { companyId, manifestId, deliv const netTotal = Math.round(Number(totals.net_total || 0) * 100) / 100; const totalQuantity = Math.round(Number(totals.total_quantity || 0) * 1000) / 1000; const stockPositions = Number(totals.stock_positions || 0); - const bookedPositions = Number(totals.booked_positions || 0); - const unbookedPositions = Math.max(0, stockPositions - bookedPositions); + + const hasStockPositions = stockPositions > 0; + const bookedPositions = hasStockPositions + ? Number(totals.stock_booked_positions || 0) + : Number(totals.all_booked_positions || 0); + const targetPositions = hasStockPositions ? stockPositions : positions; + const unbookedPositions = Math.max(0, targetPositions - bookedPositions); + const stockQuantity = Math.round(Number(totals.stock_quantity || 0) * 1000) / 1000; - const bookedQuantity = Math.round(Number(totals.booked_quantity || 0) * 1000) / 1000; - const unbookedQuantity = Math.round(Math.max(0, stockQuantity - bookedQuantity) * 1000) / 1000; - const isBooked = stockPositions > 0 && bookedPositions >= stockPositions ? 1 : 0; + const bookedQuantity = hasStockPositions + ? Math.round(Number(totals.stock_booked_quantity || 0) * 1000) / 1000 + : Math.round(Number(totals.all_booked_quantity || 0) * 1000) / 1000; + const targetQuantity = hasStockPositions ? stockQuantity : totalQuantity; + const unbookedQuantity = Math.round(Math.max(0, targetQuantity - bookedQuantity) * 1000) / 1000; + + const isBooked = targetPositions > 0 && bookedPositions >= targetPositions ? 1 : 0; await runner.query(isSqlite ? SQL_UPSERT_SUMMARY_SQLITE : SQL_UPSERT_SUMMARY_MSSQL, { companyId, @@ -311,9 +325,11 @@ export async function rebuildDeliverySummaries(runner, companyId) { SUM(line_net) AS net_total, SUM(amount) AS total_quantity, SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END) AS stock_positions, - SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS booked_positions, + SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS stock_booked_positions, SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END) AS stock_quantity, - SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS booked_quantity + SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS stock_booked_quantity, + SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS all_booked_positions, + SUM(booked_amount) AS all_booked_quantity FROM line_data GROUP BY manifest_id ) @@ -337,12 +353,28 @@ export async function rebuildDeliverySummaries(runner, companyId) { ROUND(COALESCE(da.net_total, 0), 2) AS net_total, ROUND(COALESCE(da.total_quantity, 0), 3) AS total_quantity, COALESCE(da.stock_positions, 0) AS stock_positions, - COALESCE(da.booked_positions, 0) AS booked_positions, - MAX(0, COALESCE(da.stock_positions, 0) - COALESCE(da.booked_positions, 0)) AS unbooked_positions, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN COALESCE(da.stock_booked_positions, 0) + ELSE COALESCE(da.all_booked_positions, 0) + END AS booked_positions, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN MAX(0, COALESCE(da.stock_positions, 0) - COALESCE(da.stock_booked_positions, 0)) + ELSE MAX(0, COALESCE(da.positions, 0) - COALESCE(da.all_booked_positions, 0)) + END AS unbooked_positions, ROUND(COALESCE(da.stock_quantity, 0), 3) AS stock_quantity, - ROUND(COALESCE(da.booked_quantity, 0), 3) AS booked_quantity, - ROUND(MAX(0, COALESCE(da.stock_quantity, 0) - COALESCE(da.booked_quantity, 0)), 3) AS unbooked_quantity, - CASE WHEN COALESCE(da.stock_positions, 0) > 0 AND COALESCE(da.booked_positions, 0) >= COALESCE(da.stock_positions, 0) THEN 1 ELSE 0 END AS is_booked + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN ROUND(COALESCE(da.stock_booked_quantity, 0), 3) + ELSE ROUND(COALESCE(da.all_booked_quantity, 0), 3) + END AS booked_quantity, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN ROUND(MAX(0, COALESCE(da.stock_quantity, 0) - COALESCE(da.stock_booked_quantity, 0)), 3) + ELSE ROUND(MAX(0, COALESCE(da.total_quantity, 0) - COALESCE(da.all_booked_quantity, 0)), 3) + END AS unbooked_quantity, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 AND COALESCE(da.stock_booked_positions, 0) >= COALESCE(da.stock_positions, 0) THEN 1 + WHEN COALESCE(da.stock_positions, 0) = 0 AND COALESCE(da.positions, 0) > 0 AND COALESCE(da.all_booked_positions, 0) >= COALESCE(da.positions, 0) THEN 1 + ELSE 0 + END AS is_booked FROM manifest m LEFT JOIN entity e ON e.id = m.entity_id LEFT JOIN delivery_agg da ON da.manifest_id = m.id @@ -403,9 +435,11 @@ export async function rebuildDeliverySummaries(runner, companyId) { SUM(line_net) AS net_total, SUM(amount) AS total_quantity, SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END) AS stock_positions, - SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS booked_positions, + SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS stock_booked_positions, SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END) AS stock_quantity, - SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS booked_quantity + SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS stock_booked_quantity, + SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS all_booked_positions, + SUM(booked_amount) AS all_booked_quantity FROM line_data GROUP BY manifest_id ) @@ -429,12 +463,28 @@ export async function rebuildDeliverySummaries(runner, companyId) { ROUND(COALESCE(da.net_total, 0), 2) AS net_total, ROUND(COALESCE(da.total_quantity, 0), 3) AS total_quantity, COALESCE(da.stock_positions, 0) AS stock_positions, - COALESCE(da.booked_positions, 0) AS booked_positions, - CASE WHEN COALESCE(da.stock_positions, 0) > COALESCE(da.booked_positions, 0) THEN COALESCE(da.stock_positions, 0) - COALESCE(da.booked_positions, 0) ELSE 0 END AS unbooked_positions, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN COALESCE(da.stock_booked_positions, 0) + ELSE COALESCE(da.all_booked_positions, 0) + END AS booked_positions, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN CASE WHEN COALESCE(da.stock_positions, 0) > COALESCE(da.stock_booked_positions, 0) THEN COALESCE(da.stock_positions, 0) - COALESCE(da.stock_booked_positions, 0) ELSE 0 END + ELSE CASE WHEN COALESCE(da.positions, 0) > COALESCE(da.all_booked_positions, 0) THEN COALESCE(da.positions, 0) - COALESCE(da.all_booked_positions, 0) ELSE 0 END + END AS unbooked_positions, ROUND(COALESCE(da.stock_quantity, 0), 3) AS stock_quantity, - ROUND(COALESCE(da.booked_quantity, 0), 3) AS booked_quantity, - ROUND(CASE WHEN COALESCE(da.stock_quantity, 0) > COALESCE(da.booked_quantity, 0) THEN COALESCE(da.stock_quantity, 0) - COALESCE(da.booked_quantity, 0) ELSE 0 END, 3) AS unbooked_quantity, - CASE WHEN COALESCE(da.stock_positions, 0) > 0 AND COALESCE(da.booked_positions, 0) >= COALESCE(da.stock_positions, 0) THEN 1 ELSE 0 END AS is_booked + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN ROUND(COALESCE(da.stock_booked_quantity, 0), 3) + ELSE ROUND(COALESCE(da.all_booked_quantity, 0), 3) + END AS booked_quantity, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 THEN ROUND(CASE WHEN COALESCE(da.stock_quantity, 0) > COALESCE(da.stock_booked_quantity, 0) THEN COALESCE(da.stock_quantity, 0) - COALESCE(da.stock_booked_quantity, 0) ELSE 0 END, 3) + ELSE ROUND(CASE WHEN COALESCE(da.total_quantity, 0) > COALESCE(da.all_booked_quantity, 0) THEN COALESCE(da.total_quantity, 0) - COALESCE(da.all_booked_quantity, 0) ELSE 0 END, 3) + END AS unbooked_quantity, + CASE + WHEN COALESCE(da.stock_positions, 0) > 0 AND COALESCE(da.stock_booked_positions, 0) >= COALESCE(da.stock_positions, 0) THEN 1 + WHEN COALESCE(da.stock_positions, 0) = 0 AND COALESCE(da.positions, 0) > 0 AND COALESCE(da.all_booked_positions, 0) >= COALESCE(da.positions, 0) THEN 1 + ELSE 0 + END AS is_booked FROM manifest m LEFT JOIN entity e ON e.id = m.entity_id LEFT JOIN delivery_agg da ON da.manifest_id = m.id