Stock Movement Done!!
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import datetime
|
from datetime import datetime, date
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Security, Request
|
from fastapi import APIRouter, Depends, Security, Request
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
@ -9,6 +10,7 @@ from ...core.security import get_current_active_user as get_user
|
|||||||
from ...db.session import SessionLocal
|
from ...db.session import SessionLocal
|
||||||
from brewman.models.master import Product, CostCentre
|
from brewman.models.master import Product, CostCentre
|
||||||
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
|
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
|
||||||
|
import brewman.schemas.reports as schemas
|
||||||
from ...core.session import (
|
from ...core.session import (
|
||||||
set_period,
|
set_period,
|
||||||
get_start_date,
|
get_start_date,
|
||||||
@ -27,7 +29,7 @@ def get_db() -> Session:
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
@router.get("")
|
@router.get("", response_model=schemas.StockMovement)
|
||||||
def report_blank(
|
def report_blank(
|
||||||
request: Request,
|
request: Request,
|
||||||
user: UserToken = Security(get_user, scopes=["stock-movement"]),
|
user: UserToken = Security(get_user, scopes=["stock-movement"]),
|
||||||
@ -39,7 +41,7 @@ def report_blank(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{start}/{finish}")
|
@router.get("/{start}/{finish}", response_model=schemas.StockMovement)
|
||||||
def report_data(
|
def report_data(
|
||||||
start: str,
|
start: str,
|
||||||
finish: str,
|
finish: str,
|
||||||
@ -47,14 +49,12 @@ def report_data(
|
|||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
user: UserToken = Security(get_user, scopes=["stock-movement"]),
|
user: UserToken = Security(get_user, scopes=["stock-movement"]),
|
||||||
):
|
):
|
||||||
body = build_stock_movement(start, finish, db)
|
body = build_stock_movement(datetime.strptime(start, "%d-%b-%Y"), datetime.strptime(finish, "%d-%b-%Y"), db)
|
||||||
set_period(start, finish, request.session)
|
set_period(start, finish, request.session)
|
||||||
return {"startDate": start, "finishDate": finish, "body": body}
|
return {"startDate": start, "finishDate": finish, "body": body}
|
||||||
|
|
||||||
|
|
||||||
def build_stock_movement(start_date, finish_date, db):
|
def build_stock_movement(start_date: date, finish_date: date, db: Session):
|
||||||
start_date = datetime.datetime.strptime(start_date, "%d-%b-%Y")
|
|
||||||
finish_date = datetime.datetime.strptime(finish_date, "%d-%b-%Y")
|
|
||||||
dict_ = {}
|
dict_ = {}
|
||||||
quantity_sum = func.sum(Journal.debit * Inventory.quantity).label("quantity")
|
quantity_sum = func.sum(Journal.debit * Inventory.quantity).label("quantity")
|
||||||
openings = (
|
openings = (
|
||||||
@ -72,7 +72,8 @@ def build_stock_movement(start_date, finish_date, db):
|
|||||||
"id": product.id,
|
"id": product.id,
|
||||||
"name": product.full_name,
|
"name": product.full_name,
|
||||||
"group": product.product_group.name,
|
"group": product.product_group.name,
|
||||||
"opening": quantity,
|
"opening": Decimal(round(quantity, 2)),
|
||||||
|
"url": ['/', 'product-ledger', str(product.id)],
|
||||||
}
|
}
|
||||||
purchases = (
|
purchases = (
|
||||||
db.query(Product, quantity_sum)
|
db.query(Product, quantity_sum)
|
||||||
@ -88,13 +89,14 @@ def build_stock_movement(start_date, finish_date, db):
|
|||||||
)
|
)
|
||||||
for product, quantity in purchases:
|
for product, quantity in purchases:
|
||||||
if product.id in dict_:
|
if product.id in dict_:
|
||||||
dict_[product.id]["purchase"] = quantity
|
dict_[product.id]["purchase"] = Decimal(round(quantity, 2))
|
||||||
else:
|
else:
|
||||||
dict_[product.id] = {
|
dict_[product.id] = {
|
||||||
"id": product.id,
|
"id": product.id,
|
||||||
"name": product.full_name,
|
"name": product.full_name,
|
||||||
"group": product.product_group.name,
|
"group": product.product_group.name,
|
||||||
"purchase": quantity,
|
"purchase": Decimal(round(quantity, 2)),
|
||||||
|
"url": ['/', 'product-ledger', str(product.id)],
|
||||||
}
|
}
|
||||||
issues = (
|
issues = (
|
||||||
db.query(Product, quantity_sum)
|
db.query(Product, quantity_sum)
|
||||||
@ -110,13 +112,14 @@ def build_stock_movement(start_date, finish_date, db):
|
|||||||
)
|
)
|
||||||
for product, quantity in issues:
|
for product, quantity in issues:
|
||||||
if product.id in dict_:
|
if product.id in dict_:
|
||||||
dict_[product.id]["issue"] = quantity * -1
|
dict_[product.id]["issue"] = Decimal(round(quantity * -1, 2))
|
||||||
else:
|
else:
|
||||||
dict_[product.id] = {
|
dict_[product.id] = {
|
||||||
"id": product.id,
|
"id": product.id,
|
||||||
"name": product.full_name,
|
"name": product.full_name,
|
||||||
"group": product.product_group.name,
|
"group": product.product_group.name,
|
||||||
"issue": quantity * -1,
|
"issue": Decimal(round(quantity * -1, 2)),
|
||||||
|
"url": ['/', 'product-ledger', str(product.id)],
|
||||||
}
|
}
|
||||||
|
|
||||||
list_ = [value for key, value in dict_.items()]
|
list_ = [value for key, value in dict_.items()]
|
||||||
@ -124,10 +127,16 @@ def build_stock_movement(start_date, finish_date, db):
|
|||||||
list_ = sorted(list_, key=lambda x: x["group"].lower())
|
list_ = sorted(list_, key=lambda x: x["group"].lower())
|
||||||
for i in range(len(list_), 0, -1):
|
for i in range(len(list_), 0, -1):
|
||||||
item = list_[i - 1]
|
item = list_[i - 1]
|
||||||
opening = item["opening"] if "opening" in item else 0
|
if "opening" not in item:
|
||||||
purchase = item["purchase"] if "purchase" in item else 0
|
item["opening"] = 0
|
||||||
issue = item["issue"] if "issue" in item else 0
|
opening = item["opening"]
|
||||||
closing = opening + purchase - issue
|
if "purchase" not in item:
|
||||||
|
item["purchase"] = 0
|
||||||
|
purchase = item["purchase"]
|
||||||
|
if "issue" not in item:
|
||||||
|
item["issue"] = 0
|
||||||
|
issue = item["issue"]
|
||||||
|
closing = round(opening + purchase - issue, 2)
|
||||||
if opening == 0 and purchase == 0 and issue == 0:
|
if opening == 0 and purchase == 0 and issue == 0:
|
||||||
list_.remove(item)
|
list_.remove(item)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -413,3 +413,41 @@ class RawMaterialCost(BaseModel):
|
|||||||
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()
|
||||||
|
|
||||||
|
|
||||||
|
class StockMovementItem(BaseModel):
|
||||||
|
id_: uuid.UUID
|
||||||
|
group: str
|
||||||
|
name: str
|
||||||
|
opening: Decimal
|
||||||
|
purchase: Decimal
|
||||||
|
issue: Decimal
|
||||||
|
closing: Decimal
|
||||||
|
url: List[str]
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
anystr_strip_whitespace = True
|
||||||
|
alias_generator = to_camel
|
||||||
|
|
||||||
|
|
||||||
|
class StockMovement(BaseModel):
|
||||||
|
start_date: date
|
||||||
|
finish_date: date
|
||||||
|
body: List[StockMovementItem]
|
||||||
|
|
||||||
|
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()
|
||||||
|
|||||||
@ -32,7 +32,11 @@
|
|||||||
<!-- Name Column -->
|
<!-- Name Column -->
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Name</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef mat-sort-header>Name</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
|
<mat-cell *matCellDef="let row">
|
||||||
|
<a [routerLink]="row.url" [queryParams]="{startDate: info.startDate, finishDate: info.finishDate}">
|
||||||
|
{{row.name}}
|
||||||
|
</a>
|
||||||
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Opening Column -->
|
<!-- Opening Column -->
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
|
|
||||||
export class StockMovementItem {
|
export class StockMovementItem {
|
||||||
|
id: string;
|
||||||
group: string;
|
group: string;
|
||||||
name: string;
|
name: string;
|
||||||
opening: number;
|
opening: number;
|
||||||
purchase: number;
|
purchase: number;
|
||||||
issue: number;
|
issue: number;
|
||||||
closing: number;
|
closing: number;
|
||||||
|
url: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StockMovement {
|
export class StockMovement {
|
||||||
|
|||||||
Reference in New Issue
Block a user