From 708a60baf7494510d771111056b6804c0c3f8386 Mon Sep 17 00:00:00 2001 From: tanshu <tanshu@gmail.com> Date: Tue, 12 May 2020 23:21:12 +0530 Subject: [PATCH] Ledger now working with response_model get_edit_url workaround found with transform clientside --- brewman/routers/reports/daybook.py | 1 - brewman/routers/reports/ledger.py | 8 +- brewman/routers/reports/product_ledger.py | 1 - brewman/routers/reports/purchase_entries.py | 1 - brewman/routers/reports/reconcile.py | 1 - brewman/routers/reports/unposted.py | 2 +- brewman/schemas/master.py | 1 + brewman/schemas/reports.py | 162 ++++++++++++++++++ .../src/app/daybook/daybook.component.html | 2 +- overlord/src/app/daybook/daybook.component.ts | 9 +- overlord/src/app/ledger/ledger.component.html | 2 +- overlord/src/app/ledger/ledger.component.ts | 8 +- .../product-ledger.component.html | 2 +- .../product-ledger.component.ts | 8 +- .../purchase-entries.component.html | 2 +- .../purchase-entries.component.ts | 9 +- .../src/app/unposted/unposted.component.html | 2 +- .../src/app/unposted/unposted.component.ts | 9 +- 18 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 brewman/schemas/reports.py diff --git a/brewman/routers/reports/daybook.py b/brewman/routers/reports/daybook.py index cba83905..f484e041 100644 --- a/brewman/routers/reports/daybook.py +++ b/brewman/routers/reports/daybook.py @@ -83,7 +83,6 @@ def build_report(start_date, finish_date, db): { "id": voucher.id, "date": voucher.date.strftime("%d-%b-%Y"), - "url": "", # get_edit_url(voucher, request), "type": VoucherType.by_id(voucher.type).name, "narration": voucher.narration, "posted": voucher.posted, diff --git a/brewman/routers/reports/ledger.py b/brewman/routers/reports/ledger.py index 3b13da1a..260be158 100644 --- a/brewman/routers/reports/ledger.py +++ b/brewman/routers/reports/ledger.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 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.Ledger) def show_blank( request: Request, user: UserToken = Security(get_user, scopes=["ledger"]), @@ -41,7 +42,7 @@ def show_blank( } -@router.get("/{id_}") +@router.get("/{id_}", response_model=schemas.Ledger) def show_data( id_: uuid.UUID, request: Request, @@ -103,7 +104,6 @@ def build_report(account_id, start_date, finish_date, db): "id": voucher.id, "date": voucher.date.strftime("%d-%b-%Y"), "name": name, - "url": "", # get_edit_url(voucher, request), "type": VoucherType.by_id(voucher.type).name, "narration": voucher.narration, "debit": debit, @@ -132,7 +132,7 @@ def opening_balance(account_id, start_date, db): credit = 0 return { "date": start_date, - "id": "OB", + "id": None, "name": "Opening Balance", "type": "Opening Balance", "narration": "", diff --git a/brewman/routers/reports/product_ledger.py b/brewman/routers/reports/product_ledger.py index 49a11670..08b7d25e 100644 --- a/brewman/routers/reports/product_ledger.py +++ b/brewman/routers/reports/product_ledger.py @@ -107,7 +107,6 @@ def build_report(product_id, start_date, finish_date, db): "id": row.Voucher.id, "date": row.Voucher.date.strftime("%d-%b-%Y"), "name": name, - "url": "", # get_edit_url(row.Voucher, request), "type": VoucherType.by_id(row.Voucher.type).name, "narration": row.Voucher.narration, "posted": row.Voucher.posted diff --git a/brewman/routers/reports/purchase_entries.py b/brewman/routers/reports/purchase_entries.py index 66152bbb..46742363 100644 --- a/brewman/routers/reports/purchase_entries.py +++ b/brewman/routers/reports/purchase_entries.py @@ -70,7 +70,6 @@ def build_report(start_date, finish_date, db): row = { "date": voucher.date.strftime("%d-%b-%Y"), "supplier": journal.account.name, - "url": "", # get_edit_url(voucher, request), "products": [], "product": item.product.full_name, "quantity": item.quantity, diff --git a/brewman/routers/reports/reconcile.py b/brewman/routers/reports/reconcile.py index ca65e4e7..ccf1c7c9 100644 --- a/brewman/routers/reports/reconcile.py +++ b/brewman/routers/reports/reconcile.py @@ -113,7 +113,6 @@ def build_report(account_id, start_date, finish_date, db): "id": voucher.id, "date": voucher.date.strftime("%d-%b-%Y"), "name": name, - "url": "", # get_edit_url(voucher, request), "type": VoucherType.by_id(voucher.type).name, "narration": voucher.narration, "debit": debit, diff --git a/brewman/routers/reports/unposted.py b/brewman/routers/reports/unposted.py index 8a6ddc95..25d39a4e 100644 --- a/brewman/routers/reports/unposted.py +++ b/brewman/routers/reports/unposted.py @@ -57,8 +57,8 @@ def build_report(db: Session): body.append( { + "id": voucher.id, "date": voucher.date.strftime("%d-%b-%Y"), - "Url": "", # get_edit_url(voucher, request), "voucherType": VoucherType.by_id(voucher.type).name, "narration": voucher.narration, "isPosted": voucher.posted, diff --git a/brewman/schemas/master.py b/brewman/schemas/master.py index 50d49afa..6e31c33f 100644 --- a/brewman/schemas/master.py +++ b/brewman/schemas/master.py @@ -13,6 +13,7 @@ def to_camel(string: str) -> str: class AccountLink(BaseModel): id_: uuid.UUID = Field(...) + name: Optional[str] class Config: fields = {'id_': 'id'} diff --git a/brewman/schemas/reports.py b/brewman/schemas/reports.py new file mode 100644 index 00000000..a925213b --- /dev/null +++ b/brewman/schemas/reports.py @@ -0,0 +1,162 @@ +import uuid +from decimal import Decimal +from typing import List, Optional +from datetime import datetime, date +from pydantic import BaseModel, Field, validator + +from brewman.schemas.master import AccountLink + + +def to_camel(string: str) -> str: + first, *others = string.split("_") + return "".join([first] + [word.capitalize() for word in others]) + + +class LedgerItem(BaseModel): + id_: Optional[uuid.UUID] + date_: date + name: str + url: str + type_: str + narration: str + debit: Decimal = Field(multiple_of=0.01) + credit: Decimal = Field(multiple_of=0.01) + posted: bool + + @validator("date_", pre=True) + def parse_date(cls, value): + return datetime.strptime( + value, + "%d-%b-%Y" + ).date() + + class Config: + anystr_strip_whitespace = True + alias_generator = to_camel + + +class Ledger(BaseModel): + start_date: date + finish_date: date + account: Optional[AccountLink] + body: List[LedgerItem] + + 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 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 Config: + fields = {"id_": "id"} + anystr_strip_whitespace = True + alias_generator = to_camel + + +class PermissionItem(BaseModel): + id_: uuid.UUID + name: str + enabled: bool + + class Config: + fields = {"id_": "id"} + + +class RoleIn(BaseModel): + name: str + permissions: List[PermissionItem] + + class Config: + fields = {"id_": "id"} + anystr_strip_whitespace = True + + +class Role(RoleIn): + id_: uuid.UUID + + +class RoleList(BaseModel): + id_: uuid.UUID + name: str + permissions: List[str] + + 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 Config: + fields = {"id_": "id"} + anystr_strip_whitespace = True + + +class UserToken(BaseModel): + id_: uuid.UUID + name: str + locked_out: bool = None + password: str + permissions: List[str] diff --git a/overlord/src/app/daybook/daybook.component.html b/overlord/src/app/daybook/daybook.component.html index c289c708..a730e32e 100644 --- a/overlord/src/app/daybook/daybook.component.html +++ b/overlord/src/app/daybook/daybook.component.html @@ -26,7 +26,7 @@ <!-- Date Column --> <ng-container matColumnDef="date"> <mat-header-cell *matHeaderCellDef mat-sort-header>Date</mat-header-cell> - <mat-cell *matCellDef="let row"><a [href]="row.url">{{row.date}}</a></mat-cell> + <mat-cell *matCellDef="let row"><a [routerLink]="['/', row.url, row.id]">{{row.date}}</a></mat-cell> </ng-container> <!-- Type Column --> diff --git a/overlord/src/app/daybook/daybook.component.ts b/overlord/src/app/daybook/daybook.component.ts index d8020c1a..5ddd65bf 100644 --- a/overlord/src/app/daybook/daybook.component.ts +++ b/overlord/src/app/daybook/daybook.component.ts @@ -7,6 +7,7 @@ import * as moment from 'moment'; import {DaybookDataSource} from './daybook-datasource'; import {Daybook} from './daybook'; import {DaybookService} from './daybook.service'; +import {map} from 'rxjs/operators'; @Component({ selector: 'app-daybook', @@ -33,8 +34,12 @@ export class DaybookComponent implements OnInit { } ngOnInit() { - this.route.data - .subscribe((data: { info: Daybook }) => { + this.route.data.pipe(map( + (data: { info: Daybook }) => { + data.info.body = data.info.body.map(x => ({...x, url: x['type'].replace(/ /g, '-').toLowerCase()})); + return data; + } + )).subscribe((data: { info: Daybook }) => { this.info = data.info; this.form.setValue({ startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), diff --git a/overlord/src/app/ledger/ledger.component.html b/overlord/src/app/ledger/ledger.component.html index 03caee7c..b6c6ee70 100644 --- a/overlord/src/app/ledger/ledger.component.html +++ b/overlord/src/app/ledger/ledger.component.html @@ -47,7 +47,7 @@ <!-- Particulars Column --> <ng-container matColumnDef="particulars"> <mat-header-cell *matHeaderCellDef mat-sort-header>Particulars</mat-header-cell> - <mat-cell *matCellDef="let row"><a [href]="row.url">{{row.name}}</a></mat-cell> + <mat-cell *matCellDef="let row"><a [routerLink]="['/', row.url, row.id]">{{row.name}}</a></mat-cell> <mat-footer-cell *matFooterCellDef>Closing Balance</mat-footer-cell> </ng-container> diff --git a/overlord/src/app/ledger/ledger.component.ts b/overlord/src/app/ledger/ledger.component.ts index 0ed4b23e..149907be 100644 --- a/overlord/src/app/ledger/ledger.component.ts +++ b/overlord/src/app/ledger/ledger.component.ts @@ -56,8 +56,12 @@ export class LedgerComponent implements OnInit, AfterViewInit { } ngOnInit() { - this.route.data - .subscribe((data: { info: Ledger }) => { + 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.info = data.info; this.calculateTotals(); this.form.setValue({ diff --git a/overlord/src/app/product-ledger/product-ledger.component.html b/overlord/src/app/product-ledger/product-ledger.component.html index f61912ee..519325ef 100644 --- a/overlord/src/app/product-ledger/product-ledger.component.html +++ b/overlord/src/app/product-ledger/product-ledger.component.html @@ -44,7 +44,7 @@ <!-- Particulars Column --> <ng-container matColumnDef="particulars"> <mat-header-cell *matHeaderCellDef mat-sort-header>Particulars</mat-header-cell> - <mat-cell *matCellDef="let row"><a [href]="row.url">{{row.name}}</a></mat-cell> + <mat-cell *matCellDef="let row"><a [routerLink]="['/', row.url, row.id]">{{row.name}}</a></mat-cell> <mat-footer-cell *matFooterCellDef>Closing Balance</mat-footer-cell> </ng-container> diff --git a/overlord/src/app/product-ledger/product-ledger.component.ts b/overlord/src/app/product-ledger/product-ledger.component.ts index 1ce5bb8c..e6f9cdcc 100644 --- a/overlord/src/app/product-ledger/product-ledger.component.ts +++ b/overlord/src/app/product-ledger/product-ledger.component.ts @@ -61,8 +61,12 @@ export class ProductLedgerComponent implements OnInit { } ngOnInit() { - this.route.data - .subscribe((data: { info: ProductLedger }) => { + this.route.data.pipe(map( + (data: { info: ProductLedger }) => { + data.info.body = data.info.body.map(x => ({...x, url: x['type'].replace(/ /g, '-').toLowerCase()})); + return data; + } + )).subscribe((data: { info: ProductLedger }) => { this.info = data.info; this.calculateTotals(); this.form.setValue({ diff --git a/overlord/src/app/purchase-entries/purchase-entries.component.html b/overlord/src/app/purchase-entries/purchase-entries.component.html index 7f3f7798..f41dfca1 100644 --- a/overlord/src/app/purchase-entries/purchase-entries.component.html +++ b/overlord/src/app/purchase-entries/purchase-entries.component.html @@ -32,7 +32,7 @@ <!-- Supplier Column --> <ng-container matColumnDef="supplier"> <mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</mat-header-cell> - <mat-cell *matCellDef="let row"><a [href]="row.url">{{row.supplier}}</a></mat-cell> + <mat-cell *matCellDef="let row"><a [routerLink]="['/', row.url, row.id]">{{row.supplier}}</a></mat-cell> </ng-container> <!-- Product Column --> diff --git a/overlord/src/app/purchase-entries/purchase-entries.component.ts b/overlord/src/app/purchase-entries/purchase-entries.component.ts index ec45a8e3..049d5d45 100644 --- a/overlord/src/app/purchase-entries/purchase-entries.component.ts +++ b/overlord/src/app/purchase-entries/purchase-entries.component.ts @@ -6,6 +6,7 @@ import {ActivatedRoute, Router} from '@angular/router'; import * as moment from 'moment'; import {PurchaseEntriesDataSource} from './purchase-entries-datasource'; import {PurchaseEntries} from './purchase-entries'; +import {map} from 'rxjs/operators'; @Component({ selector: 'app-purchase-entries', @@ -31,8 +32,12 @@ export class PurchaseEntriesComponent implements OnInit { } ngOnInit() { - this.route.data - .subscribe((data: { info: PurchaseEntries }) => { + this.route.data.pipe(map( + (data: { info: PurchaseEntries }) => { + data.info.body = data.info.body.map(x => ({...x, url: x['type'].replace(/ /g, '-').toLowerCase()})); + return data; + } + )).subscribe((data: { info: PurchaseEntries }) => { this.info = data.info; this.form.setValue({ startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), diff --git a/overlord/src/app/unposted/unposted.component.html b/overlord/src/app/unposted/unposted.component.html index 65cb9ca7..58430c99 100644 --- a/overlord/src/app/unposted/unposted.component.html +++ b/overlord/src/app/unposted/unposted.component.html @@ -12,7 +12,7 @@ <!-- Date Column --> <ng-container matColumnDef="date"> <mat-header-cell *matHeaderCellDef mat-sort-header>Date</mat-header-cell> - <mat-cell *matCellDef="let row">{{row.date}}</mat-cell> + <mat-cell *matCellDef="let row"><a [routerLink]="['/', row.url, row.id]">{{row.date}}</a></mat-cell> </ng-container> <!-- Type Column --> diff --git a/overlord/src/app/unposted/unposted.component.ts b/overlord/src/app/unposted/unposted.component.ts index 0d99b6f8..8dcd8af8 100644 --- a/overlord/src/app/unposted/unposted.component.ts +++ b/overlord/src/app/unposted/unposted.component.ts @@ -5,6 +5,7 @@ import {UnpostedDataSource} from './unposted-datasource'; import {Unposted} from './unposted'; import {ActivatedRoute, Router} from '@angular/router'; import {UnpostedService} from './unposted.service'; +import {map} from 'rxjs/operators'; @Component({ selector: 'app-unposted', @@ -23,8 +24,12 @@ export class UnpostedComponent implements OnInit { } ngOnInit() { - this.route.data - .subscribe((data: { info: Unposted[] }) => { + this.route.data.pipe(map( + (data: { info: Unposted[] }) => { + data.info = data.info.map(x => ({...x, url: x['type'].replace(/ /g, '-').toLowerCase()})); + return data; + } + )).subscribe((data: { info: Unposted[] }) => { this.info = data.info; }); this.dataSource = new UnpostedDataSource(this.paginator, this.sort, this.info);