Subversion Repositories SmartDukaan

Rev

Show changed files | Details | Compare with Previous | Blame | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
37846 1 d 10 h amit /trunk/profitmandi-fofo/src/main/ feat(warehouse): dashboards list ACTIVE warehouses only, warehouse-team screens ACTIVE+SUSPENDED (from BillingWarehouseService, WAREHOUSE_MAP gone); global $warehouseNames for labels of data rows in any state; Sellers & Warehouses screen: all-warehouse overview with status tabs, 3-state status, rename, stock/unshipped orders/stores/mapping usage, send stock alert; partner zone offers active warehouses only; brand stock 'All' = active warehouses (replaces r37838 loop); jsVersion 442  
37823 5 d 8 h amit /trunk/profitmandi-fofo/src/main/ feat(seller): rebuild Sellers & Warehouses screen; PO supplier filter by warehouse; internal warehouse from active sellerwarehouse

Needs dao r37822 and the warehouseaddressmaster.active migration (applied on hadb1).

- Sellers & Warehouses (menu 113): SellerController is now a thin layer over
WarehouseSetupService. Seller list; per-seller physical warehouses with internal
store / supplier / Dummy / sequences, Active toggle and Change address (internal
stores follow); address list with Active toggle; New Address with city, pin,
contact and invoice preview; New Seller with GSTIN checks; New Warehouse creates
the OURS/BAD vendor 40 + Dummy shape. JSON posts; refusals come back as 400 text.
- PO create screen: vendor search takes the selected warehouse and lists only
suppliers mapped to it (/vendors?warehouseId); changing warehouse clears the vendor.
- Supplier create/edit: internal warehouse defaults to 0 and is picked from active
physical warehouses (transaction.sellerwarehouse.is_active), not WAREHOUSE_MAP;
validated on save. Fixes the edit form ticking "Internal Warehouse" for a stored 0
and saving the first option (7720), and the create form never sending it.
- jsVersion 441.
 
37818 6 d 12 h amit /trunk/profitmandi-fofo/src/ feat(movement): allow full movable qty on PO screen, split raised as separate POs

- Cap the movement quantity at everything that can move; stock at more than one cost is
raised as one PO per cost on create (dao r37817). Note replaces 'raise a separate PO'.
- Tests: split by cost, multi-item PO grouping, same-warehouse refusal, shelf before arriving.
- jsVersion 440.
 
37791 8 d 14 h amit /trunk/profitmandi-fofo/src/main/ Sale returns: Finance-only B2C settlement after a NIC GSTIN refusal

Once NIC has refused a return because the buyer's GSTIN is cancelled or
invalid, only Finance may act on it - approve, retry or reject. The pending
queue shows the refusal reason and, on the day it happened, a "Refund as
B2C" action; Logistics sees "IRN failed - awaiting Finance" and no buttons.

The B2C screen states NIC's reason and every returned line with its value
including and excluding GST, and fixes the refund at the value net of GST
in whole rupees. Finance types that figure back by hand, enters a remark and
ticks the consent box before the button enables; the server re-checks the
amount, the remark, the consent and the same-day window, so the screen is a
convenience and not the control. Cancelling or finishing returns to the
queue, and a refused approval now reloads the queue so the B2C action
appears without a manual refresh.

jsVersion 438 -> 439 for return.js.
 
37786 11 d 11 h amit /trunk/profitmandi-fofo/src/main/ fix(po): read PO lines only from the PO items table

