Improve the frontend modals

This commit is contained in:
Urtzi Alfaro
2025-10-27 16:33:26 +01:00
parent 61376b7a9f
commit 858d985c92
143 changed files with 9289 additions and 2306 deletions

View File

@@ -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