brewman/brewman/brewman/schemas/input.py

194 lines
5.8 KiB
Python

import json
import uuid
from datetime import date, datetime
from decimal import Decimal
from typing import List, Optional
from brewman.schemas import to_camel
from brewman.schemas.master import AccountLink, CostCentreLink
from brewman.schemas.voucher import (
EmployeeBenefit,
Incentive,
Inventory,
Journal,
VoucherIn,
)
from fastapi import Form
from pydantic import BaseModel, Field, validator
from sqlalchemy.orm import Session
class JournalIn(VoucherIn):
journals: List[Journal]
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
json_encoders = {
date: lambda v: v.strftime("%d-%b-%Y"),
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
}
@validator("date_", pre=True)
def parse_date(cls, value):
if isinstance(value, date):
return value
return datetime.strptime(value, "%d-%b-%Y").date()
@validator("journals")
def validate_signed_amount(cls, value: List[Journal]):
if sum(x.debit * x.amount for x in value) != 0:
raise ValueError("Journal amounts do no match")
return value
@validator("journals")
def is_distinct(cls, value: List[Journal]):
journal_set = set(
hash(x.account.id_)
^ hash(None if x.cost_centre is None else x.cost_centre.id_)
for x in value
)
if len(value) != len(journal_set):
raise ValueError("Duplicate journals")
return value
@classmethod
def load_form(cls, data: str = Form(...)):
json_data = json.loads(data)
return cls.parse_obj(json_data)
class PurchaseIn(VoucherIn):
vendor: AccountLink
inventories: List[Inventory]
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
json_encoders = {
date: lambda v: v.strftime("%d-%b-%Y"),
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
}
@validator("date_", pre=True)
def parse_date(cls, value):
if isinstance(value, date):
return value
return datetime.strptime(value, "%d-%b-%Y").date()
@validator("inventories") # For Purchase, Issue and Return Vouchers
def validate_enough_inventories(cls, value: List[Inventory]):
if len(value) < 1:
raise ValueError("Not enough inventories")
return value
@validator("inventories") # For Purchase, Issue and Return Vouchers
def validate_inventories_unique(cls, value: List[Inventory]):
if len(set(x.product.id_ for x in value)) != len(value):
raise ValueError("Duplicate products")
return value
@classmethod
def load_form(cls, data: str = Form(...)):
json_data = json.loads(data)
return cls.parse_obj(json_data)
class IssueIn(VoucherIn):
source: CostCentreLink
destination: CostCentreLink
inventories: List[Inventory]
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
json_encoders = {
date: lambda v: v.strftime("%d-%b-%Y"),
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
}
@validator("date_", pre=True)
def parse_date(cls, value):
if isinstance(value, date):
return value
return datetime.strptime(value, "%d-%b-%Y").date()
@validator("inventories") # For Purchase, Issue and Return Vouchers
def validate_enough_inventories(cls, value: List[Inventory]):
if len(value) < 1:
raise ValueError("Not enough inventories")
return value
@validator("inventories") # For Purchase, Issue and Return Vouchers
def validate_inventories_unique(cls, value: List[Inventory]):
if len(set(x.product.id_ for x in value)) != len(value):
raise ValueError("Duplicate products")
return value
@validator("destination") # For Purchase, Issue and Return Vouchers
def source_destination_unique(cls, value: CostCentreLink, values):
if value.id_ == values["source"].id_:
raise ValueError("Source and destination cannot be the same")
return value
@classmethod
def load_form(cls, data: str = Form(...)):
json_data = json.loads(data)
return cls.parse_obj(json_data)
class EmployeeBenefitIn(VoucherIn):
employee_benefits: List[EmployeeBenefit]
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
json_encoders = {
date: lambda v: v.strftime("%d-%b-%Y"),
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
}
@validator("date_", pre=True)
def parse_date(cls, value):
if isinstance(value, date):
return value
return datetime.strptime(value, "%d-%b-%Y").date()
@classmethod
def load_form(cls, data: str = Form(...)):
json_data = json.loads(data)
return cls.parse_obj(json_data)
class IncentiveIn(VoucherIn):
incentives: List[Incentive]
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
json_encoders = {
date: lambda v: v.strftime("%d-%b-%Y"),
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
}
@validator("date_", pre=True)
def parse_date(cls, value):
if isinstance(value, date):
return value
return datetime.strptime(value, "%d-%b-%Y").date()
@classmethod
def load_form(cls, data: str = Form(...)):
json_data = json.loads(data)
return cls.parse_obj(json_data)
class IncentiveEmployee(BaseModel):
id_: Optional[uuid.UUID]
employee_id: uuid.UUID
cost_centre_id: uuid.UUID
journal: Optional[Journal]
days_worked: Decimal = Field(ge=0, multiple_of=0.5)
points: Decimal = Field(ge=0, multiple_of=0.01)