@cryptotaxi247 / CoPilot / commits / e6fad945

feat: display customer provisioning status in list view (#648)

Add is_provisioned field to customer API response and show color-coded status badge (green for provisioned, red for not provisioned) in the customer list.

oliver-oat committed Feb 2, 2026 at 19:35 UTC e6fad945830f035456a41b6948b3bcb185970475
4 files changed +26 -2
backend/app/customers/routes/customers.py
+12 -2
@@ -243,8 +243,18 @@ async def get_customers(session: AsyncSession = Depends(get_db)) -> CustomersRes
243 result = await session.execute(select(Customers))
244 customers = result.scalars().all()
245
246 - # Parse the customer ORM objects into schema objects
247 - customers_list = [CustomerRequestBody.from_orm(customer) for customer in customers]
246 + # Fetch all customer meta records to check provisioning status
247 + meta_result = await session.execute(select(CustomersMeta))
248 + customer_metas = meta_result.scalars().all()
249 + provisioned_codes = {meta.customer_code for meta in customer_metas}
250 +
251 + # Parse the customer ORM objects into schema objects and add is_provisioned field
252 + customers_list = []
253 + for customer in customers:
254 + customer_data = CustomerRequestBody.from_orm(customer)
255 + customer_data.is_provisioned = customer.customer_code in provisioned_codes
256 + customers_list.append(customer_data)
257 +
258 return CustomersResponse(
259 customers=customers_list,
260 success=True,
backend/app/customers/schema/customers.py
+2
@@ -25,6 +25,7 @@ class CustomerRequestBody(BaseModel):
25 country: Optional[str] = Field(None, description="Country")
26 customer_type: Optional[str] = Field(None, description="Type of the customer")
27 logo_file: Optional[str] = Field(None, description="Logo file for the customer")
28 + is_provisioned: Optional[bool] = Field(None, description="Whether the customer has been provisioned")
29
30 class Config:
31 orm_mode = True
@@ -43,6 +44,7 @@ class CustomerRequestBody(BaseModel):
44 "country": "USA",
45 "customer_type": "Enterprise",
46 "logo_file": "logo.png",
47 + "is_provisioned": True,
48 },
49 }
50
frontend/src/components/customers/CustomerItem.vue
+11
@@ -100,6 +100,16 @@
100 {{ customerInfo?.parent_customer_code }}
101 </template>
102 </Badge>
103 +
104 + <Badge type="splitted" :color="customer.is_provisioned ? 'success' : 'danger'" bright>
105 + <template #iconLeft>
106 + <Icon :name="ProvisionIcon" :size="13" />
107 + </template>
108 + <template #label>Status</template>
109 + <template #value>
110 + {{ customer.is_provisioned ? "Provisioned" : "Not Provisioned" }}
111 + </template>
112 + </Badge>
113 </div>
114 </template>
115
@@ -281,6 +291,7 @@ const InfoIcon = "carbon:information"
291 const ArrowIcon = "carbon:arrow-left"
292 const LocationIcon = "carbon:location"
293 const PhoneIcon = "carbon:phone"
294 +const ProvisionIcon = "carbon:network-3"
295
296 const showDetails = ref(false)
297 const selectedTabsGroup = ref<"customer" | "agents" | "wazuh_worker">("customer")
frontend/src/types/customers.d.ts
+1
@@ -15,6 +15,7 @@ export interface Customer {
15 customer_type: string
16 // TODO: consider removing it (logo_file)
17 logo_file: string
18 + is_provisioned?: boolean
19 }
20
21 export interface CustomerMeta {