194 lines
5.8 KiB
Python
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)
|