Spaces:
Runtime error
Runtime error
| # 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 | |