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