Spaces:
Sleeping
Sleeping
Mirchi Trading - Business Logic & Backend Architecture
Business Flow Analysis
Bill Types Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BILL TYPE CLASSIFICATION โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโ
โ ALL BILLS โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโผโโโโโโโโ โโโโโโโโโผโโโโโโโโ
โ REGULAR โ โ PATTI โ
โ (R) โ โ (P) โ
โโโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ
โ โ
โโโโโโโโดโโโโโโโ โโโโโโโโดโโโโโโโ
โ โ โ โ
โโโโโผโโโโ โโโโโผโโโโ โโโโโผโโโโ โโโโโผโโโโ
โ AWAAK โ โJAWAAK โ โ AWAAK โ โJAWAAK โ
โ (Buy) โ โ (Sell)โ โ (Buy) โ โ (Sell)โ
โโโโโโโโโ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโ
โ โ โ โ
โ โ โ โ
Stock IN Stock OUT Stock IN Stock OUT
(Purchase) (Sales) (Purchase) (Sales)
1. REGULAR BILLS (Awaak/Jawaak)
Awaak Regular (Purchase/Buy)
- Purpose: Buying mirchi from farmers/suppliers
- Stock Impact: INCREASES stock
- Payment Flow: We PAY money to party
- Balance: Party gets CREDIT (Jama for them)
Data Captured:
- Party details (farmer/supplier)
- Mirchi items with:
โข Poti count
โข Poti weights (individual bag weights)
โข Net weight (total)
โข Rate per kg
โข Amount
- Expenses:
โข Poti amount (packing)
โข CESS
โข Adat (commission)
โข Hamali (labor)
โข Packaging hamali
โข Gaadi bharni (transport)
โข Other expenses
- Payment details:
โข Cash, UPI, Bank, Due
Jawaak Regular (Sales/Sell)
- Purpose: Selling mirchi to buyers
- Stock Impact: DECREASES stock
- Payment Flow: We RECEIVE money from party
- Balance: Party gets DEBIT (Udha for them)
Data Captured:
- Same as Awaak but:
โข Stock goes OUT
โข We receive payment
โข Balance is what party OWES us
2. PATTI BILLS (Special Trading)
Patti Awaak (Patti Purchase)
- Purpose: Buying mirchi on behalf of another party (patti system)
- Stock Impact: NO direct stock change (held in patti)
- Key Difference: NO lot/weight initially - just basic purchase
Data Captured:
- Party (patti holder)
- Mirchi items with:
โข Poti count
โข Poti weights
โข Net weight
โข Rate per kg
- Patti-specific expenses:
โข Packing
โข Godown (storage)
โข Commission
โข Hamali
โข Gaadi bhade (transport)
โข Other expenses
- NO lot number initially
- NO stock entry until processed
Patti Jawaak (Patti Sales with Lot/Weight)
- Purpose: Selling patti mirchi with lot tracking
- Stock Impact: Stock OUT from patti holdings
- Key Feature: HAS lot number and weightage
Data Captured:
- Party (patti holder)
- Lot number (MANDATORY)
- Mirchi items with:
โข Poti count
โข Poti weights (detailed)
โข Net weight (calculated)
โข Rate per kg
- Weightage details:
โข Gross weight
โข Tare weight
โข Net weight verification
- Expenses same as Patti Awaak
- Stock adjustment from patti holdings
3. MIXED BILLS (Regular + Patti Combined)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MIXED BILL STRUCTURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Item 1: เคธเคพเคตเคฟเคคเฅเคฐเฅ (source: normal) - Regular stock โ
โ Item 2: เคเฅเคฏเฅเคคเคฟ (source: patti) - Patti stock โ
โ Item 3: เคจเคพเคเคฟเคจ (source: normal) - Regular stock โ
โ Item 4: เคฌเฅเคฏเคพเคกเคเฅ (source: patti) - Patti stock โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Combined expenses from both sources โ
โ Combined payment tracking โ
โ Stock adjustment for BOTH regular and patti โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4. BILL NUMBERING SYSTEM
Format: {PREFIX}{BATCH}{NUMBER}
Year: 2025
โโโ A Batch: A1, A2, A3 ... A500 (Regular Awaak)
โโโ B Batch: B1, B2, B3 ... B500 (Regular Awaak overflow)
โโโ C Batch: C1, C2, C3 ... C500 (Regular Awaak overflow)
โ ... continues till Z500
โโโ J Batch: J1, J2, J3 ... J500 (Regular Jawaak)
โ ... continues
โโโ PA Batch: PA1, PA2 ... PA500 (Patti Awaak)
โโโ PJ Batch: PJ1, PJ2 ... PJ500 (Patti Jawaak)
โโโ M Batch: M1, M2, M3 ... M500 (Mixed bills)
Next Year: 2026
โโโ All batches RESET to 1
โโโ Format: {PREFIX}{YEAR}{BATCH}{NUMBER}
Example: A2026A1, A2026A2, ... A2026A500
Bill Number Structure
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BILL NUMBER FORMAT โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Regular: {TYPE}{YEAR}{BATCH}{NUMBER} โ
โ A2025A001 = Awaak 2025, Batch A, Bill 1 โ
โ A2025A500 = Awaak 2025, Batch A, Bill 500 โ
โ A2025B001 = Awaak 2025, Batch B, Bill 1 โ
โ J2025A001 = Jawaak 2025, Batch A, Bill 1 โ
โ โ
โ Patti: {TYPE}{YEAR}{BATCH}{NUMBER} โ
โ PA2025A001 = Patti Awaak 2025, Batch A, Bill 1 โ
โ PJ2025A001 = Patti Jawaak 2025, Batch A, Bill 1 โ
โ โ
โ Mixed: M{YEAR}{BATCH}{NUMBER} โ
โ M2025A001 = Mixed 2025, Batch A, Bill 1 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Database Table for Bill Number Tracking
CREATE TABLE bill_number_sequences (
id SERIAL PRIMARY KEY,
bill_type VARCHAR(10) NOT NULL, -- 'A', 'J', 'PA', 'PJ', 'M'
year INT NOT NULL, -- 2025, 2026
batch VARCHAR(1) NOT NULL, -- 'A' to 'Z'
current_number INT NOT NULL DEFAULT 0, -- 0 to 500
is_full BOOLEAN DEFAULT FALSE, -- True when reaches 500
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE (bill_type, year, batch)
);
-- Index for fast lookup
CREATE INDEX idx_bill_seq ON bill_number_sequences (bill_type, year, batch);
5. PARTY RENAME SCENARIO
Problem Statement
Initial State:
- Party ID: p-abc123
- Party Name: "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเฅเคฐเฅเคกเคฐเฅเคธ"
- 10 transactions with this party
User Action:
- Rename party to "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ"
Question:
- What happens to old transactions?
- Should they show old name or new name?
Solution: Denormalized + Historical Tracking
-- Parties table
CREATE TABLE parties (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(255) NOT NULL, -- Current name
previous_names JSONB, -- History of name changes
phone VARCHAR(20),
city VARCHAR(255),
party_type VARCHAR(20),
...
);
-- Transactions table
CREATE TABLE transactions (
id VARCHAR(50) PRIMARY KEY,
bill_number VARCHAR(20) UNIQUE,
party_id VARCHAR(50) REFERENCES parties(id),
party_name VARCHAR(255) NOT NULL, -- SNAPSHOT at bill time
party_name_current VARCHAR(255), -- Current name (for search)
...
);
Name Change Flow
1. User renames party "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเฅเคฐเฅเคกเคฐเฅเคธ" โ "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ"
2. Backend updates:
- parties.name = "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ"
- parties.previous_names = [
{"old_name": "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเฅเคฐเฅเคกเคฐเฅเคธ", "changed_at": "2025-03-13"}
]
3. New transactions will use:
- party_name = "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ" (snapshot)
- party_name_current = "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ"
4. Old transactions keep:
- party_name = "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเฅเคฐเฅเคกเคฐเฅเคธ" (original snapshot)
- party_name_current = "เคฐเคพเคฎเคเคเคฆเฅเคฐ เคเคเคก เคธเคเคธ" (for search)
5. Reports/Invoices show:
- Historical: Original name at time of transaction
- Search: Works with current name
6. REVERT LOGIC
Revert Scenarios
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ REVERT FLOW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Regular Awaak Revert: โ
โ โโโโโโโโโโโโโโโ Revert โโโโโโโโโโโโโโโ โ
โ โ Stock: +100 โ โโโโโโโโโโโโบ โ Stock: -100 โ โ
โ โ Balance: +โน5000 โ โ Balance: -โน5000 โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ
โ Regular Jawaak Revert: โ
โ โโโโโโโโโโโโโโโ Revert โโโโโโโโโโโโโโโ โ
โ โ Stock: -50 โ โโโโโโโโโโโโบ โ Stock: +50 โ โ
โ โ Balance: +โน3000 โ โ Balance: -โน3000 โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ
โ Patti Revert: โ
โ โโโโโโโโโโโโโโโ Revert โโโโโโโโโโโโโโโ โ
โ โ Patti Stock โ โโโโโโโโโโโโบ โ Patti Stock โ โ
โ โ Balance โ โ Reversed โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Revert Rules
Can Revert: Bill has no payments or all payments reversed
Cannot Revert:
- Already reverted
- Has unreversed payments
- Referenced by other bills
- Stock already adjusted by later transactions
Revert Creates:
is_return = Trueon original- New return bill with reference to original
- Stock adjustment entry
- Balance adjustment entry
7. STOCK MANAGEMENT
Stock Tracking
CREATE TABLE stock_ledger (
id VARCHAR(50) PRIMARY KEY,
mirchi_name VARCHAR(255) NOT NULL,
mirchi_id VARCHAR(50) REFERENCES mirchi_types(id),
-- Transaction reference
transaction_id VARCHAR(50),
patti_transaction_id VARCHAR(50),
-- Stock movement
movement_type VARCHAR(20) NOT NULL, -- 'IN', 'OUT', 'RETURN_IN', 'RETURN_OUT'
quantity_in FLOAT DEFAULT 0,
quantity_out FLOAT DEFAULT 0,
balance_after FLOAT NOT NULL,
-- Lot tracking (for patti)
lot_number VARCHAR(50),
-- Timestamps
created_at TIMESTAMP DEFAULT NOW(),
-- Audit
created_by VARCHAR(50),
notes TEXT
);
8. IMPROVED DATABASE SCHEMA
Core Tables
-- Parties with name history
CREATE TABLE parties (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
previous_names JSONB DEFAULT '[]',
phone VARCHAR(20) NOT NULL DEFAULT '',
city VARCHAR(255) NOT NULL DEFAULT '',
party_type VARCHAR(20) NOT NULL DEFAULT 'both',
notes TEXT,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Mirchi Types
CREATE TABLE mirchi_types (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Bill Number Sequences
CREATE TABLE bill_number_sequences (
id SERIAL PRIMARY KEY,
bill_type VARCHAR(10) NOT NULL,
year INT NOT NULL,
batch VARCHAR(1) NOT NULL,
current_number INT NOT NULL DEFAULT 0,
is_full BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE (bill_type, year, batch)
);
-- Regular Transactions
CREATE TABLE transactions (
id VARCHAR(50) PRIMARY KEY,
bill_number VARCHAR(20) NOT NULL UNIQUE,
bill_date DATE NOT NULL,
bill_type VARCHAR(20) NOT NULL, -- 'awaak', 'jawaak'
-- Party reference with snapshot
party_id VARCHAR(50) NOT NULL REFERENCES parties(id),
party_name VARCHAR(255) NOT NULL, -- Snapshot at creation
party_phone VARCHAR(20) DEFAULT '',
-- Financials
subtotal FLOAT DEFAULT 0,
total_amount FLOAT DEFAULT 0,
paid_amount FLOAT DEFAULT 0,
balance_amount FLOAT DEFAULT 0,
-- Expenses (JSONB for flexibility)
expenses JSONB,
-- Lot number (optional for regular)
lot_number VARCHAR(50),
-- Return tracking
is_return BOOLEAN DEFAULT FALSE,
original_bill_id VARCHAR(50) REFERENCES transactions(id),
return_bill_id VARCHAR(50) REFERENCES transactions(id),
-- Mixed bill flag
is_mixed BOOLEAN DEFAULT FALSE,
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Transaction Items
CREATE TABLE transaction_items (
id VARCHAR(50) PRIMARY KEY,
transaction_id VARCHAR(50) NOT NULL REFERENCES transactions(id) ON DELETE CASCADE,
mirchi_name VARCHAR(255) NOT NULL,
mirchi_id VARCHAR(50) REFERENCES mirchi_types(id),
poti_count INT DEFAULT 0,
poti_weights TEXT, -- JSON array of weights
net_weight FLOAT DEFAULT 0,
rate_per_kg FLOAT DEFAULT 0,
amount FLOAT DEFAULT 0,
-- Source for mixed bills
source VARCHAR(20) DEFAULT 'normal', -- 'normal', 'patti'
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Transaction Payments
CREATE TABLE transaction_payments (
id VARCHAR(50) PRIMARY KEY,
transaction_id VARCHAR(50) NOT NULL REFERENCES transactions(id) ON DELETE CASCADE,
amount FLOAT NOT NULL,
mode VARCHAR(20) NOT NULL, -- 'cash', 'upi', 'bank', 'due'
reference VARCHAR(255),
paid_at DATE,
-- Revert tracking
is_reversed BOOLEAN DEFAULT FALSE,
reversed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Patti Transactions
CREATE TABLE patti_transactions (
id VARCHAR(50) PRIMARY KEY,
bill_number VARCHAR(20) NOT NULL UNIQUE,
bill_date DATE NOT NULL,
bill_type VARCHAR(20) NOT NULL, -- 'patti_awaak', 'patti_jawaak'
-- Party reference
party_id VARCHAR(50) NOT NULL REFERENCES parties(id),
party_name VARCHAR(255) NOT NULL,
party_phone VARCHAR(20) DEFAULT '',
-- Financials
subtotal FLOAT DEFAULT 0,
total_amount FLOAT DEFAULT 0,
paid_amount FLOAT DEFAULT 0,
balance_amount FLOAT DEFAULT 0,
-- Patti expenses
expenses JSONB,
-- Lot number (MANDATORY for patti_jawaak)
lot_number VARCHAR(50),
-- Weightage details (for patti_jawaak)
gross_weight FLOAT,
tare_weight FLOAT,
verified_net_weight FLOAT,
-- Return tracking
is_return BOOLEAN DEFAULT FALSE,
original_bill_id VARCHAR(50) REFERENCES patti_transactions(id),
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Patti Transaction Items
CREATE TABLE patti_transaction_items (
id VARCHAR(50) PRIMARY KEY,
transaction_id VARCHAR(50) NOT NULL REFERENCES patti_transactions(id) ON DELETE CASCADE,
mirchi_name VARCHAR(255) NOT NULL,
mirchi_id VARCHAR(50) REFERENCES mirchi_types(id),
poti_count INT DEFAULT 0,
poti_weights TEXT,
net_weight FLOAT DEFAULT 0,
rate_per_kg FLOAT DEFAULT 0,
amount FLOAT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Stock Ledger
CREATE TABLE stock_ledger (
id VARCHAR(50) PRIMARY KEY,
mirchi_name VARCHAR(255) NOT NULL,
mirchi_id VARCHAR(50) REFERENCES mirchi_types(id),
-- References
transaction_id VARCHAR(50) REFERENCES transactions(id),
patti_transaction_id VARCHAR(50) REFERENCES patti_transactions(id),
-- Movement
movement_type VARCHAR(20) NOT NULL,
quantity_in FLOAT DEFAULT 0,
quantity_out FLOAT DEFAULT 0,
balance_after FLOAT NOT NULL,
-- Lot tracking
lot_number VARCHAR(50),
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Party Jama Entries (for balance tracking)
CREATE TABLE party_jama_entries (
id VARCHAR(50) PRIMARY KEY,
party_id VARCHAR(50) NOT NULL REFERENCES parties(id) ON DELETE CASCADE,
entry_date DATE NOT NULL,
amount FLOAT NOT NULL,
entry_type VARCHAR(20) NOT NULL, -- 'jama' (credit), 'udha' (debit)
-- Reference
transaction_id VARCHAR(50) REFERENCES transactions(id),
patti_transaction_id VARCHAR(50) REFERENCES patti_transactions(id),
reference VARCHAR(255),
notes TEXT,
-- Revert tracking
is_reversed BOOLEAN DEFAULT FALSE,
reversed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
9. API ENDPOINTS SUMMARY
Parties
GET /api/parties- List all partiesGET /api/parties/{id}- Get party detailsPOST /api/parties- Create partyPUT /api/parties/{id}- Update party (handles rename)DELETE /api/parties/{id}- Soft delete party
Mirchi Types
GET /api/mirchi-types- List all typesPOST /api/mirchi-types- Create typePUT /api/mirchi-types/{id}- Update typeDELETE /api/mirchi-types/{id}- Soft delete
Transactions
GET /api/transactions- List with filtersGET /api/transactions/next-bill-number?type={type}- Get next bill numberGET /api/transactions/{id}- Get detailsPOST /api/transactions- Create transactionPUT /api/transactions/{id}- Update transactionPOST /api/transactions/{id}/payment- Add paymentPOST /api/transactions/{id}/revert- Revert transaction
Patti Transactions
- Same structure as regular transactions
- Additional endpoints for lot/weightage
Reports
GET /api/reports/stock- Stock reportGET /api/reports/party-ledger/{id}- Party ledgerGET /api/reports/daily-summary- Daily summary