"""Dashboard models for the ACPortal API."""
from __future__ import annotations
from datetime import datetime
from typing import Any, List, Optional
from uuid import UUID
from pydantic import Field
from ab.api.models.base import RequestModel, ResponseModel
[docs]
class DashboardParams(RequestModel):
"""Query parameters for GET /dashboard."""
view_id: Optional[int] = Field(None, alias="viewId", description="Grid view ID")
company_id: Optional[str] = Field(None, alias="companyId", description="Company UUID filter")
[docs]
class DashboardCompanyParams(RequestModel):
"""Query parameters for GET /dashboard/gridviews (company filter)."""
company_id: Optional[str] = Field(None, alias="companyId", description="Company UUID filter")
[docs]
class DashboardCompanyRequest(RequestModel):
"""Body for POST /dashboard/{inbound,inhouse,outbound,...} endpoints."""
company_id: Optional[str] = Field(None, alias="companyId", description="Company UUID filter")
[docs]
class DashboardItem(ResponseModel):
"""Row in the dashboard data grid — element of `DashboardSummary.data`."""
location: Optional[str] = Field(None, description="Location code")
job_display_id: Optional[int] = Field(None, alias="jobDisplayID", description="Job display ID")
pickup: Optional[str] = Field(None, description="Pickup company name")
customer: Optional[str] = Field(None, description="Customer name")
packer: Optional[str] = Field(None, description="Packer name")
priority: Optional[int] = Field(None, description="Priority")
next: Optional[str] = Field(None, description="Next step label")
pause: Optional[int] = Field(None, description="Pause flag")
labels: Optional[str] = Field(None, description="Labels")
ops_form: Optional[str] = Field(None, alias="opsForm", description="Ops form")
# A short label, not a number. Live values include "1 ", "2 ", "2.", "10" --
# padded, and "2." does not parse as an integer at all, so this was never an
# int that happened to arrive as text. Kept as the string the API sends
# rather than coerced, which would have to invent a reading for "2.".
step: Optional[str] = Field(None, description="Workflow step label")
ship_by: Optional[datetime] = Field(None, alias="shipBy", description="Ship-by date-time")
expedite: Optional[str] = Field(None, description="Expedite flag")
note: Optional[str] = Field(None, description="Note")
carrier: Optional[str] = Field(None, description="Carrier name")
labor: Optional[float] = Field(None, description="Estimated labor hours")
actual: Optional[float] = Field(None, description="Actual labor hours")
item_count: Optional[int] = Field(None, alias="item_Count", description="Item count")
cust_ref: Optional[str] = Field(None, alias="custRef", description="Customer reference")
requestor: Optional[str] = Field(None, description="Requesting company name")
agent: Optional[str] = Field(None, description="Agent code")
rep: Optional[str] = Field(None, description="Sales rep name")
job_price: Optional[float] = Field(None, alias="jobPrice", description="Job price")
basis: Optional[str] = Field(None, description="Pricing basis code")
created: Optional[datetime] = Field(None, description="Job created date-time")
full_age: Optional[int] = Field(None, alias="fullAge", description="Full age in days")
held: Optional[int] = Field(None, description="Days held")
net_age: Optional[int] = Field(None, alias="netAge", description="Net age in days")
status: Optional[str] = Field(None, description="Job status label")
next_status: Optional[str] = Field(None, alias="next_Status", description="Next status label")
dims: Optional[str] = Field(None, description="Dimensions summary")
[docs]
class DashboardSummary(ResponseModel):
"""Aggregated dashboard data — GET /dashboard."""
inbound_count: Optional[int] = Field(None, alias="inboundCount", description="Inbound shipment count")
outbound_count: Optional[int] = Field(None, alias="outboundCount", description="Outbound shipment count")
in_house_count: Optional[int] = Field(None, alias="inHouseCount", description="In-house shipment count")
local_deliveries_count: Optional[int] = Field(
None,
alias="localDeliveriesCount",
description="Local delivery count",
)
recent_estimates_count: Optional[int] = Field(
None,
alias="recentEstimatesCount",
description="Recent estimates count",
)
data: Optional[List[DashboardItem]] = Field(None, description="Grid view rows")
[docs]
class GridViewState(ResponseModel):
"""Saved grid view state — GET/POST /dashboard/gridviewstate/{id}."""
id: Optional[str] = Field(None, description="View state ID")
columns: Optional[List[dict]] = Field(None, description="Column configurations")
filters: Optional[List[dict]] = Field(None, description="Active filters")
sort_order: Optional[List[dict]] = Field(None, alias="sortOrder", description="Sort configuration")
[docs]
class GridViewInfo(ResponseModel):
"""Grid view metadata — GET /dashboard/gridviews.
Shape matches the swagger ``GridViewDetails`` component. ``id`` is the
forward reference consumed by :class:`DashboardParams.view_id` when
calling GET ``/dashboard``.
"""
id: Optional[int] = Field(None, description="View ID — feeds DashboardParams.view_id")
name: Optional[str] = Field(None, description="View name")
data_key: Optional[str] = Field(None, alias="dataKey", description="Data key")
is_active: Optional[bool] = Field(None, alias="isActive", description="Whether the view is active")
stored_procedure: Optional[str] = Field(
None,
alias="storedProcedure",
description="Backing stored procedure",
)
columns_specification: Optional[str] = Field(
None,
alias="columnsSpecification",
description="Column specification (raw)",
)
sp_columns: Optional[List[dict]] = Field(
None,
alias="spColumns",
description="Stored procedure column metadata",
)
[docs]
class GridSorting(RequestModel):
"""SortingInfo body options for the 8_01 dashboard grids."""
selector: str | None = Field(None, alias="selector", description="Selector.")
desc: bool = Field(False, alias="desc", description="Desc.")
[docs]
class GridGrouping(RequestModel):
"""GroupingInfo body options for the 8_01 dashboard grids."""
selector: str | None = Field(None, alias="selector", description="Selector.")
desc: bool = Field(False, alias="desc", description="Desc.")
group_interval: str | None = Field(None, alias="groupInterval", description="Group interval.")
is_expanded: bool | None = Field(None, alias="isExpanded", description="Is expanded.")
[docs]
class GridSummary(RequestModel):
"""SummaryInfo body options for the 8_01 dashboard grids."""
selector: str | None = Field(None, alias="selector", description="Selector.")
summary_type: str | None = Field(None, alias="summaryType", description="Summary type.")
[docs]
class DashboardGridOptions(RequestModel):
"""WebApiDataSourceLoadOptions body options for the 8_01 dashboard grids."""
require_total_count: bool = Field(False, alias="requireTotalCount", description="Require total count.")
require_group_count: bool = Field(False, alias="requireGroupCount", description="Require group count.")
is_count_query: bool = Field(False, alias="isCountQuery", description="Is count query.")
is_summary_query: bool = Field(False, alias="isSummaryQuery", description="Is summary query.")
skip: int = Field(0, alias="skip", description="Skip.", ge=0)
take: int = Field(0, alias="take", description="Take.", ge=0)
sort: list[GridSorting] | None = Field(None, alias="sort", description="Sort.")
group: list[GridGrouping] | None = Field(None, alias="group", description="Group.")
filter: list[Any] | None = Field(None, alias="filter", description="Filter.")
total_summary: list[GridSummary] | None = Field(None, alias="totalSummary", description="Total summary.")
group_summary: list[GridSummary] | None = Field(None, alias="groupSummary", description="Group summary.")
select: list[str] | None = Field(None, alias="select", description="Select.")
pre_select: list[str] | None = Field(None, alias="preSelect", description="Pre select.")
remote_select: bool | None = Field(None, alias="remoteSelect", description="Remote select.")
remote_grouping: bool | None = Field(None, alias="remoteGrouping", description="Remote grouping.")
expand_linq_sum_type: bool | None = Field(None, alias="expandLinqSumType", description="Expand linq sum type.")
primary_key: list[str] | None = Field(None, alias="primaryKey", description="Primary key.")
default_sort: str | None = Field(None, alias="defaultSort", description="Default sort.")
string_to_lower: bool | None = Field(None, alias="stringToLower", description="String to lower.")
paginate_via_primary_key: bool | None = Field(
None, alias="paginateViaPrimaryKey", description="Paginate via primary key."
)
sort_by_primary_key: bool | None = Field(None, alias="sortByPrimaryKey", description="Sort by primary key.")
allow_async_over_sync: bool = Field(False, alias="allowAsyncOverSync", description="Allow async over sync.")
search_value: str | None = Field(None, alias="searchValue", description="Search value.")
[docs]
class DashboardGridParams(RequestModel):
"""Company scope is a query parameter, separate from grid load options."""
company_id: UUID = Field(alias="companyId", description="Company UUID whose jobs populate the grid.")