Skip to content

Phase 14: Bank Guarantee

Duration: 1 day Goal: Track supplier Bank Guarantees for I3/Contract items


I3 category items and Contract Rum require suppliers to furnish Bank Guarantees.


class BankGuarantee(BaseDocType):
"""Supplier Bank Guarantee for I3/Contract items."""
supplier: str # FK to Supplier
bg_number: str = Field(max_length=50, unique=True)
bg_date: date
bg_amount: Decimal
expiry_date: date
# Bank
bank_name: str
bank_branch: str | None = None
bank_address: str | None = None
bank_phone: str | None = None
# Status
is_deleted: bool = False
remarks: str | None = None
# Items covered
items: list["BankGuaranteeItem"] = []
class Meta:
table_name = "bank_guarantee"
class BankGuaranteeItem(BaseDocType):
"""Item-wise BG quantity allocation."""
parent: str # FK to BankGuarantee
item: str # FK to Item
qty_cases: Decimal # Covered quantity
class Meta:
table_name = "bank_guarantee_item"

class PRGOBGValidator:
"""Validate I3 item quantities against BG."""
async def get_bg_qty(self, supplier: str, item: str) -> Decimal:
"""Get total BG quantity for item from supplier."""
result = await self.db.fetch_one("""
SELECT SUM(bgi.qty_cases) as total
FROM bank_guarantee_item bgi
JOIN bank_guarantee bg ON bgi.parent = bg.id
WHERE bg.supplier = $1 AND bgi.item = $2
AND bg.expiry_date >= CURRENT_DATE
AND NOT bg.is_deleted
""", supplier, item)
return result["total"] or Decimal("0")
async def validate_prgo_against_bg(
self,
prgo: PRGO,
item: str,
recommended_qty: Decimal,
) -> None:
"""Warn if recommended qty exceeds BG."""
item_obj = await self.item_repo.get(item)
if item_obj.category != "I3":
return
supplier = await self.get_default_supplier(item)
bg_qty = await self.get_bg_qty(supplier, item)
if recommended_qty > bg_qty:
# Note: This is a warning, not a blocker
await self.add_prgo_remark(
prgo, item,
f"Recommended qty {recommended_qty} exceeds BG qty {bg_qty}"
)

class BGExpiryAlertService:
"""Alert for expiring Bank Guarantees."""
async def get_expiring_soon(self, days: int = 30) -> list[BankGuarantee]:
"""Get BGs expiring in next N days."""
threshold = date.today() + timedelta(days=days)
return await self.bg_repo.find(
filters=[
FilterSpec("expiry_date", FilterOperator.LE, threshold),
FilterSpec("expiry_date", FilterOperator.GE, date.today()),
FilterSpec("is_deleted", FilterOperator.EQ, False),
]
)

Endpoint Method Description
/api/v1/bank-guarantee GET, POST List/Create BG
/api/v1/bank-guarantee/{id} GET, PUT BG CRUD
/api/v1/bank-guarantee/expiring GET Expiring soon
/api/v1/supplier/{id}/bank-guarantees GET Supplier’s BGs

  • BG creation with item allocation
  • PRGO shows BG qty for I3 items
  • Copy BG to Recommended shortcut works
  • Expiry alerts working
  • BG utilization tracking (optional)