diff --git a/brewman/main.py b/brewman/main.py index 5f5fbac8..d1ce3325 100644 --- a/brewman/main.py +++ b/brewman/main.py @@ -1,5 +1,6 @@ import uvicorn from fastapi import FastAPI +from starlette.middleware.sessions import SessionMiddleware from .routers import ( account, @@ -17,15 +18,17 @@ from .routers import ( login, ) from .routers.auth import client, user, role +from .routers.reports import ledger, balance_sheet, profit_loss, closing_stock from .db.base_class import Base from .config import Settings as settings -from .db.session import SessionLocal, engine +from .db.session import engine Base.metadata.create_all(bind=engine) app = FastAPI() +app.add_middleware(SessionMiddleware, secret_key="c982367648") # app.include_router(brewman.routers, prefix="/api/db-image", tags=["db-image"]) app.include_router(login.router, tags=["login"]) app.include_router(account.router, prefix="/api/accounts", tags=["accounts"]) @@ -57,6 +60,10 @@ app.include_router(recipe.router, prefix="/api/recipes", tags=["products"]) app.include_router(client.router, prefix="/api/clients", tags=["clients"]) app.include_router(role.router, prefix="/api/roles", tags=["users"]) app.include_router(user.router, prefix="/api/users", tags=["users"]) +app.include_router(ledger.router, prefix="/api/ledger", tags=["reports"]) +app.include_router(balance_sheet.router, prefix="/api/balance-sheet", tags=["reports"]) +app.include_router(profit_loss.router, prefix="/api/profit-loss", tags=["reports"]) +app.include_router(closing_stock.router, prefix="/api/closing-stock", tags=["reports"]) def init(): diff --git a/brewman/routers/reports/balance_sheet.py b/brewman/routers/reports/balance_sheet.py index a536225e..4e802beb 100644 --- a/brewman/routers/reports/balance_sheet.py +++ b/brewman/routers/reports/balance_sheet.py @@ -1,8 +1,13 @@ import datetime + +from fastapi import APIRouter, Depends, Security, Request +from sqlalchemy.orm import Session from sqlalchemy.sql.expression import func, desc +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal from brewman.models.master import AccountType, AccountBase - from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.routers.reports.closing_stock import get_closing_stock from brewman.routers.reports.profit_loss import get_accumulated_profit @@ -12,33 +17,47 @@ from brewman.routers.services.session import ( session_period_finish, ) -from fastapi import APIRouter - router = APIRouter() -@router.get("/api/balance-sheet") # "Balance Sheet" -def report_blank(request): - return {"date": session_period_finish(request), "body": [], "footer": []} +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() -@router.get("/api/balance-sheet/{date}") # "Balance Sheet" -def report_data(request): - date = request.matchdict.get("date", None) - body, footer = build_balance_sheet(date, request.dbsession) - session_period_set(session_period_start(request), date, request) +@router.get("") +def report_blank( + request: Request, + user: UserToken = Security(get_user, scopes=["balance-sheet"]), +): + return {"date": session_period_finish(request.session), "body": [], "footer": []} + + +@router.get("/{date}") +def report_data( + date: str, + request: Request, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["balance-sheet"]), +): + body, footer = build_balance_sheet(date, db) + session_period_set(session_period_start(request.session), date, request.session) return {"date": date, "body": body, "footer": footer} -def build_balance_sheet(finish_date, dbsession): +def build_balance_sheet(finish_date, db): if not isinstance(finish_date, datetime.datetime): finish_date = datetime.datetime.strptime(finish_date, "%d-%b-%Y") type_list = [i.id for i in AccountType.list() if i.balance_sheet == True] report = [] groups = dict() # Add Net Profit / Loss - closing_stock = get_closing_stock(finish_date, dbsession) - net_profit = get_accumulated_profit(finish_date, dbsession) - closing_stock + closing_stock = get_closing_stock(finish_date, db) + net_profit = get_accumulated_profit(finish_date, db) - closing_stock total_amount = net_profit report.append( { @@ -69,7 +88,7 @@ def build_balance_sheet(finish_date, dbsession): amount_sum = func.sum(Journal.amount * Journal.debit) query = ( - dbsession.query(AccountBase, amount_sum) + db.query(AccountBase, amount_sum) .join(Journal.voucher) .join(Journal.account) .filter(Voucher.date <= finish_date) diff --git a/brewman/routers/reports/closing_stock.py b/brewman/routers/reports/closing_stock.py index 154025d3..8a9afc2a 100644 --- a/brewman/routers/reports/closing_stock.py +++ b/brewman/routers/reports/closing_stock.py @@ -1,7 +1,12 @@ import datetime +from fastapi import APIRouter, Depends, Security, Request +from sqlalchemy.orm import Session from sqlalchemy.sql.expression import func +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal from brewman.models.master import Product, CostCentre from brewman.models.voucher import Voucher, Journal, Inventory from brewman.routers.services.session import ( @@ -10,31 +15,45 @@ from brewman.routers.services.session import ( session_period_finish, ) -from fastapi import APIRouter - router = APIRouter() -@router.get("/api/closing-stock") # "Closing Stock" -def report_blank(request): - return {"date": session_period_finish(request), "body": []} +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() -@router.get("/api/closing-stock/{date}") # "Closing Stock" -def report_data(request): - date = request.matchdict.get("date", None) - session_period_set(session_period_start(request), date, request) - return {"date": date, "body": build_report(date, request.dbsession)} +@router.get("") # "Closing Stock" +def report_blank( + request: Request, + user: UserToken = Security(get_user, scopes=["closing-stock"]), +): + return {"date": session_period_finish(request.session), "body": []} -def build_report(date, dbsession): +@router.get("/{date}") +def report_data( + date: str, + request: Request, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["closing-stock"]), +): + session_period_set(session_period_start(request.session), date, request.session) + return {"date": date, "body": build_report(date, db)} + + +def build_report(date, db): date = datetime.datetime.strptime(date, "%d-%b-%Y") amount_sum = func.sum( Journal.debit * Inventory.quantity * Inventory.rate * (1 + Inventory.tax) ).label("amount") quantity_sum = func.sum(Journal.debit * Inventory.quantity).label("quantity") query = ( - dbsession.query(Product, quantity_sum, amount_sum) + db.query(Product, quantity_sum, amount_sum) .join(Product.inventories) .join(Inventory.voucher) .join(Voucher.journals) @@ -59,9 +78,9 @@ def build_report(date, dbsession): return body -def get_opening_stock(start_date, dbsession): +def get_opening_stock(start_date, db): opening_stock = ( - dbsession.query( + db.query( func.sum( Inventory.quantity * Inventory.rate @@ -79,9 +98,9 @@ def get_opening_stock(start_date, dbsession): return 0 if opening_stock is None else opening_stock -def get_closing_stock(finish_date, dbsession): +def get_closing_stock(finish_date, db): closing_stock = ( - dbsession.query( + db.query( func.sum( Inventory.quantity * Inventory.rate diff --git a/brewman/routers/reports/ledger.py b/brewman/routers/reports/ledger.py index 88118896..09b33524 100644 --- a/brewman/routers/reports/ledger.py +++ b/brewman/routers/reports/ledger.py @@ -1,9 +1,13 @@ import datetime import uuid -from sqlalchemy.orm import joinedload_all +from fastapi import APIRouter, Depends, Security, Request +from sqlalchemy.orm import joinedload_all, Session from sqlalchemy.sql.expression import func +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal from brewman.models.master import AccountBase from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.routers.services.session import ( @@ -11,34 +15,47 @@ from brewman.routers.services.session import ( session_period_start, session_period_finish, ) -from brewman.routers.services.voucher import get_edit_url - -from fastapi import APIRouter router = APIRouter() -@router.get("/api/ledger") # "Ledger" -def show_blank(request): +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.get("") +def show_blank( + request: Request, + user: UserToken = Security(get_user, scopes=["ledger"]), +): return { - "startDate": session_period_start(request), - "finishDate": session_period_finish(request), + "startDate": session_period_start(request.session), + "finishDate": session_period_finish(request.session), "account": None, "body": [], } -@router.get("/api/ledger/{id}") # "Ledger" -def show_data(request): - account = ( - request.dbsession.query(AccountBase) - .filter(AccountBase.id == uuid.UUID(request.matchdict["id"])) - .first() - ) - start_date = request.GET.get("s", session_period_start(request)) - finish_date = request.GET.get("f", session_period_finish(request)) - body = build_report(account.id, start_date, finish_date, request) - session_period_set(start_date, finish_date, request) +@router.get("/{id_}") +def show_data( + id_: uuid.UUID, + request: Request, + s: str = None, + f: str = None, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["ledger"]), +): + account = db.query(AccountBase).filter(AccountBase.id == id_).first() + + start_date = s if s is not None else session_period_start(request.session) + finish_date = f if f is not None else session_period_finish(request.session) + body = build_report(account.id, start_date, finish_date, db) + session_period_set(start_date, finish_date, request.session) return { "startDate": start_date, "finishDate": finish_date, @@ -47,13 +64,13 @@ def show_data(request): } -def build_report(account_id, start_date, finish_date, request): +def build_report(account_id, start_date, finish_date, db): body = [] - opening = opening_balance(account_id, start_date, request.dbsession) + opening = opening_balance(account_id, start_date, db) body.append(opening) query = ( - request.dbsession.query(Voucher) + db.query(Voucher) .options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True)) .filter(Voucher.journals.any(Journal.account_id == account_id)) .filter(Voucher.date >= datetime.datetime.strptime(start_date, "%d-%b-%Y")) @@ -87,7 +104,7 @@ def build_report(account_id, start_date, finish_date, request): "id": voucher.id, "date": voucher.date.strftime("%d-%b-%Y"), "name": name, - "url": get_edit_url(voucher, request), + "url": "", # get_edit_url(voucher, request), "type": VoucherType.by_id(voucher.type).name, "narration": voucher.narration, "debit": debit, @@ -98,9 +115,9 @@ def build_report(account_id, start_date, finish_date, request): return body -def opening_balance(account_id, start_date, dbsession): +def opening_balance(account_id, start_date, db): opening = ( - dbsession.query(func.sum(Journal.amount * Journal.debit)) + db.query(func.sum(Journal.amount * Journal.debit)) .join(Journal.voucher) .filter(Voucher.date < datetime.datetime.strptime(start_date, "%d-%b-%Y")) .filter(Voucher.type != VoucherType.by_name("Issue").id) diff --git a/brewman/routers/reports/profit_loss.py b/brewman/routers/reports/profit_loss.py index 0f7d4db1..7c46c602 100644 --- a/brewman/routers/reports/profit_loss.py +++ b/brewman/routers/reports/profit_loss.py @@ -1,7 +1,13 @@ import datetime +from fastapi import APIRouter, Depends, Security, Request +from sqlalchemy.orm import Session from sqlalchemy.sql.expression import func, desc +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal + from brewman.models.master import AccountType, AccountBase from brewman.models.voucher import Voucher, Journal, VoucherType from brewman.routers.reports.closing_stock import get_opening_stock, get_closing_stock @@ -11,36 +17,50 @@ from brewman.routers.services.session import ( session_period_finish, ) -from fastapi import APIRouter - router = APIRouter() -@router.get("/api/profit-loss", permission="Profit & Loss") -def report_blank(request): +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.get("") +def report_blank( + request: Request, + user: UserToken = Security(get_user, scopes=["profit-&-loss"]), +): return { - "startDate": session_period_start(request), - "finishDate": session_period_finish(request), + "startDate": session_period_start(request.session), + "finishDate": session_period_finish(request.session), "body": [], "footer": {}, } -@router.get("/api/profit-loss", request_param=["s", "f"], permission="Profit & Loss") -def report_data(request): - start_date = request.GET["s"] - finish_date = request.GET["f"] - body, footer = build_profit_loss(start_date, finish_date, request.dbsession) - session_period_set(start_date, finish_date, request) +@router.get("/{start}/{finish}") +def report_data( + start: str, + finish: str, + request: Request, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["profit-&-loss"]), +): + body, footer = build_profit_loss(start, finish, db) + session_period_set(start, finish, request.session) return { - "startDate": start_date, - "finishDate": finish_date, + "startDate": start, + "finishDate": finish, "body": body, "footer": footer, } -def build_profit_loss(start_date, finish_date, dbsession): +def build_profit_loss(start_date, finish_date, db): start_date = datetime.datetime.strptime(start_date, "%d-%b-%Y") finish_date = datetime.datetime.strptime(finish_date, "%d-%b-%Y") profit_type_list = [i.id for i in AccountType.list() if i.balance_sheet == False] @@ -49,7 +69,7 @@ def build_profit_loss(start_date, finish_date, dbsession): amount_sum = func.sum(Journal.amount * Journal.debit) query = ( - dbsession.query(AccountBase, amount_sum) + db.query(AccountBase, amount_sum) .join(Journal.voucher) .join(Journal.account) .filter(Voucher.date >= start_date) @@ -63,8 +83,8 @@ def build_profit_loss(start_date, finish_date, dbsession): ) # Get opening / closing stock - opening_stock = get_opening_stock(start_date, dbsession) - closing_stock = get_closing_stock(finish_date, dbsession) + opening_stock = get_opening_stock(start_date, db) + closing_stock = get_closing_stock(finish_date, db) total_amount = (opening_stock - closing_stock) * -1 report.append( @@ -117,11 +137,11 @@ def build_profit_loss(start_date, finish_date, dbsession): return sorted(report, key=lambda d: d["order"]), footer -def get_accumulated_profit(finish_date, dbsession): +def get_accumulated_profit(finish_date, db): type_list = [i.id for i in AccountType.list() if i.balance_sheet is False] accumulated_profit = ( - dbsession.query(func.sum(Journal.amount * Journal.debit)) + db.query(func.sum(Journal.amount * Journal.debit)) .join(Journal.voucher) .join(Journal.account) .filter(Voucher.date <= finish_date) diff --git a/brewman/routers/services/session.py b/brewman/routers/services/session.py index 15fa7649..00890942 100644 --- a/brewman/routers/services/session.py +++ b/brewman/routers/services/session.py @@ -1,39 +1,34 @@ from datetime import date, timedelta -def session_current_date(request): - session = request.session - if "currentDate" not in session: - session["currentDate"] = date.today().strftime("%d-%b-%Y") - return session["currentDate"] +def session_current_date(session): + if "date" not in session: + session["date"] = date.today().strftime("%d-%b-%Y") + return session["date"] -def session_current_date_set(request, date_): - session = request.session - session["currentDate"] = date_ - return session["currentDate"] +def session_current_date_set(session, date_): + session["date"] = date_ + return session["date"] -def session_period_start(request): - session = request.session - if "periodStart" not in session: - session["periodStart"] = get_first_day(date.today()).strftime("%d-%b-%Y") - return session["periodStart"] +def session_period_start(session): + if "start" not in session: + session["start"] = get_first_day(date.today()).strftime("%d-%b-%Y") + return session["start"] -def session_period_finish(request): - session = request.session - if "periodFinish" not in session: - session["periodFinish"] = get_last_day(date.today()).strftime("%d-%b-%Y") - return session["periodFinish"] +def session_period_finish(session): + if "finish" not in session: + session["finish"] = get_last_day(date.today()).strftime("%d-%b-%Y") + return session["finish"] -def session_period_set(start, finish, request): - session = request.session - session["periodStart"] = ( +def session_period_set(start, finish, session): + session["start"] = ( start if isinstance(start, str) else start.strftime("%d-%b-%Y") ) - session["periodFinish"] = ( + session["finish"] = ( finish if isinstance(finish, str) else finish.strftime("%d-%b-%Y") ) diff --git a/overlord/src/app/profit-loss/profit-loss.service.ts b/overlord/src/app/profit-loss/profit-loss.service.ts index 6fb9db1d..0210209d 100644 --- a/overlord/src/app/profit-loss/profit-loss.service.ts +++ b/overlord/src/app/profit-loss/profit-loss.service.ts @@ -21,14 +21,9 @@ export class ProfitLossService { } list(startDate: string, finishDate): Observable<ProfitLoss> { - const options = {params: new HttpParams()}; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return <Observable<ProfitLoss>>this.http.get<ProfitLoss>(url, options) + startDate = startDate ? `/${startDate}` : ''; + finishDate = finishDate ? `/${finishDate}` : ''; + return <Observable<ProfitLoss>>this.http.get<ProfitLoss>(`${url}${startDate}${finishDate}`) .pipe( catchError(this.log.handleError(serviceName, 'list')) ); diff --git a/requirements.txt b/requirements.txt index 7fc83cdd..6efc5749 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ psycopg2 python-multipart pyjwt alembic +itsdangerous \ No newline at end of file