bmc_hub/app/modules/also/models/schemas.py
Christian a604a3cc44 Add comprehensive test suite for vTiger integration and ticket module
- Implemented test scripts for vTiger account retrieval, contact data, and modules.
- Created a detailed test suite for the ticket module, covering database schema validation, ticket number generation, prepaid card constraints, and service logic.
- Added tests for vTiger field inspection and various queries related to accounts and sales orders.
- Introduced SQL migration scripts for the ALSO Cloud Billing foundation, including import jobs, lines, and mapping tables with necessary constraints and indices.
- Enhanced workflow columns in the import lines table to support matching and validation timestamps.
2026-06-20 03:29:51 +02:00

149 lines
4.1 KiB
Python

from datetime import date, datetime
from decimal import Decimal
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field
ALSO_SOURCE_TYPES = Literal["api", "xml", "json_export", "xml_export", "csv"]
ALSO_QUEUE_STATUSES = Literal[
"new",
"matching_products",
"matching_customers",
"ready_for_approval",
"approved",
"invoiced",
"error",
]
class AlsoImportJobCreate(BaseModel):
source_type: ALSO_SOURCE_TYPES
source_label: Optional[str] = None
file_name: Optional[str] = None
import_version: Optional[str] = None
raw_payload: Dict[str, Any] = Field(default_factory=dict)
class AlsoImportLineInput(BaseModel):
line_no: Optional[int] = None
source_line_ref: Optional[str] = None
company: Optional[str] = None
customer_id: Optional[str] = None
account_id: Optional[str] = None
vat: Optional[str] = None
also_company_id: Optional[str] = None
material_number: Optional[str] = None
product_name: Optional[str] = None
vendor: Optional[str] = None
cost_amount: Optional[Decimal] = None
sales_price: Optional[Decimal] = None
unit_price: Optional[Decimal] = None
total_price: Optional[Decimal] = None
currency: Optional[str] = None
billing_start: Optional[date] = None
charge_interval: Optional[str] = None
billing_interval: Optional[str] = None
billable_parameters: Optional[Decimal] = None
queue_status: ALSO_QUEUE_STATUSES = "new"
raw_line: Dict[str, Any] = Field(default_factory=dict)
class AlsoImportLinesRequest(BaseModel):
lines: List[AlsoImportLineInput] = Field(default_factory=list)
class AlsoQueueProcessRequest(BaseModel):
import_job_id: Optional[int] = Field(default=None, gt=0)
line_ids: List[int] = Field(default_factory=list)
limit: int = Field(default=500, ge=1, le=5000)
class AlsoQueueApproveRequest(BaseModel):
import_job_id: Optional[int] = Field(default=None, gt=0)
line_ids: List[int] = Field(default_factory=list)
class AlsoQueueProcessResult(BaseModel):
processed: int
updated: int
ready_for_approval: int
errored: int
class AlsoApproveResult(BaseModel):
approved_lines: int
created_drafts: int
draft_ids: List[int] = Field(default_factory=list)
class AlsoCompanyMappingUpsert(BaseModel):
also_company_id: str = Field(min_length=1)
also_customer_id: Optional[str] = None
customer_id: int = Field(gt=0)
match_confidence: Optional[Decimal] = None
notes: Optional[str] = None
class AlsoProductMappingUpsert(BaseModel):
material_number: str = Field(min_length=1)
vendor: str = Field(min_length=1)
hub_product_id: int = Field(gt=0)
product_name_snapshot: Optional[str] = None
class AlsoImportJobResponse(BaseModel):
id: int
source_type: str
source_label: Optional[str] = None
status: str
file_name: Optional[str] = None
import_version: Optional[str] = None
imported_by_user_id: Optional[int] = None
imported_at: datetime
line_count: int = 0
class AlsoQueueLineResponse(BaseModel):
id: int
import_job_id: int
queue_status: str
company: Optional[str] = None
customer_id: Optional[str] = None
material_number: Optional[str] = None
product_name: Optional[str] = None
vendor: Optional[str] = None
total_price: Optional[Decimal] = None
currency: Optional[str] = None
matched_customer_id: Optional[int] = None
matched_product_id: Optional[int] = None
order_draft_id: Optional[int] = None
validation_errors_json: List[Dict[str, Any]] = Field(default_factory=list)
class AlsoDashboardSummaryResponse(BaseModel):
monthly_revenue: Decimal
monthly_cost: Decimal
monthly_margin: Decimal
unmatched_products: int
unmatched_customers: int
pending_approvals: int
invoiced_customers: int
class AlsoDifferenceItem(BaseModel):
customer_id: Optional[int] = None
customer_name: Optional[str] = None
material_number: Optional[str] = None
product_name: Optional[str] = None
vendor: Optional[str] = None
previous_month_qty: Decimal
current_month_qty: Decimal
change_percent: Optional[Decimal] = None
warning: bool = False