pratikbackend / docs /BUSINESS_LOGIC.md
Antaram's picture
Upload 96 files
7647b38 verified
|
Raw
History Blame Contribute Delete
22 kB
# 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