# 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 ```sql 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 ```sql -- 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 1. **Can Revert**: Bill has no payments or all payments reversed 2. **Cannot Revert**: - Already reverted - Has unreversed payments - Referenced by other bills - Stock already adjusted by later transactions 3. **Revert Creates**: - `is_return = True` on original - New return bill with reference to original - Stock adjustment entry - Balance adjustment entry --- ## 7. STOCK MANAGEMENT ### Stock Tracking ```sql 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 ```sql -- 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 parties - `GET /api/parties/{id}` - Get party details - `POST /api/parties` - Create party - `PUT /api/parties/{id}` - Update party (handles rename) - `DELETE /api/parties/{id}` - Soft delete party ### Mirchi Types - `GET /api/mirchi-types` - List all types - `POST /api/mirchi-types` - Create type - `PUT /api/mirchi-types/{id}` - Update type - `DELETE /api/mirchi-types/{id}` - Soft delete ### Transactions - `GET /api/transactions` - List with filters - `GET /api/transactions/next-bill-number?type={type}` - Get next bill number - `GET /api/transactions/{id}` - Get details - `POST /api/transactions` - Create transaction - `PUT /api/transactions/{id}` - Update transaction - `POST /api/transactions/{id}/payment` - Add payment - `POST /api/transactions/{id}/revert` - Revert transaction ### Patti Transactions - Same structure as regular transactions - Additional endpoints for lot/weightage ### Reports - `GET /api/reports/stock` - Stock report - `GET /api/reports/party-ledger/{id}` - Party ledger - `GET /api/reports/daily-summary` - Daily summary