Improve the frontend modals
This commit is contained in:
@@ -31,11 +31,12 @@ class SupplierService:
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
supplier_data: SupplierCreate,
|
||||
created_by: UUID
|
||||
created_by: UUID,
|
||||
created_by_role: str = "member"
|
||||
) -> Supplier:
|
||||
"""Create a new supplier"""
|
||||
logger.info("Creating supplier", tenant_id=str(tenant_id), name=supplier_data.name)
|
||||
|
||||
"""Create a new supplier with role-based auto-approval"""
|
||||
logger.info("Creating supplier", tenant_id=str(tenant_id), name=supplier_data.name, role=created_by_role)
|
||||
|
||||
# Check for duplicate name
|
||||
existing = await self.repository.get_by_name(tenant_id, supplier_data.name)
|
||||
if existing:
|
||||
@@ -50,18 +51,48 @@ class SupplierService:
|
||||
raise ValueError(
|
||||
f"Supplier with code '{supplier_data.supplier_code}' already exists"
|
||||
)
|
||||
|
||||
|
||||
# Generate supplier code if not provided
|
||||
supplier_code = supplier_data.supplier_code
|
||||
if not supplier_code:
|
||||
supplier_code = self._generate_supplier_code(supplier_data.name)
|
||||
|
||||
|
||||
# Fetch tenant supplier settings to determine approval workflow
|
||||
try:
|
||||
from shared.clients.tenant_client import create_tenant_client
|
||||
tenant_client = create_tenant_client(settings)
|
||||
supplier_settings = await tenant_client.get_supplier_settings(str(tenant_id)) or {}
|
||||
except Exception as e:
|
||||
logger.warning("Failed to fetch tenant settings, using defaults", error=str(e))
|
||||
supplier_settings = {}
|
||||
|
||||
# Determine initial status based on settings and role
|
||||
require_approval = supplier_settings.get('require_supplier_approval', True)
|
||||
auto_approve_admin = supplier_settings.get('auto_approve_for_admin_owner', True)
|
||||
|
||||
# Auto-approval logic
|
||||
if not require_approval:
|
||||
# Workflow disabled globally - always auto-approve
|
||||
initial_status = SupplierStatus.active
|
||||
auto_approved = True
|
||||
logger.info("Supplier approval workflow disabled - auto-approving")
|
||||
elif auto_approve_admin and created_by_role.lower() in ['admin', 'owner']:
|
||||
# Auto-approve for admin/owner roles
|
||||
initial_status = SupplierStatus.active
|
||||
auto_approved = True
|
||||
logger.info("Auto-approving supplier created by admin/owner", role=created_by_role)
|
||||
else:
|
||||
# Require approval for other roles
|
||||
initial_status = SupplierStatus.pending_approval
|
||||
auto_approved = False
|
||||
logger.info("Supplier requires approval", role=created_by_role)
|
||||
|
||||
# Create supplier data
|
||||
create_data = supplier_data.model_dump(exclude_unset=True)
|
||||
create_data.update({
|
||||
'tenant_id': tenant_id,
|
||||
'supplier_code': supplier_code,
|
||||
'status': SupplierStatus.pending_approval,
|
||||
'status': initial_status,
|
||||
'created_by': created_by,
|
||||
'updated_by': created_by,
|
||||
'quality_rating': 0.0,
|
||||
@@ -69,16 +100,23 @@ class SupplierService:
|
||||
'total_orders': 0,
|
||||
'total_amount': 0.0
|
||||
})
|
||||
|
||||
|
||||
# Set approval fields if auto-approved
|
||||
if auto_approved:
|
||||
create_data['approved_by'] = created_by
|
||||
create_data['approved_at'] = datetime.utcnow()
|
||||
|
||||
supplier = await self.repository.create(create_data)
|
||||
|
||||
|
||||
logger.info(
|
||||
"Supplier created successfully",
|
||||
tenant_id=str(tenant_id),
|
||||
supplier_id=str(supplier.id),
|
||||
name=supplier.name
|
||||
name=supplier.name,
|
||||
status=initial_status.value,
|
||||
auto_approved=auto_approved
|
||||
)
|
||||
|
||||
|
||||
return supplier
|
||||
|
||||
async def get_supplier(self, supplier_id: UUID) -> Optional[Supplier]:
|
||||
@@ -144,7 +182,28 @@ class SupplierService:
|
||||
|
||||
logger.info("Supplier deleted successfully", supplier_id=str(supplier_id))
|
||||
return True
|
||||
|
||||
|
||||
async def hard_delete_supplier(self, supplier_id: UUID, tenant_id: UUID) -> Dict[str, Any]:
|
||||
"""
|
||||
Hard delete supplier and all associated data (permanent deletion)
|
||||
Returns deletion summary for audit purposes
|
||||
"""
|
||||
logger.info("Hard deleting supplier", supplier_id=str(supplier_id), tenant_id=str(tenant_id))
|
||||
|
||||
# Delegate to repository layer - all DB access is done there
|
||||
deletion_summary = await self.repository.hard_delete_supplier(supplier_id)
|
||||
|
||||
if not deletion_summary:
|
||||
raise ValueError("Supplier not found")
|
||||
|
||||
logger.info(
|
||||
"Supplier hard deleted successfully",
|
||||
supplier_id=str(supplier_id),
|
||||
**deletion_summary
|
||||
)
|
||||
|
||||
return deletion_summary
|
||||
|
||||
async def search_suppliers(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
@@ -184,18 +243,18 @@ class SupplierService:
|
||||
) -> Optional[Supplier]:
|
||||
"""Approve a pending supplier"""
|
||||
logger.info("Approving supplier", supplier_id=str(supplier_id))
|
||||
|
||||
supplier = self.repository.approve_supplier(supplier_id, approved_by)
|
||||
|
||||
supplier = await self.repository.approve_supplier(supplier_id, approved_by)
|
||||
if not supplier:
|
||||
logger.warning("Failed to approve supplier - not found or not pending")
|
||||
return None
|
||||
|
||||
|
||||
if notes:
|
||||
self.repository.update(supplier_id, {
|
||||
await self.repository.update(supplier_id, {
|
||||
'notes': (supplier.notes or "") + f"\nApproval notes: {notes}",
|
||||
'updated_at': datetime.utcnow()
|
||||
})
|
||||
|
||||
|
||||
logger.info("Supplier approved successfully", supplier_id=str(supplier_id))
|
||||
return supplier
|
||||
|
||||
@@ -207,14 +266,14 @@ class SupplierService:
|
||||
) -> Optional[Supplier]:
|
||||
"""Reject a pending supplier"""
|
||||
logger.info("Rejecting supplier", supplier_id=str(supplier_id))
|
||||
|
||||
supplier = self.repository.reject_supplier(
|
||||
|
||||
supplier = await self.repository.reject_supplier(
|
||||
supplier_id, rejection_reason, rejected_by
|
||||
)
|
||||
if not supplier:
|
||||
logger.warning("Failed to reject supplier - not found or not pending")
|
||||
return None
|
||||
|
||||
|
||||
logger.info("Supplier rejected successfully", supplier_id=str(supplier_id))
|
||||
return supplier
|
||||
|
||||
@@ -318,4 +377,4 @@ class SupplierService:
|
||||
if min_order is not None and min_order < 0:
|
||||
errors['minimum_order_amount'] = "Minimum order amount cannot be negative"
|
||||
|
||||
return errors
|
||||
return errors
|
||||
|
||||
Reference in New Issue
Block a user