Ledger now working with response_model
get_edit_url workaround found with transform clientside
This commit is contained in:
parent
9c9f0dfdd6
commit
708a60baf7
brewman
routers/reports
schemas
overlord/src/app
@ -83,7 +83,6 @@ def build_report(start_date, finish_date, db):
|
|||||||
{
|
{
|
||||||
"id": voucher.id,
|
"id": voucher.id,
|
||||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||||
"url": "", # get_edit_url(voucher, request),
|
|
||||||
"type": VoucherType.by_id(voucher.type).name,
|
"type": VoucherType.by_id(voucher.type).name,
|
||||||
"narration": voucher.narration,
|
"narration": voucher.narration,
|
||||||
"posted": voucher.posted,
|
"posted": voucher.posted,
|
||||||
|
@ -10,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 AccountBase
|
from brewman.models.master import AccountBase
|
||||||
from brewman.models.voucher import Voucher, Journal, VoucherType
|
from brewman.models.voucher import Voucher, Journal, VoucherType
|
||||||
|
import brewman.schemas.reports as schemas
|
||||||
from ...core.session import (
|
from ...core.session import (
|
||||||
set_period,
|
set_period,
|
||||||
get_start_date,
|
get_start_date,
|
||||||
@ -28,7 +29,7 @@ def get_db() -> Session:
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
@router.get("")
|
@router.get("", response_model=schemas.Ledger)
|
||||||
def show_blank(
|
def show_blank(
|
||||||
request: Request,
|
request: Request,
|
||||||
user: UserToken = Security(get_user, scopes=["ledger"]),
|
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(
|
def show_data(
|
||||||
id_: uuid.UUID,
|
id_: uuid.UUID,
|
||||||
request: Request,
|
request: Request,
|
||||||
@ -103,7 +104,6 @@ def build_report(account_id, start_date, finish_date, db):
|
|||||||
"id": voucher.id,
|
"id": voucher.id,
|
||||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||||
"name": name,
|
"name": name,
|
||||||
"url": "", # get_edit_url(voucher, request),
|
|
||||||
"type": VoucherType.by_id(voucher.type).name,
|
"type": VoucherType.by_id(voucher.type).name,
|
||||||
"narration": voucher.narration,
|
"narration": voucher.narration,
|
||||||
"debit": debit,
|
"debit": debit,
|
||||||
@ -132,7 +132,7 @@ def opening_balance(account_id, start_date, db):
|
|||||||
credit = 0
|
credit = 0
|
||||||
return {
|
return {
|
||||||
"date": start_date,
|
"date": start_date,
|
||||||
"id": "OB",
|
"id": None,
|
||||||
"name": "Opening Balance",
|
"name": "Opening Balance",
|
||||||
"type": "Opening Balance",
|
"type": "Opening Balance",
|
||||||
"narration": "",
|
"narration": "",
|
||||||
|
@ -107,7 +107,6 @@ def build_report(product_id, start_date, finish_date, db):
|
|||||||
"id": row.Voucher.id,
|
"id": row.Voucher.id,
|
||||||
"date": row.Voucher.date.strftime("%d-%b-%Y"),
|
"date": row.Voucher.date.strftime("%d-%b-%Y"),
|
||||||
"name": name,
|
"name": name,
|
||||||
"url": "", # get_edit_url(row.Voucher, request),
|
|
||||||
"type": VoucherType.by_id(row.Voucher.type).name,
|
"type": VoucherType.by_id(row.Voucher.type).name,
|
||||||
"narration": row.Voucher.narration,
|
"narration": row.Voucher.narration,
|
||||||
"posted": row.Voucher.posted
|
"posted": row.Voucher.posted
|
||||||
|
@ -70,7 +70,6 @@ def build_report(start_date, finish_date, db):
|
|||||||
row = {
|
row = {
|
||||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||||
"supplier": journal.account.name,
|
"supplier": journal.account.name,
|
||||||
"url": "", # get_edit_url(voucher, request),
|
|
||||||
"products": [],
|
"products": [],
|
||||||
"product": item.product.full_name,
|
"product": item.product.full_name,
|
||||||
"quantity": item.quantity,
|
"quantity": item.quantity,
|
||||||
|
@ -113,7 +113,6 @@ def build_report(account_id, start_date, finish_date, db):
|
|||||||
"id": voucher.id,
|
"id": voucher.id,
|
||||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||||
"name": name,
|
"name": name,
|
||||||
"url": "", # get_edit_url(voucher, request),
|
|
||||||
"type": VoucherType.by_id(voucher.type).name,
|
"type": VoucherType.by_id(voucher.type).name,
|
||||||
"narration": voucher.narration,
|
"narration": voucher.narration,
|
||||||
"debit": debit,
|
"debit": debit,
|
||||||
|
@ -57,8 +57,8 @@ def build_report(db: Session):
|
|||||||
|
|
||||||
body.append(
|
body.append(
|
||||||
{
|
{
|
||||||
|
"id": voucher.id,
|
||||||
"date": voucher.date.strftime("%d-%b-%Y"),
|
"date": voucher.date.strftime("%d-%b-%Y"),
|
||||||
"Url": "", # get_edit_url(voucher, request),
|
|
||||||
"voucherType": VoucherType.by_id(voucher.type).name,
|
"voucherType": VoucherType.by_id(voucher.type).name,
|
||||||
"narration": voucher.narration,
|
"narration": voucher.narration,
|
||||||
"isPosted": voucher.posted,
|
"isPosted": voucher.posted,
|
||||||
|
@ -13,6 +13,7 @@ def to_camel(string: str) -> str:
|
|||||||
|
|
||||||
class AccountLink(BaseModel):
|
class AccountLink(BaseModel):
|
||||||
id_: uuid.UUID = Field(...)
|
id_: uuid.UUID = Field(...)
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
fields = {'id_': 'id'}
|
fields = {'id_': 'id'}
|
||||||
|
162
brewman/schemas/reports.py
Normal file
162
brewman/schemas/reports.py
Normal file
@ -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]
|
@ -26,7 +26,7 @@
|
|||||||
<!-- Date Column -->
|
<!-- Date Column -->
|
||||||
<ng-container matColumnDef="date">
|
<ng-container matColumnDef="date">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Date</mat-header-cell>
|
<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>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Type Column -->
|
<!-- Type Column -->
|
||||||
|
@ -7,6 +7,7 @@ import * as moment from 'moment';
|
|||||||
import {DaybookDataSource} from './daybook-datasource';
|
import {DaybookDataSource} from './daybook-datasource';
|
||||||
import {Daybook} from './daybook';
|
import {Daybook} from './daybook';
|
||||||
import {DaybookService} from './daybook.service';
|
import {DaybookService} from './daybook.service';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-daybook',
|
selector: 'app-daybook',
|
||||||
@ -33,8 +34,12 @@ export class DaybookComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data
|
this.route.data.pipe(map(
|
||||||
.subscribe((data: { info: Daybook }) => {
|
(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.info = data.info;
|
||||||
this.form.setValue({
|
this.form.setValue({
|
||||||
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
|
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<!-- Particulars Column -->
|
<!-- Particulars Column -->
|
||||||
<ng-container matColumnDef="particulars">
|
<ng-container matColumnDef="particulars">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Particulars</mat-header-cell>
|
<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>
|
<mat-footer-cell *matFooterCellDef>Closing Balance</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -56,8 +56,12 @@ export class LedgerComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data
|
this.route.data.pipe(map(
|
||||||
.subscribe((data: { info: Ledger }) => {
|
(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.info = data.info;
|
||||||
this.calculateTotals();
|
this.calculateTotals();
|
||||||
this.form.setValue({
|
this.form.setValue({
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<!-- Particulars Column -->
|
<!-- Particulars Column -->
|
||||||
<ng-container matColumnDef="particulars">
|
<ng-container matColumnDef="particulars">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Particulars</mat-header-cell>
|
<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>
|
<mat-footer-cell *matFooterCellDef>Closing Balance</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -61,8 +61,12 @@ export class ProductLedgerComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data
|
this.route.data.pipe(map(
|
||||||
.subscribe((data: { info: ProductLedger }) => {
|
(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.info = data.info;
|
||||||
this.calculateTotals();
|
this.calculateTotals();
|
||||||
this.form.setValue({
|
this.form.setValue({
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<!-- Supplier Column -->
|
<!-- Supplier Column -->
|
||||||
<ng-container matColumnDef="supplier">
|
<ng-container matColumnDef="supplier">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</mat-header-cell>
|
<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>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Product Column -->
|
<!-- Product Column -->
|
||||||
|
@ -6,6 +6,7 @@ import {ActivatedRoute, Router} from '@angular/router';
|
|||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import {PurchaseEntriesDataSource} from './purchase-entries-datasource';
|
import {PurchaseEntriesDataSource} from './purchase-entries-datasource';
|
||||||
import {PurchaseEntries} from './purchase-entries';
|
import {PurchaseEntries} from './purchase-entries';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-purchase-entries',
|
selector: 'app-purchase-entries',
|
||||||
@ -31,8 +32,12 @@ export class PurchaseEntriesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data
|
this.route.data.pipe(map(
|
||||||
.subscribe((data: { info: PurchaseEntries }) => {
|
(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.info = data.info;
|
||||||
this.form.setValue({
|
this.form.setValue({
|
||||||
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
|
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Date Column -->
|
<!-- Date Column -->
|
||||||
<ng-container matColumnDef="date">
|
<ng-container matColumnDef="date">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Date</mat-header-cell>
|
<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>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Type Column -->
|
<!-- Type Column -->
|
||||||
|
@ -5,6 +5,7 @@ import {UnpostedDataSource} from './unposted-datasource';
|
|||||||
import {Unposted} from './unposted';
|
import {Unposted} from './unposted';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {UnpostedService} from './unposted.service';
|
import {UnpostedService} from './unposted.service';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-unposted',
|
selector: 'app-unposted',
|
||||||
@ -23,8 +24,12 @@ export class UnpostedComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.data
|
this.route.data.pipe(map(
|
||||||
.subscribe((data: { info: Unposted[] }) => {
|
(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.info = data.info;
|
||||||
});
|
});
|
||||||
this.dataSource = new UnpostedDataSource(this.paginator, this.sort, this.info);
|
this.dataSource = new UnpostedDataSource(this.paginator, this.sort, this.info);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user