Chore: Mypy work going on
Fix: Recipes costing of semi items would show very high cost of the whole recipe for per unit as ingredient
This commit is contained in:
1 parent
ddd389a899
commit
ee7f036ced
47 files changed
+487
-437
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
[flake8]
|
||||
ignore = E203, W503
|
||||
ignore = E203, W503, E501
|
||||
max-line-length = 120
|
||||
exclude = .git,__pycache__,__init__.py,.mypy_cache,.pytest_cache
|
||||
@@ -66,7 +66,7 @@ def authenticate_user(username: str, password: str, db: Session) -> Optional[Use
|
||||
|
||||
|
||||
def client_allowed(user: UserModel, client_id: int, otp: Optional[int], db: Session) -> Tuple[bool, Client]:
|
||||
client: Client = (
|
||||
client: Optional[Client] = (
|
||||
db.execute(select(Client).where(Client.code == client_id)).scalar_one_or_none() if client_id else None
|
||||
)
|
||||
if client is None:
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
from datetime import date, timedelta
|
||||
from typing import Union
|
||||
|
||||
|
||||
def get_date(session: dict) -> str:
|
||||
if "date" not in session:
|
||||
session["date"] = date.today().strftime("%d-%b-%Y")
|
||||
return session["date"]
|
||||
return session["date"] # type: ignore[no-any-return]
|
||||
|
||||
|
||||
def set_date(date_: str, session: dict) -> str:
|
||||
session["date"] = date_
|
||||
return session["date"]
|
||||
def set_date(date_: Union[str, date], session: dict) -> None:
|
||||
session["date"] = date_ if isinstance(date_, str) else date_.strftime("%d-%b-%Y")
|
||||
|
||||
|
||||
def get_start_date(session: dict) -> str:
|
||||
if "start" not in session:
|
||||
session["start"] = get_first_day(date.today()).strftime("%d-%b-%Y")
|
||||
return session["start"]
|
||||
return session["start"] # type: ignore[no-any-return]
|
||||
|
||||
|
||||
def get_finish_date(session: dict) -> str:
|
||||
if "finish" not in session:
|
||||
session["finish"] = get_last_day(date.today()).strftime("%d-%b-%Y")
|
||||
return session["finish"]
|
||||
return session["finish"] # type: ignore[no-any-return]
|
||||
|
||||
|
||||
def set_period(start, finish, session: dict):
|
||||
def set_period(start: Union[str, date], finish: Union[str, date], session: dict) -> None:
|
||||
if start is not None:
|
||||
session["start"] = start if isinstance(start, str) else start.strftime("%d-%b-%Y")
|
||||
if finish is not None:
|
||||
|
||||
@@ -8,5 +8,5 @@ from ..core.config import settings
|
||||
|
||||
logging.basicConfig()
|
||||
logging.getLogger("sqlalchemy.engine").setLevel(settings.LOG_LEVEL)
|
||||
engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True, future=True)
|
||||
engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True, future=True) # type: ignore[arg-type]
|
||||
SessionFuture = sessionmaker(autoflush=False, bind=engine, future=True)
|
||||
@@ -1,8 +1,4 @@
|
||||
import re
|
||||
import uuid
|
||||
|
||||
from datetime import date, timedelta
|
||||
from decimal import Decimal
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from sqlalchemy import or_, select
|
||||
@@ -42,7 +38,7 @@ def get_lock_info(
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
data = sorted(data, key=lambda d: d["index"], reverse=True)
|
||||
data = sorted(data, key=lambda d: d["index"], reverse=True) # type: ignore[no-any-return]
|
||||
for it in data:
|
||||
li: LockInformation = LockInformation(
|
||||
voucherTypes=[VoucherTypesSelected(id=vt["id_"], name=vt["name"]) for vt in it["voucher_types"]],
|
||||
@@ -77,30 +73,3 @@ def get_lock_info(
|
||||
|
||||
return True, "Voucher allowed"
|
||||
return False, "Default Fallthrough"
|
||||
|
||||
|
||||
def to_uuid(value):
|
||||
p = re.compile("^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$")
|
||||
return uuid.UUID(value) if p.match(value) else None
|
||||
|
||||
|
||||
def to_decimal(value, default=0):
|
||||
import re
|
||||
|
||||
_parser = re.compile(
|
||||
r""" # A numeric string consists of:
|
||||
(?P<sign>[-+])? # an optional sign, followed by either...
|
||||
(
|
||||
(?=\d|\.\d) # ...a number (with at least one digit)
|
||||
(?P<int>\d*) # having a (possibly empty) integer part
|
||||
(\.(?P<frac>\d*))? # followed by an optional fractional part
|
||||
|
|
||||
(?P<signal>s)? # ...an (optionally signaling)
|
||||
NaN # NaN
|
||||
(?P<diag>\d*) # with (possibly empty) diagnostic info.
|
||||
)
|
||||
\Z
|
||||
""",
|
||||
re.VERBOSE | re.IGNORECASE,
|
||||
).match
|
||||
return Decimal(value) if _parser(value.strip()) is not None else default
|
||||
@@ -1,8 +1,8 @@
|
||||
import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import List
|
||||
from typing import List, Optional
|
||||
|
||||
import brewman.schemas.account as schemas
|
||||
|
||||
@@ -20,6 +20,7 @@ from ..models.cost_centre import CostCentre
|
||||
from ..models.journal import Journal
|
||||
from ..models.voucher import Voucher
|
||||
from ..models.voucher_type import VoucherType
|
||||
from ..schemas.balance import AccountBalance
|
||||
from ..schemas.user import UserToken
|
||||
|
||||
|
||||
@@ -121,7 +122,7 @@ async def show_list(user: UserToken = Depends(get_user)) -> List[schemas.Account
|
||||
]
|
||||
|
||||
|
||||
@router.get("/query")
|
||||
@router.get("/query", response_model=List[schemas.AccountLink])
|
||||
async def show_term(
|
||||
q: str,
|
||||
t: int = None,
|
||||
@@ -129,26 +130,26 @@ async def show_term(
|
||||
a: bool = None,
|
||||
c: int = None,
|
||||
current_user: UserToken = Depends(get_user),
|
||||
):
|
||||
) -> List[schemas.AccountLink]:
|
||||
count = c
|
||||
list_ = []
|
||||
list_: List[schemas.AccountLink] = []
|
||||
with SessionFuture() as db:
|
||||
for index, item in enumerate(AccountBase.query(q, t, r, a, db)):
|
||||
list_.append({"id": item.id, "name": item.name})
|
||||
list_.append(schemas.AccountLink(id=item.id, name=item.name))
|
||||
if count is not None and index == count - 1:
|
||||
break
|
||||
return list_
|
||||
|
||||
|
||||
@router.get("/{id_}/balance")
|
||||
@router.get("/{id_}/balance", response_model=AccountBalance)
|
||||
async def show_balance(
|
||||
id_: uuid.UUID,
|
||||
d: str = None,
|
||||
user: UserToken = Depends(get_user),
|
||||
):
|
||||
date = None if d is None or d == "" else datetime.strptime(d, "%d-%b-%Y")
|
||||
) -> AccountBalance:
|
||||
date_ = None if d is None or d == "" else datetime.strptime(d, "%d-%b-%Y")
|
||||
with SessionFuture() as db:
|
||||
return {"date": balance(id_, date, db), "total": balance(id_, None, db)}
|
||||
return AccountBalance(date=balance(id_, date_, db), total=balance(id_, None, db))
|
||||
|
||||
|
||||
@router.get("/{id_}", response_model=schemas.Account)
|
||||
@@ -161,17 +162,17 @@ def show_id(
|
||||
return account_info(item)
|
||||
|
||||
|
||||
def balance(id_: uuid.UUID, date, db: Session) -> Decimal:
|
||||
def balance(id_: uuid.UUID, date_: Optional[date], db: Session) -> Decimal:
|
||||
account: AccountBase = db.execute(select(AccountBase).where(AccountBase.id == id_)).scalar_one()
|
||||
if not account.type_.balance_sheet:
|
||||
return Decimal(0)
|
||||
|
||||
bal = select(func.sum(Journal.amount * Journal.debit)).join(Journal.voucher)
|
||||
if date is not None:
|
||||
bal = bal.where(Voucher.date <= date)
|
||||
if date_ is not None:
|
||||
bal = bal.where(Voucher.date <= date_)
|
||||
|
||||
bal = bal.where(Voucher.voucher_type != VoucherType.ISSUE).where(Journal.account_id == id_)
|
||||
result: Decimal = db.execute(bal).scalar_one_or_none()
|
||||
result: Optional[Decimal] = db.execute(bal).scalar_one_or_none()
|
||||
return Decimal(0) if result is None else result
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from datetime import date, datetime, timedelta
|
||||
from typing import Generator, List
|
||||
|
||||
import brewman.schemas.attendance as schemas
|
||||
|
||||
@@ -20,8 +21,10 @@ router = APIRouter()
|
||||
|
||||
|
||||
@router.get("", response_model=schemas.Attendance)
|
||||
def attendance_blank(request: Request, user: UserToken = Security(get_user, scopes=["attendance"])):
|
||||
return {"date": get_date(request.session), "body": []}
|
||||
def attendance_blank(
|
||||
request: Request, user: UserToken = Security(get_user, scopes=["attendance"])
|
||||
) -> schemas.Attendance:
|
||||
return schemas.Attendance(date=get_date(request.session), body=[])
|
||||
|
||||
|
||||
@router.get("/{date_}", response_model=schemas.Attendance)
|
||||
@@ -29,17 +32,17 @@ def attendance_date(
|
||||
date_: str,
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["attendance"]),
|
||||
):
|
||||
) -> schemas.Attendance:
|
||||
set_date(date_, request.session)
|
||||
with SessionFuture() as db:
|
||||
return {
|
||||
"date": date_,
|
||||
"body": attendance_date_report(datetime.strptime(date_, "%d-%b-%Y"), db),
|
||||
}
|
||||
return schemas.Attendance(
|
||||
date=date_,
|
||||
body=attendance_date_report(datetime.strptime(date_, "%d-%b-%Y"), db),
|
||||
)
|
||||
|
||||
|
||||
def attendance_date_report(date_: date, db: Session):
|
||||
body = []
|
||||
def attendance_date_report(date_: date, db: Session) -> List[schemas.AttendanceItem]:
|
||||
body: List[schemas.AttendanceItem] = []
|
||||
employees = (
|
||||
db.execute(
|
||||
select(Employee)
|
||||
@@ -93,7 +96,7 @@ def save(
|
||||
date_: str,
|
||||
data: schemas.Attendance,
|
||||
user: UserToken = Security(get_user, scopes=["attendance"]),
|
||||
):
|
||||
) -> schemas.Attendance:
|
||||
try:
|
||||
att_date = datetime.strptime(date_, "%d-%b-%Y").date()
|
||||
with SessionFuture() as db:
|
||||
@@ -107,7 +110,7 @@ def save(
|
||||
)
|
||||
attendance.create(db)
|
||||
db.commit()
|
||||
return {"date": date_, "body": attendance_date_report(att_date, db)}
|
||||
return schemas.Attendance(date=date_, body=attendance_date_report(att_date, db))
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
@@ -115,7 +118,9 @@ def save(
|
||||
)
|
||||
|
||||
|
||||
def date_range(start: date, stop: date, step=timedelta(days=1), inclusive=False):
|
||||
def date_range(
|
||||
start: date, stop: date, step: timedelta = timedelta(days=1), inclusive: bool = False
|
||||
) -> Generator[date, None, None]:
|
||||
# inclusive=False to behave like range by default
|
||||
if step.days > 0:
|
||||
while start < stop:
|
||||
|
||||
@@ -18,12 +18,12 @@ from .attendance import date_range
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
@router.get("", response_class=StreamingResponse)
|
||||
def get_report(
|
||||
s: str,
|
||||
f: str,
|
||||
# user: UserToken = Security(get_user, scopes=["attendance"]) ## removed as jwt headers are a pain in the ass
|
||||
):
|
||||
) -> StreamingResponse:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
output = io.StringIO()
|
||||
@@ -41,7 +41,7 @@ def get_report(
|
||||
# output.close()
|
||||
|
||||
|
||||
def attendance_record(start_date: date, finish_date: date, output, db: Session):
|
||||
def attendance_record(start_date: date, finish_date: date, output: io.StringIO, db: Session) -> None:
|
||||
header = ["Code", "Name", "Designation", "Department", "Salary", "Points"]
|
||||
for date_ in date_range(start_date, finish_date, inclusive=True):
|
||||
header.append(date_.strftime("%d-%b"))
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
from typing import List
|
||||
|
||||
import brewman.schemas.attendance_type as schemas
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
@@ -8,10 +12,10 @@ from ..schemas.user import UserToken
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def show_list(user: UserToken = Depends(get_user)):
|
||||
@router.get("", response_model=List[schemas.AttendanceType])
|
||||
async def show_list(user: UserToken = Depends(get_user)) -> List[schemas.AttendanceType]:
|
||||
list_ = AttendanceType.list()
|
||||
attendance_types = []
|
||||
attendance_types: List[schemas.AttendanceType] = []
|
||||
for item in list_:
|
||||
attendance_types.append({"id": item.id, "name": item.name, "value": item.value})
|
||||
attendance_types.append(schemas.AttendanceType(id=item.id, name=item.name, value=item.value))
|
||||
return attendance_types
|
||||
@@ -18,12 +18,12 @@ from ..schemas.user import UserToken
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.put("/{id_}")
|
||||
@router.put("/{id_}", response_model=None)
|
||||
def update_route(
|
||||
id_: uuid.UUID,
|
||||
data: schemas.ClientIn,
|
||||
user: UserToken = Security(get_user, scopes=["clients"]),
|
||||
):
|
||||
) -> None:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Client = db.execute(select(Client).where(Client.id == id_)).scalar_one()
|
||||
@@ -32,7 +32,6 @@ def update_route(
|
||||
item.otp = None
|
||||
item.name = data.name
|
||||
db.commit()
|
||||
return {}
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
@@ -40,18 +39,17 @@ def update_route(
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{id_}")
|
||||
@router.delete("/{id_}", response_model=None)
|
||||
def delete_route(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["clients"]),
|
||||
):
|
||||
) -> None:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Client = db.execute(select(Client).where(Client.id == id_)).scalar_one()
|
||||
db.execute(delete(LoginHistory).where(LoginHistory.client_id == item.id))
|
||||
db.delete(item)
|
||||
db.commit()
|
||||
return {}
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
@@ -82,17 +80,17 @@ async def show_list(
|
||||
return clients
|
||||
|
||||
|
||||
@router.get("/{id_}")
|
||||
@router.get("/{id_}", response_model=schemas.Client)
|
||||
def show_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["clients"]),
|
||||
):
|
||||
) -> schemas.Client:
|
||||
with SessionFuture() as db:
|
||||
item: Client = db.execute(select(Client).where(Client.id == id_)).scalar_one()
|
||||
return {
|
||||
"id": item.id,
|
||||
"code": item.code,
|
||||
"name": item.name,
|
||||
"enabled": item.enabled,
|
||||
"otp": item.otp,
|
||||
}
|
||||
return schemas.Client(
|
||||
id=item.id,
|
||||
code=item.code,
|
||||
name=item.name,
|
||||
enabled=item.enabled,
|
||||
otp=item.otp,
|
||||
)
|
||||
@@ -61,11 +61,11 @@ def update_route(
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{id_}", response_model=schemas.CostCentreBlank)
|
||||
@router.delete("/{id_}", response_model=None)
|
||||
def delete_route(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["cost-centres"]),
|
||||
):
|
||||
) -> None:
|
||||
with SessionFuture() as db:
|
||||
item: CostCentre = db.execute(select(CostCentre).where(CostCentre.id == id_)).scalar_one()
|
||||
if item.is_fixture:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from calendar import monthrange
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Body, HTTPException, Security, status
|
||||
from sqlalchemy import or_, select
|
||||
@@ -15,17 +17,18 @@ from ..models.employee import Employee
|
||||
from ..models.journal import Journal
|
||||
from ..models.voucher import Voucher
|
||||
from ..models.voucher_type import VoucherType
|
||||
from ..schemas.message import Message
|
||||
from ..schemas.user import UserToken
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("")
|
||||
@router.post("", response_model=Message)
|
||||
def credit_salary(
|
||||
month: str = Body(..., embed=True),
|
||||
user: UserToken = Security(get_user, scopes=["attendance"]),
|
||||
):
|
||||
) -> Message:
|
||||
month_ = datetime.strptime(month, "%d-%b-%Y").date()
|
||||
start_date = get_first_day(month_)
|
||||
finish_date = get_last_day(month_)
|
||||
@@ -43,13 +46,13 @@ def credit_salary(
|
||||
voucher.journals.append(item)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
return {"message": "Salary Entry created"}
|
||||
return Message(message="Salary Entry created")
|
||||
|
||||
|
||||
def salary_journals(start_date: date, finish_date: date, db: Session):
|
||||
def salary_journals(start_date: date, finish_date: date, db: Session) -> List[Journal]:
|
||||
days = monthrange(start_date.year, start_date.month)[1]
|
||||
amount = 0
|
||||
journals = []
|
||||
amount = Decimal(0)
|
||||
journals: List[Journal] = []
|
||||
employees = (
|
||||
db.execute(
|
||||
select(Employee)
|
||||
|
||||
@@ -17,8 +17,8 @@ from ..models.db_image import DbImage
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/{id_}/{type_}")
|
||||
def db_image(id_: uuid.UUID, type_: str):
|
||||
@router.get("/{id_}/{type_}", response_class=StreamingResponse)
|
||||
def db_image(id_: uuid.UUID, type_: str) -> StreamingResponse:
|
||||
with SessionFuture() as db:
|
||||
item = db.execute(select(DbImage).where(DbImage.id == id_)).scalar_one()
|
||||
if type_ == "thumbnail":
|
||||
@@ -28,7 +28,7 @@ def db_image(id_: uuid.UUID, type_: str):
|
||||
return StreamingResponse(item, media_type="image/jpeg")
|
||||
|
||||
|
||||
def save_files(voucher_id: uuid.UUID, i: List[bytes], t: List[bytes], db: Session):
|
||||
def save_files(voucher_id: uuid.UUID, i: List[bytes], t: List[bytes], db: Session) -> None:
|
||||
i = i or []
|
||||
t = t or []
|
||||
for index, value in enumerate(i):
|
||||
@@ -41,7 +41,7 @@ def update_files(
|
||||
i: List[bytes],
|
||||
t: List[bytes],
|
||||
db: Session,
|
||||
):
|
||||
) -> None:
|
||||
i = i or []
|
||||
t = t or []
|
||||
old = [f.id_ for f in data if f.id_]
|
||||
|
||||
@@ -5,23 +5,21 @@ from sqlalchemy.orm import Session
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
from ..db.session import SessionFuture
|
||||
from ..models.attendance import Attendance
|
||||
from ..schemas.settings import AttendanceCount
|
||||
from ..schemas.user import UserToken
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("")
|
||||
def post_check_db(user: UserToken = Security(get_user)):
|
||||
info = {}
|
||||
|
||||
@router.post("", response_model=AttendanceCount)
|
||||
def post_check_db(user: UserToken = Security(get_user)) -> AttendanceCount:
|
||||
with SessionFuture() as db:
|
||||
duplicate_attendances = get_duplicate_attendances(db)
|
||||
if duplicate_attendances > 0:
|
||||
fix_duplicate_attendances(db)
|
||||
info["attendanceCount"] = duplicate_attendances
|
||||
db.commit()
|
||||
return info
|
||||
return AttendanceCount(attendanceCount=duplicate_attendances)
|
||||
|
||||
|
||||
def get_duplicate_attendances(db: Session) -> int:
|
||||
@@ -37,7 +35,7 @@ def get_duplicate_attendances(db: Session) -> int:
|
||||
select(func.count(Attendance.id)).where(
|
||||
~Attendance.id.in_(sub_query), Attendance.is_valid == True # noqa: E712
|
||||
)
|
||||
).scalar()
|
||||
).scalar_one()
|
||||
return query
|
||||
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ def show_blank(
|
||||
|
||||
|
||||
@router.get("/list", response_model=List[schemas.Employee])
|
||||
async def show_list(user: UserToken = Depends(get_user)):
|
||||
async def show_list(user: UserToken = Depends(get_user)) -> List[schemas.Employee]:
|
||||
with SessionFuture() as db:
|
||||
return [
|
||||
employee_info(item)
|
||||
@@ -127,25 +127,25 @@ async def show_list(user: UserToken = Depends(get_user)):
|
||||
]
|
||||
|
||||
|
||||
@router.get("/query")
|
||||
@router.get("/query", response_model=List[schemas.EmployeeLink])
|
||||
async def show_term(
|
||||
q: str,
|
||||
c: int = None,
|
||||
current_user: UserToken = Depends(get_user),
|
||||
):
|
||||
list_ = []
|
||||
) -> List[schemas.EmployeeLink]:
|
||||
list_: List[schemas.EmployeeLink] = []
|
||||
with SessionFuture() as db:
|
||||
for index, item in enumerate(Employee.query(q=q, type_=10, reconcilable=None, active=None, db=db)):
|
||||
list_.append(
|
||||
{
|
||||
"id": item.id,
|
||||
"name": item.name,
|
||||
"designation": item.designation,
|
||||
"costCentre": {
|
||||
"id": item.cost_centre.id,
|
||||
"name": item.cost_centre.name,
|
||||
},
|
||||
}
|
||||
schemas.EmployeeLink(
|
||||
id=item.id,
|
||||
name=item.name,
|
||||
designation=item.designation,
|
||||
costCentre=schemas.CostCentreLink(
|
||||
id=item.cost_centre.id,
|
||||
name=item.cost_centre.name,
|
||||
),
|
||||
)
|
||||
)
|
||||
if c is not None and index == c - 1:
|
||||
break
|
||||
@@ -196,7 +196,7 @@ def employee_blank() -> schemas.EmployeeBlank:
|
||||
)
|
||||
|
||||
|
||||
def delete_with_data(employee: Employee, db: Session):
|
||||
def delete_with_data(employee: Employee, db: Session) -> None:
|
||||
suspense_account = db.execute(select(Account).where(Account.id == Account.suspense())).scalar_one()
|
||||
query = (
|
||||
db.execute(
|
||||
|
||||
@@ -49,7 +49,7 @@ def employee_attendance_report(
|
||||
finish_date = datetime.strptime(f or get_finish_date(request.session), "%d-%b-%Y").date()
|
||||
start_date = employee.joining_date if employee.joining_date > start_date else start_date
|
||||
finish_date = (
|
||||
employee.leaving_date if not employee.is_active and employee.leaving_date < finish_date else finish_date
|
||||
employee.leaving_date if not employee.is_active and employee.leaving_date < finish_date else finish_date # type: ignore[assignment]
|
||||
)
|
||||
info = schemas.EmployeeAttendance(
|
||||
startDate=start_date,
|
||||
|
||||
@@ -2,7 +2,7 @@ import uuid
|
||||
|
||||
from datetime import date, datetime
|
||||
from math import ceil
|
||||
from typing import List
|
||||
from typing import List, Tuple
|
||||
|
||||
import brewman.schemas.input as schema_in
|
||||
import brewman.schemas.voucher as output
|
||||
@@ -93,7 +93,7 @@ def save_employee_benefits(
|
||||
employee_benefits: List[EmployeeBenefitSchema],
|
||||
days_in_month: int,
|
||||
db: Session,
|
||||
):
|
||||
) -> Tuple[int, int]:
|
||||
total_exp, total_total = 0, 0
|
||||
for item in employee_benefits:
|
||||
account = db.execute(select(Employee).where(Employee.id == item.employee.id_)).scalar_one()
|
||||
@@ -125,7 +125,7 @@ def save_employee_benefits(
|
||||
return total_exp, total_total
|
||||
|
||||
|
||||
def save_journals(voucher: Voucher, exp: int, total: int, db: Session):
|
||||
def save_journals(voucher: Voucher, exp: int, total: int, db: Session) -> None:
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == AccountBase.esi_pf_expense())).scalar_one()
|
||||
journal = Journal(
|
||||
amount=exp,
|
||||
@@ -154,7 +154,7 @@ def update_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["employee-benefit"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
dt = get_last_day(data.date_)
|
||||
days_in_month = dt.day
|
||||
@@ -212,7 +212,7 @@ def update_employee_benefits(
|
||||
employee_benefits: List[EmployeeBenefitSchema],
|
||||
days_in_month: int,
|
||||
db: Session,
|
||||
):
|
||||
) -> Tuple[int, int]:
|
||||
exp, total = 0, 0
|
||||
for i in range(len(voucher.employee_benefits), 0, -1):
|
||||
item = voucher.employee_benefits[i - 1]
|
||||
@@ -228,7 +228,7 @@ def update_employee_benefits(
|
||||
return exp + new_exp, total + new_total
|
||||
|
||||
|
||||
def update_journals(voucher: Voucher, exp: int, total: int):
|
||||
def update_journals(voucher: Voucher, exp: int, total: int) -> None:
|
||||
journal = next(i for i in voucher.journals if i.account_id == AccountBase.esi_pf_expense())
|
||||
journal.amount = exp
|
||||
journal = next(i for i in voucher.journals if i.account_id == AccountBase.esi_pf_payable())
|
||||
@@ -239,7 +239,7 @@ def update_journals(voucher: Voucher, exp: int, total: int):
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["employee-benefit"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
@@ -255,13 +255,13 @@ def get_id(
|
||||
def show_blank(
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["employee-benefit"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
additional_info = BlankVoucherInfo(date=get_date(request.session), type=VoucherType.EMPLOYEE_BENEFIT)
|
||||
with SessionFuture() as db:
|
||||
return blank_voucher(additional_info, db)
|
||||
|
||||
|
||||
def esi_contribution(gross_salary, days_worked, days_in_month):
|
||||
def esi_contribution(gross_salary: int, days_worked: int, days_in_month: int) -> Tuple[int, int, int]:
|
||||
limit = 21000
|
||||
employee_rate = 0.0175
|
||||
employer_rate = 0.0475
|
||||
@@ -270,7 +270,7 @@ def esi_contribution(gross_salary, days_worked, days_in_month):
|
||||
return employee, employer, employee + employer
|
||||
|
||||
|
||||
def pf_contribution(gross_salary, days_worked, days_in_month):
|
||||
def pf_contribution(gross_salary: int, days_worked: int, days_in_month: int) -> Tuple[int, int, int]:
|
||||
limit = 15000
|
||||
employee_rate = 0.12
|
||||
employer_rate = 0.12 + 0.011 + 0.005 + 0.0001
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import csv
|
||||
import io
|
||||
import uuid
|
||||
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from io import StringIO
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
import brewman.schemas.fingerprint as schemas
|
||||
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
||||
from sqlalchemy import bindparam, select
|
||||
@@ -20,20 +24,20 @@ from ..schemas.user import UserToken
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("")
|
||||
@router.post("", response_model=None)
|
||||
def upload_prints(
|
||||
fingerprints: UploadFile = File(None),
|
||||
user: UserToken = Depends(get_user),
|
||||
):
|
||||
) -> None:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
start = date.today() - timedelta(days=90)
|
||||
finish = date.today() + timedelta(days=7)
|
||||
employees = {}
|
||||
employees: Dict[int, uuid.UUID] = {}
|
||||
for id_, code in db.execute(select(Employee.id, Employee.code)).all():
|
||||
employees[code] = id_
|
||||
file_data = read_file(fingerprints)
|
||||
prints = [d for d in fp(file_data, employees) if start <= d["date"].date() <= finish]
|
||||
prints = [d for d in fp(file_data, employees) if start <= d.date <= finish]
|
||||
paged_data = [prints[i : i + 100] for i in range(0, len(prints), 100)]
|
||||
for i, page in enumerate(paged_data):
|
||||
print(f"Processing page {i} of {len(paged_data)}")
|
||||
@@ -47,10 +51,9 @@ def upload_prints(
|
||||
}
|
||||
)
|
||||
.on_conflict_do_nothing(),
|
||||
page,
|
||||
[p.dict() for p in page],
|
||||
)
|
||||
db.commit()
|
||||
return {}
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
@@ -58,7 +61,7 @@ def upload_prints(
|
||||
)
|
||||
|
||||
|
||||
def read_file(input_file: UploadFile):
|
||||
def read_file(input_file: UploadFile) -> io.StringIO:
|
||||
input_file.file.seek(0)
|
||||
output = bytearray()
|
||||
while 1:
|
||||
@@ -77,24 +80,24 @@ def read_file(input_file: UploadFile):
|
||||
return StringIO(output.decode(encoding))
|
||||
|
||||
|
||||
def fp(file_data, employees):
|
||||
fingerprints = []
|
||||
def fp(file_data: StringIO, employees: Dict[int, uuid.UUID]) -> List[schemas.Fingerprint]:
|
||||
fingerprints: List[schemas.Fingerprint] = []
|
||||
reader = csv.reader(file_data, delimiter="\t")
|
||||
header = next(reader, None)
|
||||
header = next(reader)
|
||||
employee_column = 2
|
||||
date_column = len(header) - 1
|
||||
date_format = "%Y/%m/%d %H:%M:%S" if date_column == 6 else "%Y-%m-%d %H:%M:%S"
|
||||
for row in reader:
|
||||
try:
|
||||
employee_code = int(row[employee_column]) # EnNo
|
||||
date_ = datetime.strptime(row[date_column], date_format)
|
||||
date_ = datetime.strptime(row[date_column], date_format).date()
|
||||
if employee_code in employees.keys():
|
||||
fingerprints.append(
|
||||
{
|
||||
"id": uuid.uuid4(),
|
||||
"employee_id": employees[employee_code],
|
||||
"date": date_,
|
||||
}
|
||||
schemas.Fingerprint(
|
||||
id=uuid.uuid4(),
|
||||
employee_id=employees[employee_code],
|
||||
date=date_,
|
||||
)
|
||||
)
|
||||
except ValueError:
|
||||
continue
|
||||
@@ -112,7 +115,7 @@ def fp(file_data, employees):
|
||||
# return Fingerprint.__table__.insert().from_select([Fingerprint.id, Fingerprint.employee_id, Fingerprint.date], sel)
|
||||
|
||||
|
||||
def get_prints(employee_id: uuid.UUID, date_: date, db: Session):
|
||||
def get_prints(employee_id: uuid.UUID, date_: date, db: Session) -> Tuple[str, str, bool]:
|
||||
prints = (
|
||||
db.execute(
|
||||
select(Fingerprint)
|
||||
@@ -136,7 +139,7 @@ def get_prints(employee_id: uuid.UUID, date_: date, db: Session):
|
||||
last = item
|
||||
|
||||
if len(prints) == 0:
|
||||
hours_worked, full_day = "", None
|
||||
hours_worked, full_day = "", False
|
||||
elif len(prints) == 2:
|
||||
time_worked = prints[1].date - prints[0].date
|
||||
hours_worked, full_day = working_hours(time_worked)
|
||||
@@ -152,7 +155,7 @@ def get_prints(employee_id: uuid.UUID, date_: date, db: Session):
|
||||
)
|
||||
|
||||
|
||||
def working_hours(delta: timedelta):
|
||||
def working_hours(delta: timedelta) -> Tuple[str, bool]:
|
||||
minutes = (delta.seconds // 60) % 60
|
||||
minutes = int(5 * round(float(minutes) / 5))
|
||||
hours = delta.seconds // 3600
|
||||
|
||||
@@ -40,7 +40,7 @@ def save_route(
|
||||
request: Request,
|
||||
data: schema_in.IncentiveIn = Depends(schema_in.IncentiveIn.load_form),
|
||||
user: UserToken = Security(get_user, scopes=["incentive"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = save(data, user, db)
|
||||
@@ -91,7 +91,7 @@ def save_incentives(
|
||||
employees: List[schema_in.IncentiveEmployee],
|
||||
point_value: Decimal,
|
||||
db: Session,
|
||||
):
|
||||
) -> None:
|
||||
total_amount = 0
|
||||
for item in employees:
|
||||
item_amount = round(item.points * item.days_worked * point_value)
|
||||
@@ -114,13 +114,13 @@ def save_incentives(
|
||||
db.add(journal)
|
||||
|
||||
|
||||
@router.put("/{id_}")
|
||||
@router.put("/{id_}", response_model=output.Voucher)
|
||||
def update_route(
|
||||
id_: uuid.UUID,
|
||||
request: Request,
|
||||
data: schema_in.IncentiveIn = Depends(schema_in.IncentiveIn.load_form),
|
||||
user: UserToken = Security(get_user, scopes=["incentive"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = update_voucher(id_, data, user, db)
|
||||
@@ -173,7 +173,7 @@ def update_incentives(
|
||||
employees: List[schema_in.IncentiveEmployee],
|
||||
point_value: Decimal,
|
||||
db: Session,
|
||||
):
|
||||
) -> None:
|
||||
total_amount = 0
|
||||
for item in voucher.incentives:
|
||||
employee = next(e for e in employees if e.employee_id == item.journal.account_id)
|
||||
@@ -191,7 +191,7 @@ def update_incentives(
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["incentive"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
@@ -208,7 +208,7 @@ def show_blank(
|
||||
request: Request,
|
||||
d: str = None,
|
||||
user: UserToken = Security(get_user, scopes=["incentive"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
additional_info = BlankVoucherInfo(date=d or get_date(request.session), type=VoucherType.INCENTIVE)
|
||||
with SessionFuture() as db:
|
||||
return blank_voucher(additional_info, db)
|
||||
@@ -260,7 +260,7 @@ def get_employees(
|
||||
return details
|
||||
|
||||
|
||||
def balance(date_: date, voucher_id: Optional[uuid.UUID], db: Session):
|
||||
def balance(date_: date, voucher_id: Optional[uuid.UUID], db: Session) -> Decimal:
|
||||
amount = (
|
||||
select(func.sum(Journal.amount * Journal.debit))
|
||||
.join(Journal.voucher)
|
||||
@@ -279,14 +279,14 @@ def balance(date_: date, voucher_id: Optional[uuid.UUID], db: Session):
|
||||
if voucher_id is not None:
|
||||
amount = amount.where(Voucher.id != voucher_id)
|
||||
result: Optional[Decimal] = db.execute(amount).scalar_one_or_none()
|
||||
return 0 if result is None else result * -1
|
||||
return Decimal(0) if result is None else result * -1
|
||||
|
||||
|
||||
def check_if_employees_changed(
|
||||
json: List[IncentiveSchema],
|
||||
db: List[Employee],
|
||||
voucher: Optional[List[Journal]],
|
||||
):
|
||||
) -> None:
|
||||
json_ids = set(x.employee_id for x in json)
|
||||
db_ids = set(x.id for x in db)
|
||||
voucher_ids = (
|
||||
|
||||
@@ -49,7 +49,7 @@ def save_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["issue"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item, batch_consumed = save(data, user, db)
|
||||
@@ -155,7 +155,7 @@ def save_journals(
|
||||
destination: schema_in.CostCentreLink,
|
||||
amount: Decimal,
|
||||
db: Session,
|
||||
):
|
||||
) -> None:
|
||||
s = Journal(
|
||||
debit=-1,
|
||||
account_id=AccountBase.all_purchases(),
|
||||
@@ -182,7 +182,7 @@ def update_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["issue"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item, batch_consumed = update_voucher(id_, data, user, db)
|
||||
@@ -272,7 +272,7 @@ def update_inventories(
|
||||
inventories: List[InventorySchema],
|
||||
batch_consumed: Optional[bool],
|
||||
db: Session,
|
||||
):
|
||||
) -> Decimal:
|
||||
amount: Decimal = Decimal(0)
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
@@ -331,7 +331,7 @@ def update_journals(
|
||||
source: schema_in.CostCentreLink,
|
||||
destination: schema_in.CostCentreLink,
|
||||
amount: Decimal,
|
||||
):
|
||||
) -> None:
|
||||
for i in range(len(voucher.journals), 0, -1):
|
||||
item = voucher.journals[i - 1]
|
||||
if item.debit == -1:
|
||||
@@ -366,7 +366,7 @@ def refresh_voucher(id_: uuid.UUID, batch_id: uuid.UUID, db: Session) -> None:
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["issue"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
|
||||
@@ -37,7 +37,7 @@ def save_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["journal"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = save(data, user, db)
|
||||
@@ -98,7 +98,7 @@ def update_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["journal"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = update_voucher(id_, data, user, db)
|
||||
@@ -175,7 +175,7 @@ def update_voucher(id_: uuid.UUID, data: schema_in.JournalIn, user: UserToken, d
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["journal"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
|
||||
@@ -53,7 +53,7 @@ def post(
|
||||
def delete_route(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["lock-date"]),
|
||||
):
|
||||
) -> List[LockInformation]:
|
||||
with SessionFuture() as db:
|
||||
db.execute(delete(DbSetting).where(DbSetting.id == id_))
|
||||
db.commit()
|
||||
@@ -93,5 +93,5 @@ def get_info(db: Session) -> List[LockInformation]:
|
||||
finish=LockDate(days=item["finish"]["days"], date=item["finish"]["date_"]),
|
||||
index=item["index"],
|
||||
)
|
||||
for item in sorted(data, key=lambda d: d["index"], reverse=True)
|
||||
for item in sorted(data, key=lambda d: d["index"], reverse=True) # type: ignore[no-any-return]
|
||||
]
|
||||
@@ -1,4 +1,5 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Union
|
||||
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
@@ -38,7 +39,7 @@ async def login_for_access_token(
|
||||
form_data: OAuth2PasswordRequestForm = Depends(),
|
||||
client_id: int = Cookie(None),
|
||||
otp: int = Form(None),
|
||||
):
|
||||
) -> Union[Token, JSONResponse]:
|
||||
with SessionFuture() as db:
|
||||
user = authenticate_user(form_data.username, form_data.password, db)
|
||||
if not user:
|
||||
@@ -99,11 +100,11 @@ async def login_for_access_token(
|
||||
},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
return Token(access_token=access_token, token_type="bearer")
|
||||
|
||||
|
||||
@router.post("/refresh", response_model=Token)
|
||||
async def refresh_token(user: UserToken = Security(get_current_active_user)):
|
||||
async def refresh_token(user: UserToken = Security(get_current_active_user)) -> Token:
|
||||
access_token_expires = timedelta(minutes=settings.JWT_TOKEN_EXPIRE_MINUTES)
|
||||
access_token = create_access_token(
|
||||
data={
|
||||
@@ -115,4 +116,4 @@ async def refresh_token(user: UserToken = Security(get_current_active_user)):
|
||||
},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
return Token(access_token=access_token, token_type="bearer")
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Security
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -16,7 +18,7 @@ router = APIRouter()
|
||||
@router.get("", response_model=Maintenance)
|
||||
def get_maintenance(
|
||||
user: UserToken = Security(get_user),
|
||||
):
|
||||
) -> Maintenance:
|
||||
with SessionFuture() as db:
|
||||
data = db.execute(select(DbSetting).where(DbSetting.name == "Maintenance")).scalars().one_or_none()
|
||||
return info(data, db)
|
||||
@@ -26,9 +28,9 @@ def get_maintenance(
|
||||
def set_maintenance(
|
||||
data: Maintenance,
|
||||
user: UserToken = Security(get_user, scopes=["maintenance"]),
|
||||
):
|
||||
) -> Maintenance:
|
||||
with SessionFuture() as db:
|
||||
maintenance = db.execute(select(DbSetting).where(DbSetting.name == "Maintenance")).scalars().one_or_none()
|
||||
maintenance: Optional[DbSetting] = db.execute(select(DbSetting).where(DbSetting.name == "Maintenance")).scalar_one_or_none()
|
||||
if data.enabled is False and maintenance is not None:
|
||||
db.delete(maintenance)
|
||||
maintenance = None
|
||||
@@ -41,8 +43,8 @@ def set_maintenance(
|
||||
return info(maintenance, db)
|
||||
|
||||
|
||||
def info(data, db: Session):
|
||||
def info(data: Optional[DbSetting], db: Session) -> Maintenance:
|
||||
if data is None:
|
||||
return {"enabled": False, "user": ""}
|
||||
return Maintenance(enabled=False, user="")
|
||||
user = db.execute(select(User).where(User.id == data.data)).scalar_one()
|
||||
return {"enabled": True, "user": user.name}
|
||||
return Maintenance(enabled=True, user=user.name)
|
||||
@@ -50,7 +50,7 @@ def save_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["purchase"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = save(data, user, db)
|
||||
@@ -105,7 +105,7 @@ def save(data: schema_in.PurchaseIn, user: UserToken, db: Session) -> Voucher:
|
||||
return voucher
|
||||
|
||||
|
||||
def save_inventories(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[InventorySchema], db: Session):
|
||||
def save_inventories(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[InventorySchema], db: Session) -> None:
|
||||
for item in inventories:
|
||||
sku: StockKeepingUnit = db.execute(
|
||||
select(StockKeepingUnit).where(StockKeepingUnit.id == item.batch.sku.id_)
|
||||
@@ -141,7 +141,7 @@ def save_inventories(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[I
|
||||
db.add(inventory)
|
||||
|
||||
|
||||
def save_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session):
|
||||
def save_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session) -> None:
|
||||
vendor = db.execute(select(AccountBase).where(AccountBase.id == ven.id_)).scalar_one()
|
||||
journals: Dict[uuid.UUID, Journal] = {}
|
||||
amount = 0
|
||||
@@ -181,7 +181,7 @@ def update_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["purchase"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = update_voucher(id_, data, user, db)
|
||||
@@ -236,7 +236,7 @@ def update_voucher(id_: uuid.UUID, data: schema_in.PurchaseIn, user: UserToken,
|
||||
return voucher
|
||||
|
||||
|
||||
def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[InventorySchema], db: Session):
|
||||
def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[InventorySchema], db: Session) -> None:
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
quantity_consumed = -1 * get_batch_quantity(item.batch_id, voucher.id, db)
|
||||
@@ -296,7 +296,7 @@ def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, inventories: List[I
|
||||
save_inventories(voucher, vendor_id, inventories, db)
|
||||
|
||||
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session):
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session) -> None:
|
||||
vendor = db.execute(select(AccountBase).where(AccountBase.id == ven.id_)).scalar_one()
|
||||
journals: Dict[uuid.UUID, Journal] = {}
|
||||
amount = Decimal(0)
|
||||
@@ -343,7 +343,7 @@ def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session):
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["purchase"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
|
||||
@@ -46,7 +46,7 @@ def save_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["purchase-return"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = save(data, user, db)
|
||||
@@ -101,7 +101,7 @@ def save(data: schema_in.PurchaseIn, user: UserToken, db: Session) -> Voucher:
|
||||
return voucher
|
||||
|
||||
|
||||
def save_inventories(voucher: Voucher, inventories: List[InventorySchema], db: Session):
|
||||
def save_inventories(voucher: Voucher, inventories: List[InventorySchema], db: Session) -> None:
|
||||
for d_item in inventories:
|
||||
batch = db.execute(select(Batch).where(Batch.id == d_item.batch.id_)).scalar_one()
|
||||
|
||||
@@ -130,7 +130,7 @@ def save_inventories(voucher: Voucher, inventories: List[InventorySchema], db: S
|
||||
db.add(item)
|
||||
|
||||
|
||||
def save_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session):
|
||||
def save_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session) -> None:
|
||||
vendor = db.execute(select(AccountBase).where(AccountBase.id == ven.id_)).scalar_one()
|
||||
journals: Dict[uuid.UUID, Journal] = {}
|
||||
amount = 0
|
||||
@@ -170,7 +170,7 @@ def update_route(
|
||||
i: List[bytes] = File(None),
|
||||
t: List[bytes] = File(None),
|
||||
user: UserToken = Security(get_user, scopes=["purchase-return"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = update_voucher(id_, data, user, db)
|
||||
@@ -228,7 +228,7 @@ def update_voucher(id_: uuid.UUID, data: schema_in.PurchaseIn, user: UserToken,
|
||||
return voucher
|
||||
|
||||
|
||||
def update_inventory(voucher: Voucher, new_inventories: List[InventorySchema], db: Session):
|
||||
def update_inventory(voucher: Voucher, new_inventories: List[InventorySchema], db: Session) -> None:
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
batch = db.execute(select(Batch).where(Batch.id == item.batch_id)).scalar_one()
|
||||
@@ -261,7 +261,7 @@ def update_inventory(voucher: Voucher, new_inventories: List[InventorySchema], d
|
||||
save_inventories(voucher, new_inventories, db)
|
||||
|
||||
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db):
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session) -> None:
|
||||
vendor = db.execute(select(AccountBase).where(AccountBase.id == ven.id_)).scalar_one()
|
||||
journals: Dict[uuid.UUID, Journal] = {}
|
||||
amount = 0
|
||||
@@ -308,7 +308,7 @@ def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db):
|
||||
def get_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["purchase-return"]),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
|
||||
@@ -94,7 +94,7 @@ async def update_route(
|
||||
)
|
||||
|
||||
|
||||
def update_items(rate_contract: RateContract, items: List[RateContractItemSchema], db: Session):
|
||||
def update_items(rate_contract: RateContract, items: List[RateContractItemSchema], db: Session) -> None:
|
||||
for it in range(len(rate_contract.items), 0, -1):
|
||||
item = rate_contract.items[it - 1]
|
||||
index = next((idx for (idx, d) in enumerate(items) if d.id_ == item.id), None)
|
||||
|
||||
@@ -30,18 +30,18 @@ from ..schemas.user import UserToken
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/{date_}")
|
||||
@router.post("/{date_}", response_model=None)
|
||||
def rebase(
|
||||
date_: str,
|
||||
user: UserToken = Security(get_user, scopes=["rebase"]),
|
||||
):
|
||||
) -> None:
|
||||
with SessionFuture() as db:
|
||||
date_ = datetime.strptime(date_, "%d-%b-%Y")
|
||||
voucher_l = opening_accounts(date_, user.id_, db)
|
||||
voucher_b = opening_batches(date_, user.id_, db)
|
||||
starred_vouchers = save_starred(date_, db)
|
||||
date_obj = datetime.strptime(date_, "%d-%b-%Y")
|
||||
voucher_l = opening_accounts(date_obj, user.id_, db)
|
||||
voucher_b = opening_batches(date_obj, user.id_, db)
|
||||
starred_vouchers = save_starred(date_obj, db)
|
||||
db.flush()
|
||||
delete_data(date_, starred_vouchers, db)
|
||||
delete_data(date_obj, starred_vouchers, db)
|
||||
db.add(voucher_l)
|
||||
for j in voucher_l.journals:
|
||||
db.add(j)
|
||||
@@ -52,13 +52,12 @@ def rebase(
|
||||
for i in voucher_b.inventories:
|
||||
db.add(i)
|
||||
db.flush()
|
||||
cleanup_lint(date_, db)
|
||||
cleanup_lint(date_obj, db)
|
||||
# request.dbsession.execute('RESET statement_timeout;')
|
||||
db.commit()
|
||||
return {}
|
||||
|
||||
|
||||
def save_starred(date_: date, db: Session):
|
||||
def save_starred(date_: date, db: Session) -> List[Voucher]:
|
||||
accounts = [
|
||||
i.id for i in db.execute(select(AccountBase.id).where(AccountBase.is_starred == True)).all() # noqa: E712
|
||||
]
|
||||
@@ -105,7 +104,7 @@ def save_starred(date_: date, db: Session):
|
||||
return vouchers
|
||||
|
||||
|
||||
def opening_accounts(date_: date, user_id: uuid.UUID, db: Session):
|
||||
def opening_accounts(date_: date, user_id: uuid.UUID, db: Session) -> Voucher:
|
||||
running_total = 0
|
||||
sum_func = func.sum(Journal.signed_amount)
|
||||
query = db.execute(
|
||||
@@ -152,7 +151,7 @@ def opening_accounts(date_: date, user_id: uuid.UUID, db: Session):
|
||||
return voucher
|
||||
|
||||
|
||||
def opening_batches(date_: date, user_id: uuid.UUID, db: Session):
|
||||
def opening_batches(date_: date, user_id: uuid.UUID, db: Session) -> Voucher:
|
||||
total = 0
|
||||
sum_func = func.sum(Journal.debit * Inventory.quantity)
|
||||
query = db.execute(
|
||||
@@ -205,7 +204,7 @@ def opening_batches(date_: date, user_id: uuid.UUID, db: Session):
|
||||
return voucher
|
||||
|
||||
|
||||
def delete_data(date_: date, vouchers: List[Voucher], db: Session):
|
||||
def delete_data(date_: date, vouchers: List[Voucher], db: Session) -> None:
|
||||
sub_voucher = aliased(Voucher)
|
||||
sub_query = select(sub_voucher.id).where(sub_voucher.date < date_).subquery()
|
||||
|
||||
@@ -225,7 +224,7 @@ def delete_data(date_: date, vouchers: List[Voucher], db: Session):
|
||||
db.execute(delete(Voucher).where(Voucher.date < date_, ~Voucher.id.in_(vouchers)))
|
||||
|
||||
|
||||
def cleanup_lint(date_: date, db: Session):
|
||||
def cleanup_lint(date_: date, db: Session) -> None:
|
||||
# Insert executes on the end so keep list of batches and journals
|
||||
db.execute(delete(Batch).where(~Batch.id.in_(select(distinct(Inventory.batch_id)).subquery())))
|
||||
db.execute(delete(Fingerprint).where(Fingerprint.date < date_))
|
||||
|
||||
@@ -30,7 +30,6 @@ from .reports import report_finish_date, report_start_date
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
# @router.post("/new") # "Recipes"
|
||||
@router.post("", response_model=schemas.Recipe)
|
||||
def save(
|
||||
data: schemas.RecipeIn,
|
||||
@@ -90,15 +89,15 @@ def save(
|
||||
recipe_cost += round(ingredient_cost * quantity, 2)
|
||||
recipe.items.append(RecipeItem(None, product.id, quantity, ingredient_cost))
|
||||
|
||||
recipe.cost_price = round(recipe_cost, 2)
|
||||
recipe.cost_price = round(recipe_cost / recipe.recipe_yield, 2)
|
||||
recipe_sku.cost_price = round(recipe.cost_price / recipe.recipe_yield, 2)
|
||||
if recipe_sku.product.is_sold:
|
||||
recipe_sku.sale_price = recipe.sale_price
|
||||
|
||||
db.add(recipe)
|
||||
for item in recipe.items:
|
||||
item.recipe_id = recipe.id
|
||||
db.add(item)
|
||||
for r_item in recipe.items:
|
||||
r_item.recipe_id = recipe.id
|
||||
db.add(r_item)
|
||||
|
||||
seen_recipes: Set[uuid.UUID] = set()
|
||||
check_recursion(recipe, seen_recipes, db)
|
||||
@@ -177,9 +176,9 @@ async def update_route(
|
||||
else:
|
||||
recipe.items.remove(item)
|
||||
|
||||
for item in data.items:
|
||||
product = db.execute(select(Product).where(Product.id == item.product.id_)).scalar_one()
|
||||
quantity = round(item.quantity, 2)
|
||||
for d_item in data.items:
|
||||
product = db.execute(select(Product).where(Product.id == d_item.product.id_)).scalar_one()
|
||||
quantity = round(d_item.quantity, 2)
|
||||
if product.is_purchased:
|
||||
ingredient_cost = get_purchased_product_cost(product, data.valid_from, data.valid_till, db)
|
||||
else:
|
||||
@@ -189,7 +188,7 @@ async def update_route(
|
||||
recipe_cost += round(ingredient_cost * quantity, 2)
|
||||
recipe.items.append(RecipeItem(None, product.id, quantity, ingredient_cost))
|
||||
|
||||
recipe.cost_price = recipe_cost
|
||||
recipe.cost_price = round(recipe_cost / recipe.recipe_yield, 2)
|
||||
seen_recipes: Set[uuid.UUID] = set()
|
||||
check_recursion(recipe, seen_recipes, db)
|
||||
db.commit()
|
||||
@@ -249,11 +248,11 @@ def get_purchased_product_cost(product: Product, start_date: date, finish_date:
|
||||
else:
|
||||
for sku in skus:
|
||||
price.append(sku.cost_price / sku.fraction / sku.product_yield)
|
||||
return round(sum(price) / len(price), 5)
|
||||
return round(sum(price) / len(price), 5) # type: ignore[return-value]
|
||||
|
||||
|
||||
def get_sub_product_cost(product: Product, start_date: date, finish_date: date, db: Session):
|
||||
recipe: Recipe = (
|
||||
def get_sub_product_cost(product: Product, start_date: date, finish_date: date, db: Session) -> Decimal:
|
||||
recipe: Optional[Recipe] = (
|
||||
db.execute(
|
||||
select(Recipe)
|
||||
.join(Recipe.sku)
|
||||
@@ -273,57 +272,57 @@ def get_sub_product_cost(product: Product, start_date: date, finish_date: date,
|
||||
detail=f"Ingredient {product.name} is not bought and also does not have a recipe for the period.",
|
||||
)
|
||||
|
||||
return recipe.cost_price
|
||||
return round(recipe.cost_price / recipe.sku.fraction / recipe.sku.product_yield, 5)
|
||||
|
||||
|
||||
def update_old_rows(product_id, valid_from: date, valid_till: date, db: Session):
|
||||
old = (
|
||||
def update_old_rows(sku_id: uuid.UUID, valid_from: date, valid_till: date, db: Session) -> None:
|
||||
old: List[Recipe] = (
|
||||
db.execute(
|
||||
select(Recipe)
|
||||
.where(
|
||||
Recipe.product_id == product_id,
|
||||
Recipe.sku_id == sku_id,
|
||||
Recipe.valid_from < valid_till,
|
||||
Recipe.valid_till > valid_from,
|
||||
)
|
||||
.order_by(Recipe.effective_from)
|
||||
.order_by(Recipe.valid_from)
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
|
||||
new_recipes = []
|
||||
new_recipes: List[Recipe] = []
|
||||
|
||||
for item in old:
|
||||
if item.valid_from < valid_from:
|
||||
recipe = Recipe(
|
||||
product_id=item.product_id,
|
||||
quantity=item.quantity,
|
||||
sku_id=item.sku_id,
|
||||
recipe_yield=item.recipe_yield,
|
||||
cost_price=item.cost_price,
|
||||
sale_price=item.sale_price,
|
||||
valid_from=item.valid_from,
|
||||
valid_till=valid_from - timedelta(days=1),
|
||||
)
|
||||
for ri in item.recipe_items:
|
||||
recipe.recipe_items.append(RecipeItem(None, ri.product_id, ri.quantity, ri.price))
|
||||
for ri in item.items:
|
||||
recipe.items.append(RecipeItem(None, ri.product_id, ri.quantity, ri.price))
|
||||
new_recipes.append(recipe)
|
||||
if item.valid_till > valid_till:
|
||||
recipe = Recipe(
|
||||
product_id=item.product_id,
|
||||
quantity=item.quantity,
|
||||
sku_id=item.sku_id,
|
||||
recipe_yield=item.recipe_yield,
|
||||
cost_price=item.cost_price,
|
||||
sale_price=item.sale_price,
|
||||
valid_from=valid_till + timedelta(days=1),
|
||||
valid_till=item.valid_till,
|
||||
)
|
||||
for ri in item.recipe_items:
|
||||
recipe.recipe_items.append(RecipeItem(None, ri.product_id, ri.quantity, ri.price))
|
||||
for ri in item.items:
|
||||
recipe.items.append(RecipeItem(None, ri.product_id, ri.quantity, ri.price))
|
||||
new_recipes.append(recipe)
|
||||
|
||||
for recipe in new_recipes:
|
||||
db.add(recipe)
|
||||
for item in recipe.recipe_items:
|
||||
item.recipe_id = recipe.id
|
||||
db.add(item)
|
||||
for r_item in recipe.items:
|
||||
r_item.recipe_id = recipe.id
|
||||
db.add(r_item)
|
||||
|
||||
|
||||
@router.delete("/{id_}", response_model=schemas.RecipeBlank)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from datetime import date, datetime
|
||||
from typing import Dict, List
|
||||
from typing import List, Tuple
|
||||
|
||||
import brewman.schemas.cash_flow as schemas
|
||||
|
||||
@@ -31,52 +31,54 @@ def report_blank(
|
||||
startDate=get_start_date(request.session),
|
||||
finishDate=get_finish_date(request.session),
|
||||
body=schemas.CashFlowBody(operating=[], investing=[], financing=[], details=[]),
|
||||
footer=None,
|
||||
footer=[],
|
||||
)
|
||||
|
||||
|
||||
@router.get("/data")
|
||||
@router.get("/data", response_model=schemas.CashFlow)
|
||||
def report_data(
|
||||
request: Request,
|
||||
s: str,
|
||||
f: str,
|
||||
user: UserToken = Security(get_user, scopes=["cash-flow"]),
|
||||
):
|
||||
) -> schemas.CashFlow:
|
||||
with SessionFuture() as db:
|
||||
start_date = datetime.strptime(s, "%d-%b-%Y")
|
||||
finish_date = datetime.strptime(f, "%d-%b-%Y")
|
||||
body, footer = build_report(start_date, finish_date, db)
|
||||
set_period(s, f, request.session)
|
||||
return {
|
||||
"startDate": s,
|
||||
"finishDate": f,
|
||||
"body": body,
|
||||
"footer": footer,
|
||||
}
|
||||
return schemas.CashFlow(
|
||||
startDate=s,
|
||||
finishDate=f,
|
||||
body=body,
|
||||
footer=footer,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{id_}")
|
||||
@router.get("/{id_}", response_model=schemas.CashFlow)
|
||||
def report_id(
|
||||
id_: int,
|
||||
request: Request,
|
||||
s: str,
|
||||
f: str,
|
||||
user: UserToken = Security(get_user, scopes=["cash-flow"]),
|
||||
):
|
||||
) -> schemas.CashFlow:
|
||||
with SessionFuture() as db:
|
||||
start_date = datetime.strptime(s, "%d-%b-%Y")
|
||||
finish_date = datetime.strptime(f, "%d-%b-%Y")
|
||||
details, footer = build_report_id(id_, start_date, finish_date, db)
|
||||
body, footer = build_report_id(id_, start_date, finish_date, db)
|
||||
set_period(s, f, request.session)
|
||||
return {
|
||||
"startDate": s,
|
||||
"finishDate": f,
|
||||
"body": {"details": details},
|
||||
"footer": footer,
|
||||
}
|
||||
return schemas.CashFlow(
|
||||
startDate=s,
|
||||
finishDate=f,
|
||||
body=body,
|
||||
footer=footer,
|
||||
)
|
||||
|
||||
|
||||
def build_report(start_date: date, finish_date: date, db: Session):
|
||||
def build_report(
|
||||
start_date: date, finish_date: date, db: Session
|
||||
) -> Tuple[schemas.CashFlowBody, List[schemas.CashFlowItem]]:
|
||||
sub_query = (
|
||||
select(Voucher.id)
|
||||
.join(Voucher.journals)
|
||||
@@ -102,15 +104,16 @@ def build_report(start_date: date, finish_date: date, db: Session):
|
||||
).all()
|
||||
|
||||
total_amount = 0
|
||||
cf: Dict[str, List] = {"operating": [], "investing": [], "financing": []}
|
||||
cf: schemas.CashFlowBody = schemas.CashFlowBody(operating=[], investing=[], financing=[], details=[])
|
||||
dict_ = {"operating": cf.operating, "investing": cf.investing, "financing": cf.investing, "details": cf.details}
|
||||
for account_type, amount in query:
|
||||
total_amount += amount * -1
|
||||
cf[account_type.cash_flow_classification.lower()].append(
|
||||
{
|
||||
"name": account_type.name,
|
||||
"url": ["/", "cash-flow", str(account_type.id)],
|
||||
"amount": amount * -1,
|
||||
}
|
||||
dict_[account_type.cash_flow_classification.lower()].append(
|
||||
schemas.CashFlowItem(
|
||||
name=account_type.name,
|
||||
url=["/", "cash-flow", str(account_type.id)],
|
||||
amount=amount * -1,
|
||||
)
|
||||
)
|
||||
|
||||
opening = db.execute(
|
||||
@@ -138,21 +141,26 @@ def build_report(start_date: date, finish_date: date, db: Session):
|
||||
return (
|
||||
cf,
|
||||
[
|
||||
{
|
||||
"name": "Net increase in cash and cash equivalents",
|
||||
"amount": total_amount,
|
||||
},
|
||||
{
|
||||
"name": "Cash and cash equivalents at beginning of period",
|
||||
"amount": opening,
|
||||
},
|
||||
{"name": "Cash and cash equivalents at end of period", "amount": closing},
|
||||
schemas.CashFlowItem(
|
||||
name="Net increase in cash and cash equivalents",
|
||||
url=[],
|
||||
amount=total_amount,
|
||||
),
|
||||
schemas.CashFlowItem(
|
||||
name="Cash and cash equivalents at beginning of period",
|
||||
url=[],
|
||||
amount=opening,
|
||||
),
|
||||
schemas.CashFlowItem(name="Cash and cash equivalents at end of period", url=[], amount=closing),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def build_report_id(account_type: int, start_date: date, finish_date: date, db: Session):
|
||||
details = []
|
||||
def build_report_id(
|
||||
account_type: int, start_date: date, finish_date: date, db: Session
|
||||
) -> Tuple[schemas.CashFlowBody, List[schemas.CashFlowItem]]:
|
||||
cf: schemas.CashFlowBody = schemas.CashFlowBody(operating=[], investing=[], financing=[], details=[])
|
||||
details = cf.details
|
||||
sub_query = (
|
||||
select(Voucher.id)
|
||||
.join(Voucher.journals)
|
||||
@@ -177,11 +185,11 @@ def build_report_id(account_type: int, start_date: date, finish_date: date, db:
|
||||
for account, amount in query:
|
||||
total_amount += amount * -1
|
||||
details.append(
|
||||
{
|
||||
"name": account.name,
|
||||
"url": ["/", "ledger", str(account.id)],
|
||||
"amount": amount * -1,
|
||||
}
|
||||
schemas.CashFlowItem(
|
||||
name=account.name,
|
||||
url=["/", "ledger", str(account.id)],
|
||||
amount=amount * -1,
|
||||
)
|
||||
)
|
||||
|
||||
return details, [{"name": "total", "amount": total_amount}]
|
||||
return cf, [schemas.CashFlowItem(name="total", url=[], amount=total_amount)]
|
||||
@@ -63,7 +63,7 @@ def delete_voucher(
|
||||
date_: str,
|
||||
d: Optional[uuid.UUID] = None,
|
||||
user: UserToken = Security(get_user, scopes=["closing-stock"]),
|
||||
):
|
||||
) -> None:
|
||||
try:
|
||||
cost_centre_id = d or CostCentre.cost_centre_purchase()
|
||||
with SessionFuture() as db:
|
||||
@@ -210,7 +210,7 @@ def get_opening_stock(date_: date, db: Session) -> Decimal:
|
||||
return Decimal(0) if opening_stock is None else opening_stock
|
||||
|
||||
|
||||
def get_closing_stock(date_, db: Session) -> Decimal:
|
||||
def get_closing_stock(date_: date, db: Session) -> Decimal:
|
||||
closing_stock: Optional[Decimal] = db.execute(
|
||||
select(func.sum(Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit))
|
||||
.join(Journal.voucher)
|
||||
@@ -226,7 +226,7 @@ def save_route(
|
||||
request: Request,
|
||||
data: schemas.ClosingStock,
|
||||
user: UserToken = Security(get_user, scopes=["closing-stock"]),
|
||||
):
|
||||
) -> schemas.ClosingStock:
|
||||
try:
|
||||
departments = set(i.cost_centre.id_ for i in data.items if i.cost_centre is not None)
|
||||
if data.cost_centre.id_ in departments:
|
||||
@@ -265,7 +265,7 @@ def save_route(
|
||||
items = [d for d in data.items if d.cost_centre is not None and d.cost_centre.id_ == dep]
|
||||
item = save(data.date_, items, user, db)
|
||||
save_inventories(item, items, db)
|
||||
amount: Decimal = sum(i.amount for i in item.inventories)
|
||||
amount: Decimal = sum(i.amount for i in item.inventories) # type: ignore[assignment]
|
||||
save_journals(item, data.cost_centre.id_, dep, amount, db)
|
||||
check_journals_are_valid(item)
|
||||
db.commit()
|
||||
@@ -278,7 +278,7 @@ def save_route(
|
||||
)
|
||||
|
||||
|
||||
def save_cs(data: schemas.ClosingStock, db: Session):
|
||||
def save_cs(data: schemas.ClosingStock, db: Session) -> None:
|
||||
for item in data.items:
|
||||
cs = ClosingStock(
|
||||
date_=data.date_, cost_centre_id=data.cost_centre.id_, sku_id=item.product.id_, quantity=item.physical
|
||||
@@ -344,7 +344,7 @@ def save_journals(
|
||||
destination: uuid.UUID,
|
||||
amount: Decimal,
|
||||
db: Session,
|
||||
):
|
||||
) -> None:
|
||||
s = Journal(debit=-1, account_id=AccountBase.all_purchases(), amount=amount, cost_centre_id=source)
|
||||
d = Journal(debit=1, account_id=AccountBase.all_purchases(), amount=amount, cost_centre_id=destination)
|
||||
voucher.journals.append(s)
|
||||
@@ -353,7 +353,7 @@ def save_journals(
|
||||
db.add(d)
|
||||
|
||||
|
||||
def update_cs(date_: date, cost_centre_id: uuid.UUID, items: List[schemas.ClosingStockItem], db: Session):
|
||||
def update_cs(date_: date, cost_centre_id: uuid.UUID, items: List[schemas.ClosingStockItem], db: Session) -> None:
|
||||
old = (
|
||||
db.execute(
|
||||
select(ClosingStock).where(ClosingStock.date == date_, ClosingStock.cost_centre_id == cost_centre_id)
|
||||
@@ -380,7 +380,7 @@ def update_cs(date_: date, cost_centre_id: uuid.UUID, items: List[schemas.Closin
|
||||
db.add(cs)
|
||||
|
||||
|
||||
def delete_old_vouchers(date_: date, cost_centre_id: uuid.UUID, db: Session):
|
||||
def delete_old_vouchers(date_: date, cost_centre_id: uuid.UUID, db: Session) -> None:
|
||||
vouchers = (
|
||||
db.execute(select(Voucher.id).where(Voucher.date == date_, Voucher.voucher_type == VoucherType.CLOSING_STOCK))
|
||||
.scalars()
|
||||
|
||||
@@ -162,8 +162,8 @@ def opening_balance(
|
||||
.group_by(StockKeepingUnit.units)
|
||||
).all()
|
||||
|
||||
quantity: Decimal = sum(r.quantity for r in row)
|
||||
amount: Decimal = sum(r.amount for r in row)
|
||||
quantity: Decimal = sum(r.quantity for r in row) # type: ignore[assignment]
|
||||
amount: Decimal = sum(r.amount for r in row) # type: ignore[assignment]
|
||||
|
||||
return (
|
||||
quantity,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, Depends, Request, Security
|
||||
from datetime import date, datetime
|
||||
from typing import List
|
||||
|
||||
import brewman.schemas.reconcile as schemas
|
||||
|
||||
from fastapi import APIRouter, Request, Security
|
||||
from sqlalchemy import not_
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from sqlalchemy.sql.expression import and_, func, or_, select
|
||||
@@ -19,42 +23,44 @@ from ...schemas.user import UserToken
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
@router.get("", response_model=schemas.Reconcile)
|
||||
def show_blank(
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["reconcile"]),
|
||||
):
|
||||
return {
|
||||
"startDate": get_start_date(request.session),
|
||||
"finishDate": get_finish_date(request.session),
|
||||
"account": None,
|
||||
"body": [],
|
||||
}
|
||||
) -> schemas.Reconcile:
|
||||
return schemas.Reconcile(
|
||||
startDate=get_start_date(request.session),
|
||||
finishDate=get_finish_date(request.session),
|
||||
account=None,
|
||||
body=[],
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{id_}")
|
||||
@router.get("/{id_}", response_model=schemas.Reconcile)
|
||||
def show_data(
|
||||
id_: uuid.UUID,
|
||||
request: Request,
|
||||
s: str = None,
|
||||
f: str = None,
|
||||
user: UserToken = Security(get_user, scopes=["reconcile"]),
|
||||
):
|
||||
) -> schemas.Reconcile:
|
||||
with SessionFuture() as db:
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == id_)).scalar_one()
|
||||
start_date = s if s is not None else get_start_date(request.session)
|
||||
finish_date = f if f is not None else get_finish_date(request.session)
|
||||
start_date = datetime.strptime(s or get_start_date(request.session), "%d-%b-%Y")
|
||||
finish_date = datetime.strptime(f or get_finish_date(request.session), "%d-%b-%Y")
|
||||
body = build_report(account.id, start_date, finish_date, db)
|
||||
set_period(start_date, finish_date, request.session)
|
||||
return {
|
||||
"startDate": start_date,
|
||||
"finishDate": finish_date,
|
||||
"account": {"id": account.id, "name": account.name},
|
||||
"body": body,
|
||||
}
|
||||
return schemas.Reconcile(
|
||||
startDate=start_date,
|
||||
finishDate=finish_date,
|
||||
account=schemas.AccountLink(id=account.id, name=account.name),
|
||||
body=body,
|
||||
)
|
||||
|
||||
|
||||
def build_report(account_id, start_date, finish_date, db):
|
||||
def build_report(
|
||||
account_id: uuid.UUID, start_date: date, finish_date: date, db: Session
|
||||
) -> List[schemas.ReconcileItem]:
|
||||
opening = opening_balance(account_id, start_date, db)
|
||||
body = [opening]
|
||||
|
||||
@@ -66,8 +72,8 @@ def build_report(account_id, start_date, finish_date, db):
|
||||
or_(
|
||||
Voucher.is_reconciled == False, # noqa: E712
|
||||
and_(
|
||||
Voucher.reconcile_date >= datetime.datetime.strptime(start_date, "%d-%b-%Y"),
|
||||
Voucher.reconcile_date <= datetime.datetime.strptime(finish_date, "%d-%b-%Y"),
|
||||
Voucher.reconcile_date >= start_date,
|
||||
Voucher.reconcile_date <= finish_date,
|
||||
),
|
||||
),
|
||||
not_(Voucher.voucher_type.in_([VoucherType.ISSUE, VoucherType.CLOSING_STOCK])),
|
||||
@@ -94,27 +100,27 @@ def build_report(account_id, start_date, finish_date, db):
|
||||
name += "{0} / ".format(journal.account.name)
|
||||
name = name[:-3]
|
||||
body.append(
|
||||
{
|
||||
"id": voucher.id,
|
||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||
"name": name,
|
||||
"type": voucher.voucher_type.name.replace("_", " ").title(),
|
||||
"narration": voucher.narration,
|
||||
"debit": debit,
|
||||
"credit": credit,
|
||||
"isReconciled": voucher.is_reconciled,
|
||||
"reconcileDate": voucher.reconcile_date.strftime("%d-%b-%Y"),
|
||||
}
|
||||
schemas.ReconcileItem(
|
||||
id=voucher.id,
|
||||
date=voucher.date,
|
||||
name=name,
|
||||
type=voucher.voucher_type.name.replace("_", " ").title(),
|
||||
narration=voucher.narration,
|
||||
debit=debit,
|
||||
credit=credit,
|
||||
isReconciled=voucher.is_reconciled,
|
||||
reconcileDate=voucher.reconcile_date,
|
||||
)
|
||||
)
|
||||
return body
|
||||
|
||||
|
||||
def opening_balance(account_id: uuid.UUID, start_date, db: Session):
|
||||
def opening_balance(account_id: uuid.UUID, start_date: date, db: Session) -> schemas.ReconcileItem:
|
||||
opening = db.execute(
|
||||
select(func.sum(Journal.amount * Journal.debit))
|
||||
.join(Journal.voucher)
|
||||
.where(
|
||||
Voucher.reconcile_date < datetime.datetime.strptime(start_date, "%d-%b-%Y"),
|
||||
Voucher.reconcile_date < start_date,
|
||||
Voucher.is_reconciled == True, # noqa: E712
|
||||
not_(Voucher.voucher_type.in_([VoucherType.ISSUE, VoucherType.CLOSING_STOCK])),
|
||||
Journal.account_id == account_id,
|
||||
@@ -127,51 +133,46 @@ def opening_balance(account_id: uuid.UUID, start_date, db: Session):
|
||||
else:
|
||||
debit = opening
|
||||
credit = 0
|
||||
return {
|
||||
"date": start_date,
|
||||
"id": None,
|
||||
"name": "Opening Balance",
|
||||
"type": "Opening Balance",
|
||||
"narration": "",
|
||||
"debit": debit,
|
||||
"credit": credit,
|
||||
"running": opening,
|
||||
"isReconciled": True,
|
||||
"reconcileDate": start_date,
|
||||
}
|
||||
return schemas.ReconcileItem(
|
||||
date=start_date,
|
||||
id=None,
|
||||
name="Opening Balance",
|
||||
type="Opening Balance",
|
||||
narration="",
|
||||
debit=debit,
|
||||
credit=credit,
|
||||
running=opening,
|
||||
isReconciled=True,
|
||||
reconcileDate=start_date,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/{id_}")
|
||||
@router.post("/{id_}", response_model=schemas.Reconcile)
|
||||
def save(
|
||||
id_: uuid.UUID,
|
||||
data: schemas.Reconcile,
|
||||
request: Request,
|
||||
s: str = None,
|
||||
f: str = None,
|
||||
user: UserToken = Security(get_user, scopes=["reconcile"]),
|
||||
):
|
||||
) -> schemas.Reconcile:
|
||||
with SessionFuture() as db:
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == id_)).scalar_one()
|
||||
start_date = s if s is not None else get_start_date(request.session)
|
||||
finish_date = f if f is not None else get_finish_date(request.session)
|
||||
raise Exception("not fixed")
|
||||
# for item in request.json_body["body"]:
|
||||
# if "id" not in item or item["id"] is None:
|
||||
# continue
|
||||
#
|
||||
# voucher = (
|
||||
# request.dbsession.query(Voucher)
|
||||
# .where(Voucher.id == uuid.UUID(item["id"]))
|
||||
# .first()
|
||||
# )
|
||||
# is_reconciled = item["isReconciled"]
|
||||
# reconcile_date = datetime.datetime.strptime(item["reconcileDate"], "%d-%b-%Y")
|
||||
# voucher.is_reconciled = is_reconciled
|
||||
# voucher.reconcile_date = reconcile_date
|
||||
# transaction.commit()
|
||||
# body = build_report(account.id, start_date, finish_date, request)
|
||||
# return {
|
||||
# "startDate": start_date,
|
||||
# "finishDate": finish_date,
|
||||
# "account": {"id": account.id, "name": account.name},
|
||||
# "body": body
|
||||
# }
|
||||
start_date = datetime.strptime(s or get_start_date(request.session), "%d-%b-%Y")
|
||||
finish_date = datetime.strptime(f or get_finish_date(request.session), "%d-%b-%Y")
|
||||
for item in data.body:
|
||||
if item.id_ is None:
|
||||
continue
|
||||
|
||||
voucher: Voucher = db.execute(select(Voucher).where(Voucher.id == item.id_)).scalar_one()
|
||||
voucher.is_reconciled = item.is_reconciled
|
||||
if item.reconcile_date is not None:
|
||||
voucher.reconcile_date = item.reconcile_date
|
||||
db.commit()
|
||||
body = build_report(account.id, start_date, finish_date, db)
|
||||
return schemas.Reconcile(
|
||||
startDate=start_date,
|
||||
finishDate=finish_date,
|
||||
account=schemas.AccountLink(id=account.id, name=account.name),
|
||||
body=body,
|
||||
)
|
||||
@@ -106,11 +106,11 @@ def add_roles(user: User, roles: List[schemas.RoleItem], db: Session) -> None:
|
||||
user.roles.remove(ug)
|
||||
|
||||
|
||||
@router.delete("/{id_}")
|
||||
@router.delete("/{id_}", response_model=None)
|
||||
def delete_route(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["users"]),
|
||||
):
|
||||
) -> None:
|
||||
if id_ == user.id_:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||
@@ -154,11 +154,11 @@ async def show_list(
|
||||
]
|
||||
|
||||
|
||||
@router.get("/active")
|
||||
async def show_active(user: UserToken = Depends(get_user)):
|
||||
@router.get("/active", response_model=List[schemas.UserBlank])
|
||||
async def show_active(user: UserToken = Depends(get_user)) -> List[schemas.UserBlank]:
|
||||
with SessionFuture() as db:
|
||||
return [
|
||||
{"name": name}
|
||||
schemas.UserBlank(name=name)
|
||||
for name in db.execute(select(User.name).where(User.locked_out == False).order_by(User.name)) # noqa: E712
|
||||
.scalars()
|
||||
.all()
|
||||
|
||||
@@ -92,7 +92,7 @@ def check_delete_permissions(voucher: Voucher, user: UserToken) -> None:
|
||||
def delete_voucher(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user),
|
||||
):
|
||||
) -> output.Voucher:
|
||||
with SessionFuture() as db:
|
||||
voucher: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
||||
images = db.execute(select(DbImage).where(DbImage.resource_id == voucher.id)).scalars().all()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class AccountBalance(BaseModel):
|
||||
date: Decimal
|
||||
total: Decimal
|
||||
@@ -21,7 +21,7 @@ class BlankVoucherInfo(BaseModel):
|
||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y")}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
@@ -33,7 +33,7 @@ class CashFlow(BaseModel):
|
||||
start_date: date
|
||||
finish_date: date
|
||||
body: CashFlowBody
|
||||
footer: Optional[List[CashFlowItem]]
|
||||
footer: List[CashFlowItem]
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
|
||||
@@ -43,13 +43,13 @@ class ClosingStock(BaseModel):
|
||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y"), datetime: lambda v: v.strftime("%d-%b-%Y %H:%M")}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("creation_date", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
def parse_creation_date(cls, value) -> Optional[datetime]:
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, datetime):
|
||||
@@ -57,7 +57,7 @@ class ClosingStock(BaseModel):
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("last_edit_date", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
def parse_last_edit_date(cls, value) -> Optional[datetime]:
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, datetime):
|
||||
|
||||
@@ -30,13 +30,13 @@ class JournalIn(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@classmethod
|
||||
def load_form(cls, data: str = Form(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
@@ -54,13 +54,13 @@ class PurchaseIn(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@classmethod
|
||||
def load_form(cls, data: str = Form(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
@@ -79,19 +79,19 @@ class IssueIn(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("destination") # For Purchase, Issue and Return Vouchers
|
||||
def source_destination_unique(cls, value: CostCentreLink, values):
|
||||
def source_destination_unique(cls, value: CostCentreLink, values) -> CostCentreLink:
|
||||
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(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
@@ -108,13 +108,13 @@ class EmployeeBenefitIn(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@classmethod
|
||||
def load_form(cls, data: str = Form(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
@@ -131,13 +131,13 @@ class IncentiveIn(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@classmethod
|
||||
def load_form(cls, data: str = Form(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from pydantic.main import BaseModel
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
message: str
|
||||
@@ -28,29 +28,17 @@ class RateContractIn(BaseModel):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("valid_from", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y")
|
||||
|
||||
@validator("valid_till", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y")
|
||||
|
||||
|
||||
class RateContract(RateContractIn):
|
||||
id_: uuid.UUID
|
||||
creation_date: Optional[datetime]
|
||||
last_edit_date: Optional[datetime]
|
||||
user: Optional[UserLink]
|
||||
creation_date: datetime
|
||||
last_edit_date: datetime
|
||||
user: UserLink
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
@@ -60,32 +48,14 @@ class RateContract(RateContractIn):
|
||||
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("valid_from", pre=True)
|
||||
# def parse_creation_date(cls, value):
|
||||
# if isinstance(value, datetime):
|
||||
# return value
|
||||
# return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
#
|
||||
# @validator("valid_till", pre=True)
|
||||
# def parse_last_edit_date(cls, value):
|
||||
# if isinstance(value, datetime):
|
||||
# return value
|
||||
# return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("creation_date", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
def parse_creation_date(cls, value) -> datetime:
|
||||
if isinstance(value, datetime):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("last_edit_date", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
def parse_last_edit_date(cls, value) -> datetime:
|
||||
if isinstance(value, datetime):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
@@ -30,13 +30,13 @@ class RecipeIn(BaseModel):
|
||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y") if v is not None else None}
|
||||
|
||||
@validator("valid_from", pre=True)
|
||||
def parse_valid_from(cls, value):
|
||||
def parse_valid_from(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("valid_till", pre=True)
|
||||
def parse_valid_till(cls, value):
|
||||
def parse_valid_till(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import uuid
|
||||
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import validator
|
||||
from pydantic.main import BaseModel
|
||||
|
||||
from . import to_camel
|
||||
from .account import AccountLink
|
||||
|
||||
|
||||
class ReconcileItem(BaseModel):
|
||||
id_: Optional[uuid.UUID]
|
||||
date_: date
|
||||
name: str
|
||||
url: List[str]
|
||||
type_: str
|
||||
narration: str
|
||||
debit: Decimal
|
||||
credit: Decimal
|
||||
posted: bool
|
||||
is_reconciled: bool
|
||||
reconcile_date: Optional[date]
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("reconcile_date", pre=True)
|
||||
def parse_reconcile_date(cls, value):
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y")}
|
||||
|
||||
|
||||
class Reconcile(BaseModel):
|
||||
start_date: date
|
||||
finish_date: date
|
||||
account: Optional[AccountLink]
|
||||
body: List[ReconcileItem]
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y")}
|
||||
|
||||
@validator("start_date", pre=True)
|
||||
def parse_start_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("finish_date", pre=True)
|
||||
def parse_finish_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
@@ -82,4 +82,11 @@ class LockInformation(BaseModel):
|
||||
|
||||
class Maintenance(BaseModel):
|
||||
enabled: bool
|
||||
user: Optional[str]
|
||||
user: str
|
||||
|
||||
|
||||
class AttendanceCount(BaseModel):
|
||||
attendance_count: int
|
||||
|
||||
class Config:
|
||||
alias_generator = to_camel
|
||||
@@ -30,7 +30,7 @@ class VoucherIn(BaseModel):
|
||||
files: List[ImageUpload]
|
||||
|
||||
@classmethod
|
||||
def load_form(cls, data: str = Form(...)):
|
||||
def load_form(cls, data: str = Form(...)) -> BaseModel:
|
||||
json_data = json.loads(data)
|
||||
return cls.parse_obj(json_data)
|
||||
|
||||
@@ -63,13 +63,13 @@ class Voucher(VoucherIn):
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
def parse_date(cls, value) -> date:
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("creation_date", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
def parse_creation_date(cls, value) -> Optional[date]:
|
||||
if value is None or value == "":
|
||||
return None
|
||||
if isinstance(value, datetime):
|
||||
@@ -77,7 +77,7 @@ class Voucher(VoucherIn):
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("last_edit_date", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
def parse_last_edit_date(cls, value) -> Optional[date]:
|
||||
if value is None or value == "":
|
||||
return None
|
||||
if isinstance(value, datetime):
|
||||
@@ -85,7 +85,7 @@ class Voucher(VoucherIn):
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("reconcile_date", pre=True)
|
||||
def parse_reconcile_date(cls, value):
|
||||
def parse_reconcile_date(cls, value) -> Optional[date]:
|
||||
if value is None or value == "":
|
||||
return None
|
||||
elif isinstance(value, date):
|
||||
|
||||
@@ -10,7 +10,7 @@ export class CashFlow {
|
||||
details: CashFlowItem[];
|
||||
};
|
||||
|
||||
footer?: CashFlowItem[];
|
||||
footer: CashFlowItem[];
|
||||
|
||||
public constructor(init?: Partial<CashFlow>) {
|
||||
this.startDate = '';
|
||||
@@ -21,6 +21,7 @@ export class CashFlow {
|
||||
financing: [],
|
||||
details: [],
|
||||
};
|
||||
this.footer = [];
|
||||
Object.assign(this, init);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user