Skip to main content

Direct sales

Route: /org/inventory/sales · Module: org_inv_sales — 3 permissions Permission to view: View Inventory sales


1. What direct sales are​

Sales that did not come through the storefront: walk-in counter sales and offline B2B orders. The screen describes itself as "Walk-in POS & offline B2B orders — every sale decrements finished-good stock."

Direct saleStorefront order
OriginStaff ringing it upA customer checking out
Screen/org/inventory/sales/org/ecom/orders
Has a lifecycle❌ posted and done✅ placed → confirmed → shipped → delivered
Fulfilment, delivery, refunds❌✅
Writes a ledger row✅ SALE❌
Writes current_stock❌✅
The two sales channels write to different places

A storefront order decrements current_stock and posts no ledger row. A direct sale posts a SALE ledger row and does not touch current_stock — despite the screen's own subtitle saying it decrements stock.

Neither channel can see the other's numbers. See How stock is counted.

Figure 1 — The sales list. 1 today's total · 2 payment-method filter.

2. Reading the list​

ColumnNotes
DateWhen it was posted
InvoiceYour reference — INV-20260728-00412
CustomerName and phone, decoded from the row's remarks
ItemsLine count, with total units beneath
PaymentA pill — see below
TotalAfter discount and tax
👁Opens the detail drawer

TODAY in the header sums today's sales only. It is not a running total.

Payment methods​

Figure 2 — Five payment methods, one per invoice.
ValuePill
cashCash
cardCard
upiUPI
bankBank Transfer
creditCredit / On Account
The payment method is a label, not a payment

Recording upi does not create a payment record, reconcile anything, or mark money as received. Nothing in Orbit chases a credit sale for settlement. It is metadata on the ledger row.


3. Ringing up a sale​

Figure 3 — The POS entry view.
FieldNotes
ReferencePre-filled as INV-<yyyymmdd>-<seconds since midnight>. Editable
Customer name / phoneOptional. Free text — not linked to any customer record
Payment methodOne of the five above
Discount %Applied to the whole cart, not per line
Tax %Applied to the discounted subtotal
NotesFree text

The arithmetic, in order:

subtotal = Σ (qty × unit price)
discount = subtotal × discount% / 100
tax base = subtotal − discount
tax = tax base × tax% / 100
total = tax base + tax
The tax percentage here is typed by hand

It is not taken from the product's tax category. A product configured as 5% India GST does not pre-fill this field, and nothing checks that the number you type matches the catalogue.

Two people ringing up the same product can post different tax. If tax correctness matters, the storefront path — where the tax engine applies — is the one to use.

Validation — exact strings​

ConditionMessage
Empty cartCart is empty
A line with qty ≤ 0 or negative priceEach line needs a positive quantity and non-negative price
SuccessSale posted • ₹<total>

After a successful post the cart clears and the view stays open with a fresh reference — POS behaviour, for ringing up the next customer.


4. What a sale writes​

One SALE ledger row per cart line:

FieldValue
quantityNegative — stock leaving
unit_costThe unit selling price, not cost
batch_idShared across the invoice's lines
reference_noYour invoice reference
remarksThe encoded customer, phone, payment method, discount and tax
Customer name and phone are encoded into the remarks field

There are no customer columns on the ledger. The app packs them into remarks as [CUST:…] [PH:…] [PAY:…] [DISC:…] [TAX:…] and decodes them on this screen.

The ledger does not decode them, so it displays the raw tags — including the customer's name and phone in plain text. That is a privacy consideration on any tenant with real customers.


5. Permissions​

ActionPermission
Viewsales.view
Menusales.menu
Post a salesales.create

There is no edit, delete, refund or void permission — and no such action exists. A posted sale is permanent.

The UI checks none of these

NEW SALE renders for anyone with sales.view. The API rejects the post. See Permissions.


6. Troubleshooting​

SymptomCause
List is emptyNo project selected
Stock did not fallExpected — sales write the ledger, not current_stock
Tax looks wrongIt was typed manually; it does not come from the tax category
Customer name not searchable as a customerIt is free text on the sale, not a customer record
A sale needs reversingNo void exists. Post a compensating adjustment
Discount applied unexpectedlyIt applies to the whole cart, not one line