from typing import List from src.domain.entities.merchant import Merchant, MerchantListItem from src.domain.interfaces.merchant_repository import MerchantRepositoryInterface from src.core.exceptions import NotFoundException def _compute_pending_docs(item: MerchantListItem) -> List[str]: """ Mirrors MerchantController::getHelperTxt() from the Laravel codebase. Stage 1: If ALL 3 critical docs are missing → show the missing ones. Stage 2: If at least one doc exists → sequential checklist: Module → Signed Agreement → Offers → Maker Checker → Bank Details → Status """ any_doc_exists = item.has_pan_card or item.has_equifax or item.has_gst_reg if not any_doc_exists: pending = [] if not item.has_pan_card: pending.append("Pan Card") if not item.has_equifax: pending.append("Bureau Report") if not item.has_gst_reg: pending.append("Business Reg") return pending # At least one document uploaded — check workflow steps in order if not item.has_module: return ["Module"] if not item.is_agreement_signed: return ["Signed Agreement"] if not item.has_active_offer: return ["Offers"] if item.has_inactive_offer: return ["Maker Checker"] if not item.has_bank: return ["Bank Details"] if item.status == "inactive": return ["Status"] return [] def _resolve_display_status(item: MerchantListItem) -> str: """ Mirrors the status display logic from resources/views/admin/merchant/index.blade.php line 174. Conditions (in order): 1. status not set → "--" 2. receive_application is null → "Deactivated" 3. status='active', pre_status=0 → "Active for disbursements" 4. status='active', pre_status=1 → "Active for login/training" 5. otherwise → raw status value """ if item.status is None: return "--" if item.receive_application is None: return "Deactivated" if item.status == "active" and item.pre_status == 0: return "Active for disbursements" if item.status == "active" and item.pre_status == 1: return "Active for login/training" return item.status class GetMerchantsUseCase: """Returns slim merchant list with resolved display status (for frontend list view).""" def __init__(self, merchant_repo: MerchantRepositoryInterface): self.merchant_repo = merchant_repo def execute(self) -> List[MerchantListItem]: items = self.merchant_repo.get_list() for item in items: pending = _compute_pending_docs(item) # compute before status is mutated item.status = _resolve_display_status(item) item._pending_docs = pending # attach for schema serialization return items class GetMerchantByIdUseCase: """Returns a single merchant by ID.""" def __init__(self, merchant_repo: MerchantRepositoryInterface): self.merchant_repo = merchant_repo def execute(self, merchant_id: int) -> Merchant: merchant = self.merchant_repo.get_by_id(merchant_id) if not merchant: raise NotFoundException(f"Merchant {merchant_id} not found") return merchant