diff --git a/brewman/models/master.py b/brewman/models/master.py
index b618f817..399f6716 100644
--- a/brewman/models/master.py
+++ b/brewman/models/master.py
@@ -268,7 +268,7 @@ class AccountBase(Base):
__mapper_args__ = {"polymorphic_on": account_type}
- journals = relationship("Journal", backref="account")
+ journals = relationship("Journal", back_populates="account")
@property
def __name__(self):
diff --git a/brewman/models/voucher.py b/brewman/models/voucher.py
index 28fd3095..eb320491 100644
--- a/brewman/models/voucher.py
+++ b/brewman/models/voucher.py
@@ -80,12 +80,7 @@ class Voucher(Base):
"User", primaryjoin="User.id==Voucher.poster_id", cascade=None
)
- journals = relationship(
- "Journal",
- backref="voucher",
- cascade="delete, delete-orphan",
- cascade_backrefs=False,
- )
+ journals = relationship("Journal", back_populates="voucher", cascade="delete, delete-orphan", cascade_backrefs=False,)
inventories = relationship(
"Inventory",
backref="voucher",
@@ -167,6 +162,9 @@ class Journal(Base):
account_id = Column("account_id", GUID(), ForeignKey("accounts.id"), nullable=False)
cost_centre_id = Column("cost_centre_id", GUID(), ForeignKey("cost_centres.id"), nullable=False)
+ voucher = relationship("Voucher", back_populates="journals")
+ account = relationship("AccountBase", back_populates="journals")
+
@hybrid_property
def signed_amount(self):
return self.debit * self.amount
diff --git a/brewman/routers/reports/balance_sheet.py b/brewman/routers/reports/balance_sheet.py
index db5e34bf..f97534af 100644
--- a/brewman/routers/reports/balance_sheet.py
+++ b/brewman/routers/reports/balance_sheet.py
@@ -1,4 +1,4 @@
-import datetime
+from datetime import datetime, date
from fastapi import APIRouter, Depends, Security, Request
from sqlalchemy.orm import Session
@@ -11,6 +11,7 @@ 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
+import brewman.schemas.reports as schemas
from ...core.session import (
set_period,
get_start_date,
@@ -29,60 +30,58 @@ def get_db() -> Session:
db.close()
-@router.get("")
+@router.get("", response_model=schemas.BalanceSheet)
def report_blank(
request: Request,
user: UserToken = Security(get_user, scopes=["balance-sheet"]),
):
- return {"date": get_finish_date(request.session), "body": [], "footer": []}
+ return {"date": get_finish_date(request.session), "body": [], "footer": None}
-@router.get("/{date}")
+@router.get("/{date_}", response_model=schemas.BalanceSheet)
def report_data(
- date: str,
+ date_: str,
request: Request,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["balance-sheet"]),
):
- body, footer = build_balance_sheet(date, db)
- set_period(get_start_date(request.session), date, request.session)
- return {"date": date, "body": body, "footer": footer}
+ body, footer = build_balance_sheet(datetime.strptime(date_, "%d-%b-%Y"), db)
+ set_period(get_start_date(request.session), date_, request.session)
+ return {"date": date_, "body": body, "footer": footer}
-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]
+def build_balance_sheet(date_: date, db: Session):
+ type_list = [i.id for i in AccountType.list() if i.balance_sheet]
report = []
groups = dict()
# Add Net Profit / Loss
- closing_stock = get_closing_stock(finish_date, db)
- net_profit = get_accumulated_profit(finish_date, db) - closing_stock
+ closing_stock = round(get_closing_stock(date_, db), 2)
+ net_profit = round(get_accumulated_profit(date_, db), 2) - closing_stock
total_amount = net_profit
report.append(
{
"name": "Net Loss" if net_profit >= 0 else "Net Profit",
- "subAmount": net_profit,
- "order": 79,
+ "subAmount": round(net_profit, 2),
+ "order": 79000,
}
)
capital_group = AccountType.by_id(5)
groups[capital_group.id] = {
"group": capital_group.name,
- "amount": total_amount,
+ "amount": round(total_amount, 2),
"order": capital_group.order,
}
total_amount += closing_stock
report.append(
- {"name": "Closing Stock", "subAmount": closing_stock, "order": 20.001}
+ {"name": "Closing Stock", "subAmount": round(closing_stock, 2), "order": 20001}
)
asset_group = AccountType.by_id(4)
groups[asset_group.id] = {
"group": asset_group.name,
- "amount": closing_stock,
+ "amount": round(closing_stock, 2),
"order": asset_group.order,
}
@@ -91,7 +90,7 @@ def build_balance_sheet(finish_date, db):
db.query(AccountBase, amount_sum)
.join(Journal.voucher)
.join(Journal.account)
- .filter(Voucher.date <= finish_date)
+ .filter(Voucher.date <= date_)
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.filter(AccountBase.type.in_(type_list))
.group_by(AccountBase)
@@ -101,27 +100,25 @@ def build_balance_sheet(finish_date, db):
)
counter = 0
- sss = 0
for account, amount in query:
# Add Items
account_type = AccountType.by_id(account.type)
- sss += amount
total_amount += amount
if amount != 0:
- counter += 0.001
+ counter += 1
report.append(
{
"name": account.name,
- "subAmount": amount,
+ "subAmount": round(amount, 2),
"order": account_type.order + counter,
}
)
if account_type.id in groups:
- groups[account_type.id]["amount"] += amount
+ groups[account_type.id]["amount"] = round(groups[account_type.id]["amount"] + amount, 2)
else:
groups[account_type.id] = {
"group": account_type.name,
- "amount": amount,
+ "amount": round(amount, 2),
"order": account_type.order,
}
@@ -129,5 +126,5 @@ def build_balance_sheet(finish_date, db):
for item in groups.values():
report.append(item)
- footer = {"name": "Total", "amount": total_amount, "order": 100}
+ footer = {"name": "Total", "amount": round(total_amount, 2), "order": 100000}
return sorted(report, key=lambda d: d["order"]), footer
diff --git a/brewman/routers/reports/cash_flow.py b/brewman/routers/reports/cash_flow.py
index 806d10b6..8fbbfa1f 100644
--- a/brewman/routers/reports/cash_flow.py
+++ b/brewman/routers/reports/cash_flow.py
@@ -10,6 +10,7 @@ from ...core.security import get_current_active_user as get_user
from ...db.session import SessionLocal
from brewman.models.master import AccountBase, AccountType
from brewman.models.voucher import Voucher, Journal, VoucherType
+import brewman.schemas.reports as schemas
from ...core.session import (
set_period,
get_start_date,
@@ -28,7 +29,7 @@ def get_db() -> Session:
db.close()
-@router.get("")
+@router.get("", response_model=schemas.CashFlow)
def report_blank(
request: Request,
user: UserToken = Security(get_user, scopes=["cash-flow"]),
@@ -36,8 +37,8 @@ def report_blank(
return {
"startDate": get_start_date(request.session),
"finishDate": get_finish_date(request.session),
- "body": [],
- "footer": {},
+ "body": {"operating": [], "investing": [], "financing": [], "details": []},
+ "footer": None,
}
@@ -112,7 +113,7 @@ def build_report(start_date, finish_date, db):
cf[lt.cash_flow_classification.lower()].append(
{
"name": lt.name,
- "url": "", # request.route_url("cash_flow_id", id=str(lt.id), _query={"startDate": start_date, "finishDate": finish_date},),
+ "url": ['/', 'cash-flow', str(lt.id)],
"amount": amount * -1,
}
)
@@ -186,7 +187,7 @@ def build_report_id(account_type, start_date, finish_date, db):
details.append(
{
"name": account.name,
- "url": "", # request.route_url("ledger_id", id=account.id, _query={"startDate": start_date, "finishDate": finish_date},),
+ "url": ['/', 'ledger', str(account.id)],
"amount": amount * -1,
}
)
diff --git a/brewman/routers/reports/ledger.py b/brewman/routers/reports/ledger.py
index 260be158..7e3aadb1 100644
--- a/brewman/routers/reports/ledger.py
+++ b/brewman/routers/reports/ledger.py
@@ -104,6 +104,7 @@ def build_report(account_id, start_date, finish_date, db):
"id": voucher.id,
"date": voucher.date.strftime("%d-%b-%Y"),
"name": name,
+ "url": ['/', VoucherType.by_id(voucher.type).name.replace(" ", "-").lower(), str(voucher.id)],
"type": VoucherType.by_id(voucher.type).name,
"narration": voucher.narration,
"debit": debit,
@@ -135,6 +136,7 @@ def opening_balance(account_id, start_date, db):
"id": None,
"name": "Opening Balance",
"type": "Opening Balance",
+ "url": [],
"narration": "",
"debit": debit,
"credit": credit,
diff --git a/brewman/routers/reports/unposted.py b/brewman/routers/reports/unposted.py
index 25d39a4e..fb058855 100644
--- a/brewman/routers/reports/unposted.py
+++ b/brewman/routers/reports/unposted.py
@@ -61,7 +61,6 @@ def build_report(db: Session):
"date": voucher.date.strftime("%d-%b-%Y"),
"voucherType": VoucherType.by_id(voucher.type).name,
"narration": voucher.narration,
- "isPosted": voucher.posted,
"debitName": name_debit,
"debitAmount": debit,
"creditName": name_credit,
diff --git a/brewman/schemas/reports.py b/brewman/schemas/reports.py
index a925213b..37bf7d39 100644
--- a/brewman/schemas/reports.py
+++ b/brewman/schemas/reports.py
@@ -16,7 +16,7 @@ class LedgerItem(BaseModel):
id_: Optional[uuid.UUID]
date_: date
name: str
- url: str
+ url: List[str]
type_: str
narration: str
debit: Decimal = Field(multiple_of=0.01)
@@ -33,6 +33,9 @@ class LedgerItem(BaseModel):
class Config:
anystr_strip_whitespace = True
alias_generator = to_camel
+ json_encoders = {
+ date: lambda v: v.strftime("%d-%b-%Y")
+ }
class Ledger(BaseModel):
@@ -63,100 +66,84 @@ class Ledger(BaseModel):
).date()
-class ClientIn(BaseModel):
- name: str
- enabled: bool
- otp: Optional[int]
-
-
-class Client(ClientIn):
- id_: uuid.UUID
- code: int
- creation_date: datetime
-
-
-class LoginHistory(BaseModel):
- id_: uuid.UUID
- user_id: uuid.UUID
- client_id: uuid.UUID
- date: datetime
+class BalanceSheetItem(BaseModel):
+ name: Optional[str]
+ group: Optional[str]
+ amount: Optional[Decimal]
+ sub_amount: Optional[Decimal]
+ order: int
class Config:
- fields = {"id_": "id"}
anystr_strip_whitespace = True
alias_generator = to_camel
-class PermissionItem(BaseModel):
- id_: uuid.UUID
- name: str
- enabled: bool
+class BalanceSheet(BaseModel):
+ date_: date
+ body: List[BalanceSheetItem]
+ footer: Optional[BalanceSheetItem]
class Config:
- fields = {"id_": "id"}
-
-
-class RoleIn(BaseModel):
- name: str
- permissions: List[PermissionItem]
-
- class Config:
- fields = {"id_": "id"}
anystr_strip_whitespace = True
+ alias_generator = to_camel
+ json_encoders = {
+ date: lambda v: v.strftime("%d-%b-%Y")
+ }
+
+ @validator("date_", pre=True)
+ def parse_date(cls, value):
+ return datetime.strptime(
+ value,
+ "%d-%b-%Y"
+ ).date()
-class Role(RoleIn):
- id_: uuid.UUID
-
-
-class RoleList(BaseModel):
- id_: uuid.UUID
+class CashFlowItem(BaseModel):
name: str
- permissions: List[str]
+ url: Optional[List[str]]
+ amount: Decimal = Field(multiple_of=0.01)
class Config:
- fields = {"id_": "id"}
- anystr_strip_whitespace = True
-
-
-class RoleItem(BaseModel):
- id_: uuid.UUID
- name: str
- enabled: bool
-
- class Config:
- fields = {"id_": "id"}
-
-
-class UserIn(BaseModel):
- name: str
- password: str
- locked_out: bool
- roles: List[RoleItem]
-
- class Config:
- fields = {"id_": "id"}
anystr_strip_whitespace = True
alias_generator = to_camel
-class User(UserIn):
- id_: uuid.UUID
-
-
-class UserList(BaseModel):
- id_: uuid.UUID
- name: str
- roles: List[str]
+class CashFlowBody(BaseModel):
+ operating: List[CashFlowItem]
+ investing: List[CashFlowItem]
+ financing: List[CashFlowItem]
+ details: List[CashFlowItem]
class Config:
- fields = {"id_": "id"}
anystr_strip_whitespace = True
+ alias_generator = to_camel
+
+
+class CashFlow(BaseModel):
+ start_date: date
+ finish_date: date
+ body: CashFlowBody
+ footer: Optional[List[CashFlowItem]]
+
+ 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):
+ return datetime.strptime(
+ value,
+ "%d-%b-%Y"
+ ).date()
+
+ @validator("finish_date", pre=True)
+ def parse_finish_date(cls, value):
+ return datetime.strptime(
+ value,
+ "%d-%b-%Y"
+ ).date()
-class UserToken(BaseModel):
- id_: uuid.UUID
- name: str
- locked_out: bool = None
- password: str
- permissions: List[str]
diff --git a/overlord/src/app/balance-sheet/balance-sheet.component.html b/overlord/src/app/balance-sheet/balance-sheet.component.html
index 28137f3a..8146547e 100644
--- a/overlord/src/app/balance-sheet/balance-sheet.component.html
+++ b/overlord/src/app/balance-sheet/balance-sheet.component.html
@@ -21,21 +21,21 @@
Group
{{row.group}}
- {{info.footer.group}}
+ {{info.footer?.group}}
Name
{{row.name}}
- {{info.footer.name}}
+ {{info.footer?.name}}
Amount
{{row.subAmount | currency:'INR' | clear}}
- {{info.footer.subAmount | currency:'INR' | clear}}
+ {{info.footer?.subAmount | currency:'INR' | clear}}
@@ -43,7 +43,7 @@
Total
{{row.amount | currency:'INR' | clear}}
- {{info.footer.amount | currency:'INR' | clear}}
+ {{info.footer?.amount | currency:'INR' | clear}}
diff --git a/overlord/src/app/balance-sheet/balance-sheet.component.ts b/overlord/src/app/balance-sheet/balance-sheet.component.ts
index 63cda1a6..4d94d40c 100644
--- a/overlord/src/app/balance-sheet/balance-sheet.component.ts
+++ b/overlord/src/app/balance-sheet/balance-sheet.component.ts
@@ -43,15 +43,12 @@ export class BalanceSheetComponent implements OnInit {
}
show() {
- const info = this.getInfo();
- this.router.navigate(['balance-sheet', info.date]);
+ const date = this.getDate();
+ this.router.navigate(['balance-sheet', date]);
}
- getInfo(): BalanceSheet {
+ getDate(): string {
const formModel = this.form.value;
-
- return {
- date: moment(formModel.date).format('DD-MMM-YYYY')
- };
+ return moment(formModel.date).format('DD-MMM-YYYY');
}
}
diff --git a/overlord/src/app/balance-sheet/balance-sheet.ts b/overlord/src/app/balance-sheet/balance-sheet.ts
index 8235c971..043c6ee0 100644
--- a/overlord/src/app/balance-sheet/balance-sheet.ts
+++ b/overlord/src/app/balance-sheet/balance-sheet.ts
@@ -1,5 +1,12 @@
+export class BalanceSheetItem {
+ name?: string;
+ group?: string;
+ amount?: number;
+ subAmount?: number;
+ order: number;
+}
export class BalanceSheet {
date: string;
- body?: any[];
- footer?: any[];
+ body: BalanceSheetItem[];
+ footer?: BalanceSheetItem;
}
diff --git a/overlord/src/app/cash-flow/cash-flow.component.html b/overlord/src/app/cash-flow/cash-flow.component.html
index 6858fb83..ad7daf68 100644
--- a/overlord/src/app/cash-flow/cash-flow.component.html
+++ b/overlord/src/app/cash-flow/cash-flow.component.html
@@ -26,7 +26,7 @@
Name
- {{row.name}}
+ {{row.name}}
diff --git a/overlord/src/app/cash-flow/cash-flow.ts b/overlord/src/app/cash-flow/cash-flow.ts
index dc5bc422..5c422a9d 100644
--- a/overlord/src/app/cash-flow/cash-flow.ts
+++ b/overlord/src/app/cash-flow/cash-flow.ts
@@ -1,6 +1,6 @@
export class CashFlowItem {
name: string;
- url: string;
+ url: [];
amount: number;
constructor(name: string) {
diff --git a/overlord/src/app/ledger/ledger.component.html b/overlord/src/app/ledger/ledger.component.html
index b6c6ee70..be281cbb 100644
--- a/overlord/src/app/ledger/ledger.component.html
+++ b/overlord/src/app/ledger/ledger.component.html
@@ -47,7 +47,7 @@
Particulars
- {{row.name}}
+ {{row.name}}
Closing Balance
diff --git a/overlord/src/app/ledger/ledger.component.ts b/overlord/src/app/ledger/ledger.component.ts
index 149907be..7a81d3d9 100644
--- a/overlord/src/app/ledger/ledger.component.ts
+++ b/overlord/src/app/ledger/ledger.component.ts
@@ -56,12 +56,7 @@ export class LedgerComponent implements OnInit, AfterViewInit {
}
ngOnInit() {
- this.route.data.pipe(map(
- (data: { info: Ledger }) => {
- data.info.body = data.info.body.map(x => ({...x, url: x['type'].replace(/ /g, '-').toLowerCase()}));
- return data;
- }
- )).subscribe((data: { info: Ledger }) => {
+ this.route.data.subscribe((data: { info: Ledger }) => {
this.info = data.info;
this.calculateTotals();
this.form.setValue({
diff --git a/overlord/src/app/unposted/unposted.ts b/overlord/src/app/unposted/unposted.ts
index 2f5292d0..0a992013 100644
--- a/overlord/src/app/unposted/unposted.ts
+++ b/overlord/src/app/unposted/unposted.ts
@@ -3,7 +3,6 @@ export class Unposted {
date: string;
voucherType: string;
narration: string;
- isPosted: boolean;
debitName: string;
debitAmount: number;
creditName: string;