This commit is contained in:
2026-09-28 19:35:16 +05:30
parent eeef8851e4
commit 9a991fe5ab
3 changed files with 45 additions and 31 deletions

View File

@@ -560,8 +560,17 @@ export interface OrderRow {
*/
ordervalue?: number;
orderamount?: number;
/** Cash to collect on delivery. Shown only when > 0. */
collectionamt?: number;
/*
* `collectionamt` was declared here and read by three screens. It does not
* exist in Fiesta — `grep -rn "collectionamt" --include=*.go` returns nothing
* — so every one of them showed a dash or zero from the day it was written.
* Removed 2026-09-28 along with those screens.
*
* A type can describe a field the server has never sent, and nothing catches
* it: the optional marker makes `undefined` legal, and `?? 0` turns it into a
* plausible figure. That is the trap, and it is worth remembering before the
* next optional money field is added on the strength of a field name.
*/
deliverycharge?: number;
deliveryamt?: number;
paymenttype?: number;

View File

@@ -185,19 +185,18 @@ function Sheet({
label="Value"
value={value > 0 ? moneyExact(value) : detailAmount > 0 ? moneyExact(detailAmount) : '—'}
/>
{/* A delivery shows what the rider is paid. An order has no second
money figure worth the space: "Cash to collect" stood here and read
`collectionamt`, which Fiesta does not have, so it was a dash on
every order ever opened. See `pages/SalesPage.tsx` for why it cannot
be derived from `paymenttype` either. */}
{job ? (
<Metric
label="Rider charge"
value={job.deliverycharges ? moneyExact(job.deliverycharges) : '—'}
isSmall
/>
) : (
<Metric
label="Cash to collect"
value={order?.collectionamt ? moneyExact(order.collectionamt) : '—'}
isSmall
/>
)}
) : null}
{/* Counted from the lines when the row carries no count. `itemcount`
and `quantity` are both routinely absent on the list read, which is
what made this a dash on an order that plainly had something in it. */}

View File

@@ -5,7 +5,7 @@ import { Card } from '@astryxdesign/core/Card';
import { HStack } from '@astryxdesign/core/HStack';
import { Text } from '@astryxdesign/core/Text';
import { VStack } from '@astryxdesign/core/VStack';
import { Banknote, Bike, Calculator, IndianRupee, MapPin, Package, Percent, Receipt, ReceiptText, ShoppingCart, Truck, UserX } from 'lucide-react';
import { Bike, Calculator, IndianRupee, MapPin, Package, Percent, Receipt, ReceiptText, ShoppingCart, Truck, UserX } from 'lucide-react';
import type { DeliveryRow, OrderRow, PosSale, TenantLocation } from '@/api/types';
import { KpiCard } from '@/components/KpiCard';
import { PageHeader } from '@/components/PageHeader';
@@ -89,8 +89,28 @@ function offlineBillNumber(order: OrderRow): string {
* - **Deliveries are their own read.** Not a filter over orders. The delivery
* row has a rider name, a planned distance AND an actual one, a rider charge
* AND a job value, and its own status ladder.
* - **COD only appears when there is cash to collect.** `collectionamt` on
* every row would be a column of dashes.
*
* ── There is no cash-on-delivery figure, and there never was ────────────────
*
* A COD column, a COD total and a "cash to collect" metric were removed on
* 2026-09-28 because nothing could ever fill them. They read `collectionamt`,
* a field that does not exist anywhere in Fiesta — `grep --include=*.go`
* returns nothing — so all three had shown a dash or zero on every order since
* the day they were written.
*
* It cannot be derived either, which was measured rather than assumed: across
* 800 live orders spanning three tenants and two regions, including 247
* delivered ones, `orders.paymenttype` is 42 on every single row, and
* `paymentstatus` is not returned by `getorders` at all. There is no signal in
* the data that separates a cash order from a prepaid one.
*
* (The same measurement shows `getdeliveryinsight`'s `payondelivery` and
* `paylater` aggregates are permanently zero — they key on paymenttype 43 and
* 64, which do not occur.)
*
* Bringing COD back means the customer app recording the payment method and
* Fiesta serving it. Until then a blank column promises a number the system
* has never been able to produce, which reads as broken rather than unbuilt.
*/
export function SalesPage() {
const { scoped, selected, branches, tenantid } = useBranchScope();
@@ -279,9 +299,8 @@ export function SalesPage() {
const orderTotals = useMemo(() => {
const value = orderRows.reduce((sum, row) => sum + orderValue(row), 0);
const cod = orderRows.reduce((sum, row) => sum + (row.collectionamt ?? 0), 0);
const qty = orderRows.reduce((sum, row) => sum + orderQuantity(row), 0);
return { value, cod, qty };
return { value, qty };
}, [orderRows]);
const deliveryTotals = useMemo(() => {
@@ -407,13 +426,10 @@ export function SalesPage() {
tone="accent"
icon={<ShoppingCart size={15} />}
/>
<KpiCard
label="Cash to collect"
value={money(orderTotals.cod)}
note="COD on these orders"
tone={orderTotals.cod > 0 ? 'warning' : 'neutral'}
icon={<Banknote size={15} />}
/>
{/* A "Cash to collect" card stood here. It read `collectionamt`,
which Fiesta does not have, so it showed ₹0 on every order ever
listed. See the note at the top of this file for why it cannot
be derived either. */}
<KpiCard
label="Items"
value={count(orderTotals.qty)}
@@ -468,9 +484,6 @@ export function SalesPage() {
<TotalsBar
label={`${orderRows.length} order${orderRows.length === 1 ? '' : 's'}`}
chips={[
...(orderTotals.cod > 0
? [{ label: 'COD', value: money(orderTotals.cod), tone: 'warning' as const }]
: []),
{ label: 'Value', value: money(orderTotals.value), tone: 'accent' as const },
]}
/>
@@ -758,7 +771,6 @@ function OrdersTable({
<Th>Pickup</Th>
<Th>Drop</Th>
<Th>Qty</Th>
<Th>COD</Th>
<Th>Amount</Th>
<Th>Status</Th>
<Th />
@@ -768,7 +780,6 @@ function OrdersTable({
{/* Keyed on orderheaderid, never orderid — `orderid` is not unique
in this tenant's data, a defect the old console hit first. */}
{paged.rows.map((row, index) => {
const cod = row.collectionamt ?? 0;
const amount = orderValue(row);
const verdict = assignability(row, branchOf(row), assigned, released);
const stage = orderStage(row, stages);
@@ -841,11 +852,6 @@ function OrdersTable({
<Td isMuted>
<Mono>{orderQuantity(row) || '—'}</Mono>
</Td>
{/* Only rendered when there is cash to collect — a COD column
of dashes is a column that costs width and says nothing. */}
<Td isStrong={cod > 0} isMuted={cod === 0}>
<Mono>{cod > 0 ? moneyExact(cod) : '—'}</Mono>
</Td>
<Td isStrong={amount > 0} isMuted={amount === 0}>
<Mono>{amount > 0 ? moneyExact(amount) : '—'}</Mono>
</Td>