Phase 12: Liquor Permits
Duration: 1.5 days Goal: Implement permit management for LIF (Liquor/IMFL) items
Overview
Section titled “Overview”Liquor items require permits from state excise authorities before receipt at depots.
1. Permit DocType
Section titled “1. Permit DocType”class Permit(BaseDocType): """Excise permit for liquor item receipt."""
permit_number: str = Field(max_length=50, unique=True)
# Reference purchase_order: str # FK to PurchaseOrder item: str # FK to Item depot: str # FK to Depot
# Dates permit_date: date validity_date: date extended_validity_date: date | None = None
# Quantity permit_quantity: Decimal # Cases
# Status is_cancelled: bool = False is_utilized: bool = False utilized_quantity: Decimal = Decimal("0")
remarks: str | None = None
class Meta: table_name = "permit" indexes = ["purchase_order", "item", "depot"]2. Permit in Receipt Flow
Section titled “2. Permit in Receipt Flow”class LiquorReceiptController: """Special handling for LIF item receipts."""
async def validate_permit( self, receipt: PurchaseReceipt, item: PurchaseReceiptItem, ) -> None: """Validate permit exists and has available quantity."""
if not await self.is_liquor_item(item.item): return
permit = await self.permit_repo.find_active( purchase_order=receipt.purchase_order, item=item.item, depot=receipt.depot, )
if not permit: raise ValidationError(f"No valid permit for {item.item_name}")
if permit.validity_date < date.today(): if not permit.extended_validity_date or permit.extended_validity_date < date.today(): raise ValidationError(f"Permit {permit.permit_number} has expired")
available = permit.permit_quantity - permit.utilized_quantity if available < item.qty: raise ValidationError( f"Permit has only {available} cases, trying to receive {item.qty}" )
async def on_receipt_submit( self, receipt: PurchaseReceipt, item: PurchaseReceiptItem, ) -> None: """Update permit utilization on receipt."""
if not await self.is_liquor_item(item.item): return
permit = await self.permit_repo.find_active( purchase_order=receipt.purchase_order, item=item.item, depot=receipt.depot, )
permit.utilized_quantity += item.qty if permit.utilized_quantity >= permit.permit_quantity: permit.is_utilized = True
await self.permit_repo.save(permit)3. API Endpoints
Section titled “3. API Endpoints”| Endpoint | Method | Description |
|---|---|---|
/api/v1/permit |
GET, POST | List/Create permits |
/api/v1/permit/{id} |
GET, PUT | Permit CRUD |
/api/v1/permit/{id}/extend |
POST | Extend validity |
/api/v1/permit/{id}/cancel |
POST | Cancel permit |
/api/v1/permit/pending |
GET | Unutilized permits |
4. Verification Checklist
Section titled “4. Verification Checklist”- Permit creation linked to PO
- Receipt blocked without valid permit
- Permit utilization tracked
- Extension workflow
- Permit expiry alerts