"""Models used by the client""" import datetime import json from enum import Enum from typing import Any, Dict, List, Optional, Type, TypeVar import pydantic def to_lower_camel(s: str) -> str: """Alias generator to avoid breaking PEP8""" first, *others = s.split("_") return "".join([first.lower(), *map(str.capitalize, others)]) T = TypeVar("T", bound="BaseModel") class BaseModel(pydantic.BaseModel): """Expanded BaseModel for convenience""" @classmethod def from_dict(cls: Type[T], data: Dict[Any, Any]) -> T: """Initialize class from dict""" return cls(**data) @classmethod def from_json(cls: Type[T], json_data: str) -> T: """Initialize class from json file""" data = json.loads(json_data) return cls.from_dict(data) class BatchProgressEnum(str, Enum): CREATED = "created" VALIDATION_COMPLETED = "validation_completed" VALIDATION_FAILED = "validation_failed" SENT_TO_UBW = "sent_to_ubw" SEND_TO_UBW_FAILED = "send_to_ubw_failed" POLLING_COMPLETED = "polling_completed" POLLING_FAILED = "polling_failed" UBW_IMPORT_OK = "ubw_import_ok" UBW_IMPORT_FAILED = "ubw_import_failed" FETCH_FINAL_VOUCHERNO_COMPLETED = "fetch_final_voucherno_completed" FETCH_FINAL_VOUCHERNO_FAILED = "fetch_final_voucherno_failed" def __str__(self) -> str: return str(self.value) class ResponseStatusEnum(str, Enum): ACCEPTED = "Accepted" CONFLICT = "Conflict" UNKNOWN = "Unknown" def __str__(self) -> str: return str(self.value) class Transaction(BaseModel): account: str amount: float transdate: Optional[datetime.datetime] curamount: Optional[float] currency: Optional[str] description: str dim1: Optional[str] dim2: Optional[str] dim3: Optional[str] dim4: Optional[str] dim5: Optional[str] dim6: Optional[str] dim7: Optional[str] sequenceno: int taxcode: Optional[str] transtype: Optional[str] extinvref: Optional[str] class Voucher(BaseModel): voucherdate: datetime.datetime exref: Optional[str] voucherno: int transactions: List[Transaction] class InputBatch(BaseModel): """ Model representing a batch, with a list of vouchers (and each voucher has a list of transactions.) """ client: str batchid: str period: Optional[int] interface: str vouchertype: Optional[str] vouchers: List[Voucher] class OutputBatch(BaseModel): """ Model representing a batch, with a list of voucher ids connected to that batch. """ id: int created: str batchid: str period: Optional[int] interface: str client: str vouchertype: Optional[str] batch_validated_ok_date: Optional[str] batch_rejected_code: Optional[str] sent_date: Optional[str] http_response_content: Optional[str] http_response_code: Optional[int] orderno: Optional[int] polling_statuscode: Optional[str] polling_statuscode_date: Optional[str] getresult_date: Optional[str] getresult_statuscode: Optional[str] getresult_logg: Optional[str] getresult_report: Optional[str] batch_progress: Optional[str] vouchers: Optional[List[int]] class ErrorTransaction(BaseModel): id: int transaction_id: int validation_date: datetime.datetime validation_error: str validation_error_type_code: str class ErrorVoucher(BaseModel): id: int voucher_id: int validation_date: datetime.datetime validation_error: str validation_error_type_code: str class ErrorBatch(BaseModel): id: int batch_id: int date: datetime.datetime error: str error_type_code: str error_level: str error_source: str class BatchErrors(BaseModel): """Model for the /batch_error/<id> endpoint""" batch_errors: List[ErrorBatch] voucher_errors: List[ErrorVoucher] transaction_errors: List[ErrorTransaction] class CompleteTransaction(BaseModel): id: int voucher_id: int created: datetime.datetime account: str amount: float transdate: Optional[datetime.datetime] curamount: float currency: str description: str dim1: Optional[str] dim2: Optional[str] dim3: Optional[str] dim4: Optional[str] dim5: Optional[str] dim6: Optional[str] dim7: Optional[str] sequenceno: int taxcode: Optional[str] transtype: str extinvref: Optional[str] class CompleteVoucher(BaseModel): id: int batch_id: int created: datetime.datetime voucherdate: Optional[datetime.datetime] exref: str voucherno: int voucherno_ubw: Optional[int] voucherno_ubw_wflow: Optional[int] vouchertype: Optional[str] transactions: List[CompleteTransaction] class CompleteBatch(BaseModel): """Model for the /batch_complete/<id> endpoint""" created: datetime.datetime batchid: str period: Optional[int] interface: str client: str vouchertype: Optional[str] batch_validated_ok_date: Optional[datetime.datetime] batch_rejected_code: Optional[str] sent_date: Optional[datetime.datetime] http_response_content: Optional[str] http_response_code: Optional[int] orderno: Optional[int] polling_statuscode: Optional[str] polling_statuscode_date: Optional[datetime.datetime] getresult_date: Optional[datetime.datetime] getresult_statuscode: Optional[str] getresult_logg: Optional[str] getresult_report: Optional[str] batch_progress: str vouchers: List[CompleteVoucher] class Parameter(BaseModel): client: str created: datetime.datetime interface: str parameter: str mandatory: str validation: str value: str status: Optional[str] valid_from: Optional[datetime.date] valid_to: Optional[datetime.date] description: Optional[str] class Detail(BaseModel): id: Optional[int] # Cannot be sent in order_id: Optional[int] # Cannot be sent in account: str buyer_product_descr: Optional[str] buyer_product_code: str line_total: Optional[float] koststed: str prosjekt: Optional[str] t1: Optional[str] r00: Optional[str] delprosjekt: str anlegg: Optional[str] aktivitet: Optional[str] line_no: int product_specification: Optional[int] price: Optional[float] quantity: Optional[float] class Order(BaseModel): id: Optional[int] # Cannot be sent in abw_order_id: Optional[int] # Cannot be sent in accountable: Optional[str] buyer_no: str currency: str ext_order_ref: Optional[str] order_date: Optional[datetime.date] order_type: str sales_man: str trans_type: str ext_order_id: Optional[str] order_no: Optional[int] deliv_date: Optional[datetime.date] text3: Optional[str] text4: Optional[str] header_text: Optional[str] footer_text: Optional[str] details: Optional[List[Detail]] ubw_final_number: Optional[str] class AbwOrder(BaseModel): """ Model representing an AbwOrder, with a list of orders (and each order has a list of details.) """ id: Optional[int] # Cannot be sent in progress: Optional[str] # Cannot be sent in abworder_validated_ok_date: Optional[datetime.datetime] # Cannot be sent in responsible: str interface: str client: str abworderid: str ordrenr_ubw: Optional[str] # Not sent in, but returned by the API. orders: List[Order] class ErrorDetail(BaseModel): id: int detail_id: int validation_date: datetime.datetime validation_error: str validation_error_type_code: str class ErrorOrder(BaseModel): id: int order_id: int validation_date: datetime.datetime validation_error: str validation_error_type_code: str class ErrorAbwOrder(BaseModel): id: int abworder_id: int date: datetime.datetime error: str error_type_code: str error_level: str error_source: str class AbwOrderErrors(BaseModel): """Model for the /abw_order_errors/<id> endpoint""" abw_order_errors: List[ErrorAbwOrder] order_errors: List[ErrorOrder] detail_errors: List[ErrorDetail]