from datetime import datetime from pydantic import BaseModel, ConfigDict, Field class Parcela(BaseModel): valor: float vencimento: datetime | None = None class Autor(BaseModel): id: str name: str email: str class ComprasProperties(BaseModel): # O Holmes manda PEDIDO_LINX como numero (345, sem aspas). O Pydantic v2 # nao converte numero pra string sozinho, entao precisa habilitar. model_config = ConfigDict(coerce_numbers_to_str=True) protocolo: str pedido_linx: str = Field(alias="PEDIDO_LINX") fornecedor: str = Field(alias="Fornecedores") tipo_compra: str = Field(alias="Tipo de Compra") cnpj: str = Field(alias="CNPJ") # Chega vazio enquanto o processo nao passou pela fase da nota. nf_entrada: str | None = Field(default=None, alias="NUMERO NF ENTRADA") num_parcelas: int | None = Field(default=None, alias="num. parcelas") parcela1: float | None = Field(default=None, alias="parcela1") parcela2: float | None = Field(default=None, alias="parcela2") parcela3: float | None = Field(default=None, alias="parcela3") parcela4: float | None = Field(default=None, alias="parcela4") parcela5: float | None = Field(default=None, alias="parcela5") parcela6: float | None = Field(default=None, alias="parcela6") parcela7: float | None = Field(default=None, alias="parcela7") parcela8: float | None = Field(default=None, alias="parcela8") parcela9: float | None = Field(default=None, alias="parcela9") parcela10: float | None = Field(default=None, alias="parcela10") parcela11: float | None = Field(default=None, alias="parcela11") parcela12: float | None = Field(default=None, alias="parcela12") vencimento1: datetime | None = Field(default=None, alias="vencimento parcela1") vencimento2: datetime | None = Field(default=None, alias="vencimento parcela2") vencimento3: datetime | None = Field(default=None, alias="vencimento parcela3") vencimento4: datetime | None = Field(default=None, alias="vencimento parcela4") vencimento5: datetime | None = Field(default=None, alias="vencimento parcela5") vencimento6: datetime | None = Field(default=None, alias="vencimento parcela6") vencimento7: datetime | None = Field(default=None, alias="vencimento parcela7") vencimento8: datetime | None = Field(default=None, alias="vencimento parcela8") vencimento9: datetime | None = Field(default=None, alias="vencimento parcela9") vencimento10: datetime | None = Field(default=None, alias="vencimento parcela10") vencimento11: datetime | None = Field(default=None, alias="vencimento parcela11") vencimento12: datetime | None = Field(default=None, alias="vencimento parcela12") @property def parcelas(self) -> dict[int, Parcela]: """Junta parcelaN + vencimento parcelaN, ignorando os slots vazios.""" parcelas = {} for n in range(1, 13): valor = getattr(self, f"parcela{n}") if valor is None: continue parcelas[n] = Parcela( valor=valor, vencimento=getattr(self, f"vencimento{n}"), ) return parcelas @property def total_parcelas(self) -> float: return round(sum(p.valor for p in self.parcelas.values()), 2) class DadosCompras(BaseModel): id: str author: Autor properties: ComprasProperties class PayloadCompras(BaseModel): # Chave de deduplicacao: o id do processo no Holmes. Como ele reentrega # webhook, sem isso todo reenvio vira linha duplicada no banco do cliente. id_processo: str protocolo: str cnpj: str pedido_linx: str fornecedor: str tipo: str nf_entrada: str | None aprovador: str valor_total: float parcelas: dict[int, Parcela]