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 {