From 04789ea9a1d012de2201eba0ee4476dc87a93ee7 Mon Sep 17 00:00:00 2001 From: fahed Date: Tue, 31 Mar 2026 14:41:51 +0300 Subject: [PATCH] fix: B2C visitor count uses UnitQuantity (1 ticket = 1 visitor) B2C generates one PDF ticket per person, so UnitQuantity = visitors. Other channels (POS, Safiyyah POS, etc.) use PeopleCount for visitors since group tickets cover multiple people. Co-Authored-By: Claude Opus 4.6 (1M context) --- server/src/services/etlSync.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/services/etlSync.ts b/server/src/services/etlSync.ts index 95d9404..4be56d2 100644 --- a/server/src/services/etlSync.ts +++ b/server/src/services/etlSync.ts @@ -40,7 +40,11 @@ export function aggregateTransactions(sales: ERPSaleRecord[]): AggregatedRecord[ for (const sale of sales) { const date = sale.TransactionDate.split(' ')[0]; - const channel = getChannelLabel(sale.OperatingAreaName); + const rawChannel = sale.OperatingAreaName; + const channel = getChannelLabel(rawChannel); + // B2C: each ticket = one visitor (1 PDF per person) + // Other channels: PeopleCount = actual visitors (group tickets) + const isB2C = rawChannel === 'B2C'; for (const product of sale.Products) { const { museums, split } = getMuseumsFromProduct(product.ProductDescription); @@ -72,7 +76,8 @@ export function aggregateTransactions(sales: ERPSaleRecord[]): AggregatedRecord[ map.set(key, entry); } - entry.Visits += product.PeopleCount * split; + const visitors = isB2C ? product.UnitQuantity : product.PeopleCount; + entry.Visits += visitors * split; entry.Tickets += product.UnitQuantity * split; entry.GrossRevenue += product.TotalPrice * split; entry.NetRevenue += (product.TotalPrice - product.TaxAmount) * split;