Create PO collected rows from every table on the page ($("table > tbody > tr")). The aging-SKU
approval modal added in r37750 has its own table (#pmscpFlaggedRows); after a flagged attempt was
abandoned, its rows were sent as lines with itemId 0 and the server rejected the PO with
"Items are duplicate [0]". The create, add-row and over-cap loops now read #purchase-order-table only.
Bump JS version to 438.
 
37780 11 d 15 h amit /trunk/profitmandi-fofo/src/ feat(partner-access): demo partner access page + validation

- Demo Partner Access page (Admin Control): grant partners to a Sales person,
list and revoke active grants; server-guarded by canManage
- Partner access dropdown: position partners + active demo partners "(Demo)";
shared cached mapping is copied, never mutated
- /login-as-partner-readonly: partner must be in caller's positions or demo
grants (was unchecked; Partner access is its only caller)
- /mobileapp?emailId=: Sales position holders get the partner app token only
for position/demo partners; other admins (Partner Info) unchanged
- DemoPartnerAccessTest (5, local DB, rolled back)
- jsVersion 437

Needs dao r37779 and migration_demo_partner_access.sql applied.
 
37774 12 d 9 h amit /trunk/profitmandi-fofo/src/main/ feat: show sanction request investment numbers as whole rupees

Adds a global $nf0 Velocity formatter (en-IN grouping, 0 decimals, HALF_UP) and
uses it for Total/Short Investment on the sanction request and RBM L2 screens.
 
37770 12 d 10 h amit /trunk/profitmandi-fofo/src/main/ fix(movement): GRN of a movement invoice validated against its own PO + billed IMEIs; Reopen removed; PO list shows Created By; supplier state from GSTIN; jsVersion 436  
37765 12 d 11 h amit /trunk/profitmandi-fofo/src/main/ feat(store-closure): closure popup with reason, remark and approval mail upload

- Close Store (inactive stores page and deactivate flow) opens one shared popup; /closeStore
delegates to StoreClosureService (dao r37764)
- store status access checks read StoreAccess lists; mohit.gulati removed from extend billing
- jsVersion 435
 
37723 18 d 11 h amit /trunk/profitmandi-fofo/src/ Bulk-uploaded movement rows are validated on screen; popup shows arriving stock per PO

Bulk upload only fills the PO screen - the PO is created from the screen. It used to price
with resolvePrices(qty), so one row over what could move rejected the whole file. It now prices
from describeAvailability (same cost layer order creation uses) and never refuses on quantity:
over-cap rows turn red on render, createPO blocks while any row is red and lists them, and
the server checks again on create. An item with no stock and nothing arriving still fails
the upload (nothing to price).

Popup reads in stock + arriving (per PO, <- supplier) - promised (per PO) = can move; the
'Of these, still to arrive' line is gone. Tests for the Oppo A6 UP->Noida case. jsVersion 433.
Needs dao r37722.
 
37711 19 d 0 h amit /trunk/ Bulk-uploaded PO rows show the same availability breakdown as hand-picked ones

A row added by hand showed what the warehouse holds, what older orders have promised and how many
units the order could take; the same row arriving from a bulk upload showed none of it. The file
was the one place the numbers behind a quantity were hidden, which is the case where a mistake is
least visible and hardest to unpick afterwards.

describeAvailability now also answers for a list of items. Both reads it needs already took a
list, so a whole file costs the same two queries a single item does rather than two per row. An
item the warehouse holds nothing of is left out of the result instead of failing the upload - its
quantity is still checked when the order is priced, and the row simply shows no breakdown.

The single-item and batch paths build their answer from one shared method, so the two cannot drift
apart, and the screen reuses the renderer it already had.
 
37707 19 d 0 h amit /trunk/profitmandi-fofo/src/main/ GRN price mismatch: say which PO the invoice will be received against, and what to do if it closes first

Resolving a price mismatch discards the PO line and raises a replacement dated to the invoice. That
replacement is what the invoice is received against, so it is the one that has to stay open long
enough for the stock to arrive - and it closes on its own after four days for a movement, six for a
vendor order. Until now nothing said so: the GRN simply stopped matching and the correction sat
holding stock that had already arrived.

The confirmation now states what is about to happen and what to do if the stock lands late, and the
request screen explains what Po Id is. Reopening is offered only where it exists - a movement can be
reopened from Purchase Orders, a vendor order cannot and needs a fresh PO.
 
37705 19 d 0 h amit /trunk/profitmandi-fofo/src/main/ PO list: show the transaction id so a movement can be found from the invoice being received

An internal movement is raised as a transaction, so the invoice on the GRN desk leads straight back to its PO
through that id. The list is a DataTable, so having the column makes it searchable - which is how someone finds
the PO to reopen when a receipt arrives after auto-close, instead of hunting through date ranges.

Placed after Status so existing column positions are unchanged.
 
37704 19 d 0 h amit /trunk/ Reopen a movement PO whose stock arrived late, and stop stranding GRN price corrections

Internal movements auto-close after four days, which fits 99.6% of them - 5,491 of 5,515 receipts
land inside the window. The remainder leave the PO closed with the stock still in transit and
nowhere to receive it: 998 internal POs closed during 2026 still holding 21,996 unreceived units.

A closed movement PO can now be reopened from the purchase order list. Reopening stamps
reopenedAt, and auto-close measures from WarehousePurchaseOrder.getOpenSince() - reopenedAt when
set, the PO date otherwise - so a reopened PO gets the same fresh window a new one gets instead of
being closed straight back on the next sweep. Only movements between our own warehouses: an
external vendor PO that has closed is settled with that vendor, not reopened unilaterally.

Separately, a GRN price correction now checks that the PO it just raised is one the invoice can
actually be received against. Matching reads POs that are open and approved for the same supplier
and warehouse dated on or before the invoice; it never looks at the PO being corrected, so what
matters is that the new PO is receivable. 54 were not - backdated into INIT by the old approval
gate, hence outside the match - and each stranded silently: original line discarded, GRN completed
without it, the correction left holding a reservation for stock that had already arrived.

isOpen() names the open set - INIT, READY, PARTIALLY_FULFILLED - that the movement and commitment
queries already read.

Migration sql/add_po_reopened_at_20260918.sql adds reopenedAt, nullable and additive. It must run
before this ships: the entity maps the column.
 
37701 19 d 4 h amit /trunk/profitmandi-fofo/src/ PO create: expected stock counts toward the quantity, popover wording follows

Stock still to arrive is now part of what the order can take, so the breakdown reports it as a
qualifier on that number rather than as something set aside - 'Of these, still to arrive' instead
of 'On the way in (not yet received)', which read as though it could not be ordered.

Tests follow the two rule changes: expected receipts can be ordered against, a quantity beyond
what is held and expected together is still refused and says so, and availability counts expected
receipts toward what can move. 21 tests pass.
 
37699 19 d 6 h amit /trunk/profitmandi-fofo/src/main/ Fix: movement availability popover rendered empty except the closing note

The breakdown was built as a table. Bootstrap 3.4.1 sanitizes popover content against a
whitelist that includes neither table nor its rows and cells, and it removes a non-whitelisted
element together with everything inside it - so the whole table was dropped and only the note
survived, leaving a popover that referred to orders that were not shown.

Rebuilt from divs and spans, which are whitelisted. Sanitizing stays on rather than being
switched off for this popover: the content carries PO numbers and warehouse names read out of
the database.

Also stops the zero-quantity note pointing at orders that are not there - a warehouse whose
only stock is still inbound has nothing promised to point at. jsVersion bumped.
 
37697 19 d 6 h amit /trunk/profitmandi-fofo/src/ PO create: show what can move, and which orders hold the rest, while the quantity is typed

Picking an item on a movement order already called getPricing, which read the sending
warehouse's stock and returned only a price. It now returns the availability too, so the row
can show it: an info marker beside the quantity box opens the breakdown - in stock, promised
with each holding order named by PO number and date, anything still arriving, and the quantity
this order can take.

The quantity box flags the moment what is typed passes that cap, so it is corrected before
submitting rather than after being refused. The marker turns amber when stock is partly
promised and red when none can move.

Outside vendors are unaffected: their pricing response carries no availability and their rows
are left exactly as they were. jsVersion bumped so the screen picks up the new script.

Tests cover the four cases that matter: what can move with orders named, zero movable reported
rather than refused, this order's cap kept separate from what the warehouse holds when stock
came in at two costs, and a warehouse holding none of the item still refusing.
 
37670 20 d 8 h amit /trunk/profitmandi-fofo/src/main/ Check GSTIN shape on the onboarding screen before submit (jsVersion 425)

Both GST boxes are validated client-side and must match, so ops see the problem on the screen
instead of discovering it when NIC refuses the first invoice. Server-side guard in dao r37669
is what actually enforces it.
 
37643 21 d 11 h amit /trunk/profitmandi-fofo/src/main/ Hot Deal brand: admin edits attributes + optional OEM catalog mapping; brand/date/cap controls removed; jsVersion 424  
37632 21 d 14 h aman /trunk/ fix(loi): don't leave an LOI half signed when the signed PDF fails to save

Confirm Sign stores the partner OTP (/validateLoiOtp) before the browser builds and uploads the
signed PDF (/saveLoiDoc). When that second step failed - html2pdf not loaded from cdnjs, upload
rejected, tab closed, server error - nothing was shown, no LOI mail went out, no onboarding was
created, and because loiOtpPresent hid Generate LOI the filler could never re-sign (LOI 734).

- pendingFormList: loiOtpPresent only when OTP AND loiDoc are both saved; new loiSignIncomplete
flag shows a red "signed LOI not saved" note on the Pending LOI list (web + V2 app).
- loi-form.js Confirm Sign: every failure after the OTP says the LOI was NOT saved and how to
retry; checks html2pdf is loaded; success alert only after /saveLoiDoc confirms; no double submit.
- /saveLoiDoc (fofo + V2): refuses a document without a verified OTP; a repeat call for an
already saved LOI is a no-op (no second mail / completion).
- /validateLoiOtp (fofo + V2): clear message when no OTP was sent in 24h; reports the real
rejection reason (e.g. OTP already used) instead of always "wrong".
- sendSignedLoiPdfToPartner: filler without a manager no longer throws and rolls back the save.
- OtpProcessor.generateOtp: never hands back an already verified OTP under the 2-minute throttle.
- AppConfig version 423 for loi-form.js.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RhJD2sc6pf3Zd7f4hyGxhH
 

Show All