{{ card.label }}
{{ formatCurrency(card.value / 100) }}{{ card.difference >= 0 ? '+' : '' }}{{ formatCurrency(card.difference / 100) }} vs previous equivalent period{{ card.current ? 'Currently unpaid · all dates' : 'Selected period' }}No actions assigned yet
Ask the shop owner to update the allowed actions for your account.
Your shop at a glance
Choose the period you want to review.
NEEDS ATTENTION
{{ shopActions.length ? 'A few things to check.' : 'Nothing urgent flagged.' }}
Profit includes unpaid credit sales. Money received shows actual customer payments in this period.
Total cash earned
{{ formatCurrency(cashTotals.totalCents / 100) }}Total value of these sales, including credit.Actual cash earned
{{ formatCurrency(cashTotals.receivedCents / 100) }}Payments received against these sales.Credit outstanding
{{ formatCurrency(cashTotals.creditCents / 100) }}Total earned minus actual payments received.Cash, card and mobile payments included. Sales in the selected period; payments counted up to its end date. These figures include tax and exclude fully returned sales.
Earnings breakdown
For the selected period. Sales and profit exclude tax. Returns are deducted on the return date.
- Total sales
- {{ formatCurrency(earnings.total / 100) }}
- Discounts
- − {{ formatCurrency(earnings.discounts / 100) }}
- Returns (after original discounts)
- − {{ formatCurrency(earnings.returned / 100) }}
- Net sales
- {{ formatCurrency(earnings.net / 100) }}
- Cash sales Paid in full at checkout, including card and mobile
- {{ formatCurrency(earnings.cashSales / 100) }}
- Credit sales Full value sold on account, including any deposit
- {{ formatCurrency(earnings.creditSales / 100) }}
- Cost of sales
- − {{ formatCurrency(earnings.costs / 100) }}
- Gross profit
- {{ formatCurrency(earnings.grossProfit / 100) }}
Expenses in detail
| Date | Category | Description | Payment method | Amount |
|---|---|---|---|---|
| {{ expense.date }} | {{ expense.category }} | {{ expense.description || '—' }} | {{ expense.paymentMethod }} | {{ formatCurrency(expense.amountCents / 100) }} |
| No expenses recorded in this period. | ||||
- Total expenses
- − {{ formatCurrency(earnings.expenseTotal / 100) }}
- Actual profit Gross profit minus recorded expenses
- {{ formatCurrency(earnings.profit / 100) }}
Profit includes credit sales even while the customer still owes you. Payments received and credit outstanding are shown separately above. Collecting a debt does not add another sale or another profit.
Sales Revenue & Gross profit Trend
Daily summariesView figures
| Date | Net sales | Gross profit |
|---|---|---|
| {{ point.date }} | {{ formatCurrency(point.revenue / 100) }} | {{ formatCurrency(point.profit / 100) }} |
No sales or returns in this period. Choose another period or complete a sale to see the trend.
Net sales by category
After discounts and returns; excluding taxNo category sales in this period.
{{ p.name }}
{{ p.sku }} | Cat: {{ p.category }}
{{ p.stock }} items left
Reorder at: {{ p.reorderPoint }}
Stock levels look good.
{{ e.category }}
{{ e.description || 'General expense transaction' }}
-{{ formatCurrency(e.amount) }}
{{ formatDateTime(e.date).split(' ')[0] }}
No operational costs registered today.
{{ p.name }}
No active products match your filter.
{{ item.name }}
{{ formatCurrency(item.retailPrice) }} x {{ item.qty }}
{{ formatCurrency(item.retailPrice * item.qty) }}
Add your first item to start a sale.
Suspended Shopping Baskets ({{ heldCarts.length }})
{{ hc.customer ? hc.customer.name : 'Walk-in' }}
Items: {{ hc.items.length }}
Sales history
Filter sales, share receipts and record full or partial refunds.
{{ filteredHistory.length }} sales shown. Export CSV uses these filters. Archiving clears saved receipt logos and hides sales here; financial records stay available for accurate earnings and refunds.
| Invoice No | Timestamp | Customer | Cashier | Total Amount | Gross profit | Payment Method | Status | Actions |
|---|---|---|---|---|---|---|---|---|
| {{ sale.invoiceNumber }} | {{ formatDateTime(sale.date) }} | {{ sale.customerName }} | {{ sale.cashierName || 'System Terminal' }} | {{ formatCurrency(sale.total) }} | {{ formatCurrency(sale.profit) }} | {{ sale.paymentMethod }}{{ sale.status === 'refunded' ? 'Credit cancelled' : formatCurrency(sale.outstandingCents / 100) + ' outstanding' }} | {{ sale.status === 'refunded' ? 'Refunded' : sale.returnEvents?.length ? 'Partly refunded' : sale.status }} | |
| No transactions recorded inside the database yet. | ||||||||
Your stock
Manage products and record stock changes.
Stock value at cost
{{ formatCurrency(stockValue / 100) }}Current quantities × recorded average costNo sales in 30 days
{{ stockInsights.filter(p => p.qty <= 0 && p.stock > 0).length }}Review before buying moreBelow-cost prices
{{ stockInsights.filter(p => p.retailCents < p.costCents).length }}Check costs and selling pricesStock performance · last 30 days
Fast sellers appear first. Revenue and product contribution account for discounts and returns. Shop expenses are shown in Earnings.
| Product | Sold | Net sales | Product contribution | Stock at cost | |
|---|---|---|---|---|---|
| {{ product.name }}No net sales in 30 days | {{ product.qty }} {{ product.unit === 'kg' ? 'kg' : '' }} | {{ formatCurrency(product.revenue / 100) }} | {{ formatCurrency(product.profit / 100) }} | {{ formatCurrency(product.value / 100) }} |
Categories
Organise your stock, then add items to a category.
No categories yet. Add your first category here, or create one while adding a product.
| Item details | SKU / Barcode | Category | Cost Price | Retail Price | In Stock | Stock action | Status | Actions |
|---|---|---|---|---|---|---|---|---|
|
{{ p.name }} {{ p.description || 'No item descriptions details' }} |
{{ p.sku }} {{ p.barcode }} |
{{ p.category }} | {{ formatCurrency(p.costPrice) }} | {{ formatCurrency(p.retailPrice) }}{{ p.unit === 'kg' ? ' / kg' : '' }} |
{{ p.stock }} {{ p.unit === 'kg' ? 'kg' : 'units' }}
Reorder at: {{ p.reorderPoint }}
|
{{ p.status }} | ||
| No inventory found. Click 'Add product' to load stock records. | ||||||||
Customers
Keep customer details and loyalty points.
{{ c.name }}
Customer ID: #{{ c.id }}Points
{{ c.points || 0 }}
Owes {{ formatCurrency(c.balanceCents / 100) }}
{{ c.phone }}
{{ c.email }}
{{ c.address }}
{{ c.notes }}
Shop expenses
Record operating costs. Stock purchases belong in purchasing, which is a later milestone.
| Date | Category | Description | Payment method | Amount | Actions |
|---|---|---|---|---|---|
| {{ formatDateTime(e.date).split(' ')[0] }} | {{ e.category }} | {{ e.description || 'General expense entry' }} | {{ e.paymentMethod }} | {{ formatCurrency(e.amount) }} | |
| No expenses recorded. Log your first expenditure above. | |||||
Shop settings
Prices exclude the configured tax rate. Leave it at 0 unless your shop should charge tax.
Staff accounts
{{ emp.name }}
{{ emp.role }} · {{ emp.username }} · {{ emp.active ? 'Active' : 'Suspended' }}
Local backups
Owner backups are saved in the data/backups folder. They contain private records and are not encrypted; protect this computer and any backup copies.
CASH & COMMITMENTS
Your money
Keep money available separate from profit. These are recorded balances, not a live bank feed.
{{ can('reports') ? 'Expected cash in open drawers' : 'Expected cash in your open drawer' }}
{{ formatCurrency(drawerCash / 100) }}Includes floats. Confirm by counting.Recorded bank balance
{{ formatCurrency((moneySummary.bankCents || 0) / 100) }}{{ moneySummary.bankOpeningRecorded ? 'Opening balance + recorded movements' : 'Record the bank opening balance first' }}Card / mobile awaiting settlement
{{ formatCurrency((moneySummary.unsettledCents || 0) / 100) }}Confirm actual deposits against your bank.Customers owe you
{{ formatCurrency((moneySummary.customerDebtCents ?? creditBalanceCents) / 100) }}You owe suppliers
{{ formatCurrency((moneySummary.supplierDebtCents || 0) / 100) }}Record a money movement
Owner contributions and withdrawals do not change sales or profit. Transfers move money between bank and drawer. Settlement fees are recorded as expenses once.
Money movements
| Date | Movement | Account | Amount | Reference |
|---|---|---|---|---|
| {{ formatDateTime(event.created) }} | {{ {owner_in:'Owner contribution',owner_out:'Owner withdrawal',cash_to_bank:'Cash to bank',bank_to_cash:'Bank to cash',bank_opening:'Bank opening',card_settlement:'Card settlement'}[event.kind] }} | {{ event.method }} | {{ formatCurrency(event.amountCents / 100) }}Fee {{ formatCurrency(event.feeCents / 100) }} | {{ event.reference }} |
| No money movements recorded yet. | ||||
DAILY CASH
Cash shifts
Open a shift before selling. Count your cash when you close.
Recent shifts
| Opened | Status | Card sales | Mobile sales | Expected cash | Counted | Difference |
|---|---|---|---|---|---|---|
| {{ formatDateTime(shift.opened) }} | {{ shift.closed ? 'Closed' : 'Open' }} | {{ formatCurrency((shift.summary?.cardSalesCents || 0) / 100) }} | {{ formatCurrency((shift.summary?.mobileSalesCents || 0) / 100) }} | {{ shift.closed ? formatCurrency(shift.expected_cents / 100) : '—' }} | {{ shift.closed ? formatCurrency(shift.counted_cents / 100) : '—' }} | {{ shift.closed ? formatCurrency(shift.difference_cents / 100) : '—' }} |
BUYING & PAYMENTS
Suppliers
Receive stock once. Keep purchases, payments and what you owe together.
Add a supplier
Ask a stock manager to add suppliers.
Purchase invoices
| Date / supplier | Invoice | Total | Paid to date | Currently owed | Due | |
|---|---|---|---|---|---|---|
| {{ purchase.date }}{{ supplierName(purchase.supplierId) }} | {{ purchase.invoice }} | {{ formatCurrency(purchase.totalCents / 100) }} | {{ formatCurrency(purchase.paidCents / 100) }} | {{ formatCurrency(purchase.outstandingCents / 100) }} | {{ purchase.dueDate || 'Not set' }} | Items & payments{{ item.name }} · {{ item.qty }} {{ item.unit }} · {{ formatCurrency(item.landedCents / 100) }} {{ formatDateTime(payment.created) }} · {{ payment.method }} · {{ formatCurrency(payment.amountCents / 100) }} |
| No purchases in this period. Receive stock to record your first invoice. | ||||||
INVENTORY
Stock history
Opening balances, purchases, adjustments, sales and restocked returns are recorded. Latest 200 movements.
| When | Product | Change | Reason | Reference |
|---|---|---|---|---|
| {{ formatDateTime(movement.created) }} | {{ movement.productName }} | {{ movement.delta > 0 ? '+' : '' }}{{ movement.delta }} | {{ movement.reason }} | {{ movement.reference.slice(0, 8) }} |
| No stock movements yet. | ||||
CUSTOMER ACCOUNTS
Customer credit
Keep track of who owes you, and record payments as they arrive.
Still owed on selected sales
{{ formatCurrency(rangeCreditCents / 100) }}Current balance, after all repaymentsAll outstanding
{{ formatCurrency(creditBalanceCents / 100) }}Includes older debts outside the filterCredit movement during this period
This statement includes transactions in the chosen period, including repayments on older sales.
| Customer / sale | Due date | Sale value | Received | Outstanding | |
|---|---|---|---|---|---|
| {{ sale.customerName }}{{ sale.invoiceNumber }} · {{ formatDateTime(sale.date) }} | {{ sale.dueDate || 'No date set' }}{{ creditAge(sale) }} days since saleLast payment: {{ lastCreditPayment(sale) }}Promised: {{ customerDetails(sale.customerId).promisedDate }} | {{ formatCurrency(sale.totalCents / 100) }} | {{ formatCurrency(sale.receivedCents / 100) }} | {{ formatCurrency(sale.outstandingCents / 100) }} | Settled |
| {{ showSettledCredit ? 'No credit sales yet. Choose Credit when taking payment for a named customer.' : 'No unpaid credit sales.' }} | |||||
Recorded credit payments
| When | Customer | Invoice | Method | Amount |
|---|---|---|---|---|
| {{ formatDateTime(payment.created) }} | {{ sale.customerName }} | {{ sale.invoiceNumber }} | {{ payment.method }} | {{ formatCurrency(payment.amountCents / 100) }} |