cod fix
This commit is contained in:
@@ -560,8 +560,17 @@ export interface OrderRow {
|
|||||||
*/
|
*/
|
||||||
ordervalue?: number;
|
ordervalue?: number;
|
||||||
orderamount?: 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;
|
deliverycharge?: number;
|
||||||
deliveryamt?: number;
|
deliveryamt?: number;
|
||||||
paymenttype?: number;
|
paymenttype?: number;
|
||||||
|
|||||||
@@ -185,19 +185,18 @@ function Sheet({
|
|||||||
label="Value"
|
label="Value"
|
||||||
value={value > 0 ? moneyExact(value) : detailAmount > 0 ? moneyExact(detailAmount) : '—'}
|
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 ? (
|
{job ? (
|
||||||
<Metric
|
<Metric
|
||||||
label="Rider charge"
|
label="Rider charge"
|
||||||
value={job.deliverycharges ? moneyExact(job.deliverycharges) : '—'}
|
value={job.deliverycharges ? moneyExact(job.deliverycharges) : '—'}
|
||||||
isSmall
|
isSmall
|
||||||
/>
|
/>
|
||||||
) : (
|
) : null}
|
||||||
<Metric
|
|
||||||
label="Cash to collect"
|
|
||||||
value={order?.collectionamt ? moneyExact(order.collectionamt) : '—'}
|
|
||||||
isSmall
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{/* Counted from the lines when the row carries no count. `itemcount`
|
{/* Counted from the lines when the row carries no count. `itemcount`
|
||||||
and `quantity` are both routinely absent on the list read, which is
|
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. */}
|
what made this a dash on an order that plainly had something in it. */}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Card } from '@astryxdesign/core/Card';
|
|||||||
import { HStack } from '@astryxdesign/core/HStack';
|
import { HStack } from '@astryxdesign/core/HStack';
|
||||||
import { Text } from '@astryxdesign/core/Text';
|
import { Text } from '@astryxdesign/core/Text';
|
||||||
import { VStack } from '@astryxdesign/core/VStack';
|
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 type { DeliveryRow, OrderRow, PosSale, TenantLocation } from '@/api/types';
|
||||||
import { KpiCard } from '@/components/KpiCard';
|
import { KpiCard } from '@/components/KpiCard';
|
||||||
import { PageHeader } from '@/components/PageHeader';
|
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
|
* - **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
|
* row has a rider name, a planned distance AND an actual one, a rider charge
|
||||||
* AND a job value, and its own status ladder.
|
* 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() {
|
export function SalesPage() {
|
||||||
const { scoped, selected, branches, tenantid } = useBranchScope();
|
const { scoped, selected, branches, tenantid } = useBranchScope();
|
||||||
@@ -279,9 +299,8 @@ export function SalesPage() {
|
|||||||
|
|
||||||
const orderTotals = useMemo(() => {
|
const orderTotals = useMemo(() => {
|
||||||
const value = orderRows.reduce((sum, row) => sum + orderValue(row), 0);
|
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);
|
const qty = orderRows.reduce((sum, row) => sum + orderQuantity(row), 0);
|
||||||
return { value, cod, qty };
|
return { value, qty };
|
||||||
}, [orderRows]);
|
}, [orderRows]);
|
||||||
|
|
||||||
const deliveryTotals = useMemo(() => {
|
const deliveryTotals = useMemo(() => {
|
||||||
@@ -407,13 +426,10 @@ export function SalesPage() {
|
|||||||
tone="accent"
|
tone="accent"
|
||||||
icon={<ShoppingCart size={15} />}
|
icon={<ShoppingCart size={15} />}
|
||||||
/>
|
/>
|
||||||
<KpiCard
|
{/* A "Cash to collect" card stood here. It read `collectionamt`,
|
||||||
label="Cash to collect"
|
which Fiesta does not have, so it showed ₹0 on every order ever
|
||||||
value={money(orderTotals.cod)}
|
listed. See the note at the top of this file for why it cannot
|
||||||
note="COD on these orders"
|
be derived either. */}
|
||||||
tone={orderTotals.cod > 0 ? 'warning' : 'neutral'}
|
|
||||||
icon={<Banknote size={15} />}
|
|
||||||
/>
|
|
||||||
<KpiCard
|
<KpiCard
|
||||||
label="Items"
|
label="Items"
|
||||||
value={count(orderTotals.qty)}
|
value={count(orderTotals.qty)}
|
||||||
@@ -468,9 +484,6 @@ export function SalesPage() {
|
|||||||
<TotalsBar
|
<TotalsBar
|
||||||
label={`${orderRows.length} order${orderRows.length === 1 ? '' : 's'}`}
|
label={`${orderRows.length} order${orderRows.length === 1 ? '' : 's'}`}
|
||||||
chips={[
|
chips={[
|
||||||
...(orderTotals.cod > 0
|
|
||||||
? [{ label: 'COD', value: money(orderTotals.cod), tone: 'warning' as const }]
|
|
||||||
: []),
|
|
||||||
{ label: 'Value', value: money(orderTotals.value), tone: 'accent' as const },
|
{ label: 'Value', value: money(orderTotals.value), tone: 'accent' as const },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@@ -758,7 +771,6 @@ function OrdersTable({
|
|||||||
<Th>Pickup</Th>
|
<Th>Pickup</Th>
|
||||||
<Th>Drop</Th>
|
<Th>Drop</Th>
|
||||||
<Th>Qty</Th>
|
<Th>Qty</Th>
|
||||||
<Th>COD</Th>
|
|
||||||
<Th>Amount</Th>
|
<Th>Amount</Th>
|
||||||
<Th>Status</Th>
|
<Th>Status</Th>
|
||||||
<Th />
|
<Th />
|
||||||
@@ -768,7 +780,6 @@ function OrdersTable({
|
|||||||
{/* Keyed on orderheaderid, never orderid — `orderid` is not unique
|
{/* Keyed on orderheaderid, never orderid — `orderid` is not unique
|
||||||
in this tenant's data, a defect the old console hit first. */}
|
in this tenant's data, a defect the old console hit first. */}
|
||||||
{paged.rows.map((row, index) => {
|
{paged.rows.map((row, index) => {
|
||||||
const cod = row.collectionamt ?? 0;
|
|
||||||
const amount = orderValue(row);
|
const amount = orderValue(row);
|
||||||
const verdict = assignability(row, branchOf(row), assigned, released);
|
const verdict = assignability(row, branchOf(row), assigned, released);
|
||||||
const stage = orderStage(row, stages);
|
const stage = orderStage(row, stages);
|
||||||
@@ -841,11 +852,6 @@ function OrdersTable({
|
|||||||
<Td isMuted>
|
<Td isMuted>
|
||||||
<Mono>{orderQuantity(row) || '—'}</Mono>
|
<Mono>{orderQuantity(row) || '—'}</Mono>
|
||||||
</Td>
|
</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}>
|
<Td isStrong={amount > 0} isMuted={amount === 0}>
|
||||||
<Mono>{amount > 0 ? moneyExact(amount) : '—'}</Mono>
|
<Mono>{amount > 0 ? moneyExact(amount) : '—'}</Mono>
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
Reference in New Issue
Block a user