From 176559466a5f3fa694ee981d3c123f6bf365b4f7 Mon Sep 17 00:00:00 2001 From: tanshu Date: Tue, 14 Sep 2021 11:36:40 +0530 Subject: [PATCH] Feature: Changed the unposted report to entries report with paging, sorting, etc. --- brewman/brewman/main.py | 4 +- brewman/brewman/routers/reports/__init__.py | 10 ++ brewman/brewman/routers/reports/entries.py | 117 ++++++++++++++ brewman/brewman/routers/reports/unposted.py | 77 ---------- brewman/brewman/schemas/entries.py | 64 ++++++++ brewman/brewman/schemas/unposted.py | 32 ---- overlord/src/app/app-routing.module.ts | 4 +- .../app/cash-flow/cash-flow.component.html | 2 +- .../app/core/nav-bar/nav-bar.component.html | 4 +- .../src/app/entries/entries-datasource.ts | 45 ++++++ .../entries-resolver.service.spec.ts} | 8 +- .../app/entries/entries-resolver.service.ts | 38 +++++ .../entries/entries-routing.module.spec.ts | 13 ++ .../src/app/entries/entries-routing.module.ts | 30 ++++ .../src/app/entries/entries.component.css | 19 +++ .../src/app/entries/entries.component.html | 138 +++++++++++++++++ .../entries.component.spec.ts} | 12 +- overlord/src/app/entries/entries.component.ts | 143 ++++++++++++++++++ .../src/app/entries/entries.module.spec.ts | 13 ++ .../entries.module.ts} | 30 +++- .../entries.service.spec.ts} | 8 +- overlord/src/app/entries/entries.service.ts | 44 ++++++ overlord/src/app/entries/entries.ts | 32 ++++ overlord/src/app/entries/report.ts | 12 ++ .../src/app/purchase/purchase.component.ts | 23 +-- .../src/app/unposted/unposted-datasource.ts | 74 --------- .../app/unposted/unposted-resolver.service.ts | 17 --- .../unposted/unposted-routing.module.spec.ts | 13 -- .../app/unposted/unposted-routing.module.ts | 29 ---- .../src/app/unposted/unposted.component.css | 7 - .../src/app/unposted/unposted.component.html | 108 ------------- .../src/app/unposted/unposted.component.ts | 63 -------- .../src/app/unposted/unposted.module.spec.ts | 13 -- overlord/src/app/unposted/unposted.service.ts | 24 --- overlord/src/app/unposted/unposted.ts | 24 --- 35 files changed, 776 insertions(+), 518 deletions(-) create mode 100644 brewman/brewman/routers/reports/entries.py delete mode 100644 brewman/brewman/routers/reports/unposted.py create mode 100644 brewman/brewman/schemas/entries.py delete mode 100644 brewman/brewman/schemas/unposted.py create mode 100644 overlord/src/app/entries/entries-datasource.ts rename overlord/src/app/{unposted/unposted-resolver.service.spec.ts => entries/entries-resolver.service.spec.ts} (54%) create mode 100644 overlord/src/app/entries/entries-resolver.service.ts create mode 100644 overlord/src/app/entries/entries-routing.module.spec.ts create mode 100644 overlord/src/app/entries/entries-routing.module.ts create mode 100644 overlord/src/app/entries/entries.component.css create mode 100644 overlord/src/app/entries/entries.component.html rename overlord/src/app/{unposted/unposted.component.spec.ts => entries/entries.component.spec.ts} (66%) create mode 100644 overlord/src/app/entries/entries.component.ts create mode 100644 overlord/src/app/entries/entries.module.spec.ts rename overlord/src/app/{unposted/unposted.module.ts => entries/entries.module.ts} (61%) rename overlord/src/app/{unposted/unposted.service.spec.ts => entries/entries.service.spec.ts} (56%) create mode 100644 overlord/src/app/entries/entries.service.ts create mode 100644 overlord/src/app/entries/entries.ts create mode 100644 overlord/src/app/entries/report.ts delete mode 100644 overlord/src/app/unposted/unposted-datasource.ts delete mode 100644 overlord/src/app/unposted/unposted-resolver.service.ts delete mode 100644 overlord/src/app/unposted/unposted-routing.module.spec.ts delete mode 100644 overlord/src/app/unposted/unposted-routing.module.ts delete mode 100644 overlord/src/app/unposted/unposted.component.css delete mode 100644 overlord/src/app/unposted/unposted.component.html delete mode 100644 overlord/src/app/unposted/unposted.component.ts delete mode 100644 overlord/src/app/unposted/unposted.module.spec.ts delete mode 100644 overlord/src/app/unposted/unposted.service.ts delete mode 100644 overlord/src/app/unposted/unposted.ts diff --git a/brewman/brewman/main.py b/brewman/brewman/main.py index b6d6e57a..722dd323 100644 --- a/brewman/brewman/main.py +++ b/brewman/brewman/main.py @@ -57,7 +57,7 @@ from .routers.reports import ( reconcile, stock_movement, trial_balance, - unposted, + entries, ) @@ -104,7 +104,7 @@ app.include_router(raw_material_cost.router, prefix="/api/raw-material-cost", ta app.include_router(reconcile.router, prefix="/api/reconcile", tags=["reports"]) app.include_router(stock_movement.router, prefix="/api/stock-movement", tags=["reports"]) app.include_router(trial_balance.router, prefix="/api/trial-balance", tags=["reports"]) -app.include_router(unposted.router, prefix="/api/unposted", tags=["reports"]) +app.include_router(entries.router, prefix="/api/entries", tags=["reports"]) app.include_router(issue_grid.router, prefix="/api/issue-grid", tags=["vouchers"]) app.include_router(batch.router, prefix="/api/batch", tags=["vouchers"]) diff --git a/brewman/brewman/routers/reports/__init__.py b/brewman/brewman/routers/reports/__init__.py index e69de29b..fdfa1bb4 100644 --- a/brewman/brewman/routers/reports/__init__.py +++ b/brewman/brewman/routers/reports/__init__.py @@ -0,0 +1,10 @@ +from datetime import date, datetime +from typing import Optional + + +def report_start_date(s: str = None) -> Optional[date]: + return None if s is None else datetime.strptime(s, "%d-%b-%Y").date() + + +def report_finish_date(f: str = None) -> Optional[date]: + return None if f is None else datetime.strptime(f, "%d-%b-%Y").date() diff --git a/brewman/brewman/routers/reports/entries.py b/brewman/brewman/routers/reports/entries.py new file mode 100644 index 00000000..c6e4a344 --- /dev/null +++ b/brewman/brewman/routers/reports/entries.py @@ -0,0 +1,117 @@ +from datetime import date +from typing import List, Optional + +import brewman.schemas.entries as schemas + +from fastapi import APIRouter, Depends, Security +from sqlalchemy import desc, or_, select +from sqlalchemy.orm import Session, contains_eager, joinedload +from sqlalchemy.sql.functions import count + +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionFuture +from ...models.journal import Journal +from ...models.voucher import Voucher +from ...models.voucher_type import VoucherType +from ...schemas.user import UserToken +from ...schemas.user_link import UserLink +from . import report_finish_date, report_start_date + + +router = APIRouter() + + +def build_report( + start_date: Optional[date], + finish_date: date, + posted: Optional[bool], + issue: bool, + page_size: int, + page_index: int, + active_sort: str, + sort_direction: str, + db: Session, +) -> (int, List[Voucher]): + query = ( + select(Voucher) + .join(Voucher.user) + .options( + joinedload(Voucher.user, innerjoin=True), + joinedload(Voucher.journals, innerjoin=True).joinedload(Journal.account, innerjoin=True), + contains_eager(Voucher.user), + contains_eager(Voucher.journals, Journal.account), + ) + ) + sq = select(Voucher.id) + counts = select(count(Voucher.id)) + if start_date is not None: + sq = sq.where(or_(Voucher.creation_date >= start_date, Voucher.last_edit_date >= start_date)) + counts = counts.where(or_(Voucher.creation_date >= start_date, Voucher.last_edit_date >= start_date)) + if finish_date is not None: + sq = sq.where(or_(Voucher.creation_date <= finish_date, Voucher.last_edit_date <= finish_date)) + counts = counts.where(or_(Voucher.creation_date <= finish_date, Voucher.last_edit_date <= finish_date)) + if posted is not None: + sq = sq.where(Voucher.posted == posted) + counts = counts.where(Voucher.posted == posted) + if issue is False: + sq = sq.where(Voucher.type != VoucherType.by_name("Issue").id) + counts = counts.where(Voucher.type != VoucherType.by_name("Issue").id) + if active_sort == "date": + if sort_direction == "desc": + sq = sq.order_by(desc(Voucher.date), desc(Voucher.last_edit_date)) + query = query.order_by(desc(Voucher.date), desc(Voucher.last_edit_date)) + else: + sq = sq.order_by(Voucher.date, Voucher.last_edit_date) + query = query.order_by(Voucher.date, Voucher.last_edit_date) + if active_sort == "user": + if sort_direction == "desc": + sq = sq.order_by(desc(Voucher.last_edit_date)) + query = query.order_by(desc(Voucher.last_edit_date)) + else: + sq = sq.order_by(Voucher.last_edit_date) + query = query.order_by(Voucher.last_edit_date) + if page_size: + sq = sq.limit(page_size) + if page_index: + sq = sq.offset(page_size * page_index) + return db.execute(counts).scalar_one(), db.execute(query.where(Voucher.id.in_(sq))).unique().scalars().all() + + +@router.get("", response_model=schemas.Report) +def report_data( + start_date: Optional[date] = Depends(report_start_date), + finish_date: Optional[date] = Depends(report_finish_date), + p: Optional[bool] = None, # Posted + ps: Optional[int] = 50, # Page Size + pi: Optional[int] = 0, # Page Index + a: Optional[str] = "date", # Active Sort + d: Optional[str] = "desc", # Sort Direction + i: Optional[bool] = False, # Show issue vouchers + user: UserToken = Security(get_user, scopes=["ledger"]), +) -> schemas.Report: + with SessionFuture() as db: + counts, report = build_report(start_date, finish_date, p, i, ps, pi, a, d, db) + return schemas.Report( + counts=counts, + report=[ + schemas.Entries( + id=voucher.id, + date=voucher.date, + url=[ + "/", + VoucherType.by_id(voucher.type).name.replace(" ", "-").lower(), + str(voucher.id), + ], + type=VoucherType.by_id(voucher.type).name, + posted=voucher.posted, + narration=voucher.narration, + debitNames=[x.account.name for x in voucher.journals if x.debit == 1], + creditNames=[x.account.name for x in voucher.journals if x.debit != 1], + amount=sum(x.amount for x in voucher.journals if x.debit != 1), + creationDate=voucher.creation_date, + lastEditDate=voucher.last_edit_date, + user=UserLink(id=voucher.user.id, name=voucher.user.name), + ) + for voucher in report + ], + ) diff --git a/brewman/brewman/routers/reports/unposted.py b/brewman/brewman/routers/reports/unposted.py deleted file mode 100644 index 80b5bcc0..00000000 --- a/brewman/brewman/routers/reports/unposted.py +++ /dev/null @@ -1,77 +0,0 @@ -from typing import List - -import brewman.schemas.unposted as schemas - -from fastapi import APIRouter, Security -from sqlalchemy import select -from sqlalchemy.orm import Session - -from ...core.security import get_current_active_user as get_user -from ...db.session import SessionFuture -from ...models.journal import Journal -from ...models.voucher import Voucher -from ...models.voucher_type import VoucherType -from ...schemas.user import UserToken - - -router = APIRouter() - - -@router.get("", response_model=List[schemas.Unposted]) -def report_data( - user: UserToken = Security(get_user, scopes=["post-vouchers"]), -) -> List[schemas.Unposted]: - with SessionFuture() as db: - return build_report(db) - - -def build_report(db: Session) -> List[schemas.Unposted]: - body = [] - - query = ( - db.execute( - select(Voucher) - .join(Voucher.journals) - .join(Journal.account) - .where(Voucher.posted == False, Voucher.type != VoucherType.by_name("Issue").id) # noqa: E712 - .order_by(Voucher.date, Voucher.last_edit_date) - ) - .unique() - .scalars() - .all() - ) - - for voucher in query: - debit = 0 - credit = 0 - name_debit = "" - name_credit = "" - for journal in voucher.journals: - if journal.debit == 1: - debit += journal.amount - name_debit += "{0} / ".format(journal.account.name) - else: - credit += journal.amount - name_credit += "{0} / ".format(journal.account.name) - name_debit = name_debit[:-3] - name_credit = name_credit[:-3] - - body.append( - schemas.Unposted( - id=voucher.id, - date=voucher.date.strftime("%d-%b-%Y"), - url=[ - "/", - VoucherType.by_id(voucher.type).name.replace(" ", "-").lower(), - str(voucher.id), - ], - type=VoucherType.by_id(voucher.type).name, - narration=voucher.narration, - debitName=name_debit, - debitAmount=debit, - creditName=name_credit, - creditAmount=credit, - ) - ) - - return body diff --git a/brewman/brewman/schemas/entries.py b/brewman/brewman/schemas/entries.py new file mode 100644 index 00000000..4ac89499 --- /dev/null +++ b/brewman/brewman/schemas/entries.py @@ -0,0 +1,64 @@ +import uuid + +from datetime import date, datetime +from decimal import Decimal +from typing import List + +from pydantic import BaseModel, validator + +from . import to_camel +from .user_link import UserLink + + +class Entries(BaseModel): + id_: uuid.UUID + date_: date + url: List[str] + type_: str + posted: bool + narration: str + debit_names: List[str] + credit_names: List[str] + amount: Decimal + creation_date: datetime + last_edit_date: datetime + user: UserLink + + class Config: + anystr_strip_whitespace = True + alias_generator = to_camel + json_encoders = { + date: lambda v: v.strftime("%d-%b-%Y"), + datetime: lambda v: v.strftime("%d-%b-%Y %H:%M"), + } + + @validator("date_", pre=True) + def parse_date(cls, value): + if isinstance(value, date): + return value + return datetime.strptime(value, "%d-%b-%Y").date() + + @validator("creation_date", pre=True) + def parse_creation_date(cls, value): + if isinstance(value, datetime): + return value + return datetime.strptime(value, "%d-%b-%Y %H:%M") + + @validator("last_edit_date", pre=True) + def parse_last_edit_date(cls, value): + if isinstance(value, datetime): + return value + return datetime.strptime(value, "%d-%b-%Y %H:%M") + + +class Report(BaseModel): + counts: int + report: List[Entries] + + class Config: + anystr_strip_whitespace = True + alias_generator = to_camel + json_encoders = { + date: lambda v: v.strftime("%d-%b-%Y"), + datetime: lambda v: v.strftime("%d-%b-%Y %H:%M"), + } diff --git a/brewman/brewman/schemas/unposted.py b/brewman/brewman/schemas/unposted.py deleted file mode 100644 index 9a39931c..00000000 --- a/brewman/brewman/schemas/unposted.py +++ /dev/null @@ -1,32 +0,0 @@ -import uuid - -from datetime import date, datetime -from decimal import Decimal -from typing import List - -from pydantic import BaseModel, validator - -from . import to_camel - - -class Unposted(BaseModel): - id_: uuid.UUID - date_: date - url: List[str] - type_: str - narration: str - debit_name: str - debit_amount: Decimal - credit_name: str - credit_amount: Decimal - - @validator("date_", pre=True) - def parse_date(cls, value): - if isinstance(value, date): - return value - return datetime.strptime(value, "%d-%b-%Y").date() - - class Config: - anystr_strip_whitespace = True - alias_generator = to_camel - json_encoders = {date: lambda v: v.strftime("%d-%b-%Y")} diff --git a/overlord/src/app/app-routing.module.ts b/overlord/src/app/app-routing.module.ts index 0bc56a3e..e2d8ab4c 100644 --- a/overlord/src/app/app-routing.module.ts +++ b/overlord/src/app/app-routing.module.ts @@ -165,8 +165,8 @@ const appRoutes: Routes = [ import('./trial-balance/trial-balance.module').then((mod) => mod.TrialBalanceModule), }, { - path: 'unposted', - loadChildren: () => import('./unposted/unposted.module').then((mod) => mod.UnpostedModule), + path: 'entries', + loadChildren: () => import('./entries/entries.module').then((mod) => mod.EntriesModule), }, { path: 'users', diff --git a/overlord/src/app/cash-flow/cash-flow.component.html b/overlord/src/app/cash-flow/cash-flow.component.html index 5eec72ab..10b2eb54 100644 --- a/overlord/src/app/cash-flow/cash-flow.component.html +++ b/overlord/src/app/cash-flow/cash-flow.component.html @@ -35,7 +35,7 @@ - + diff --git a/overlord/src/app/core/nav-bar/nav-bar.component.html b/overlord/src/app/core/nav-bar/nav-bar.component.html index 9de30bae..cf31a9ef 100644 --- a/overlord/src/app/core/nav-bar/nav-bar.component.html +++ b/overlord/src/app/core/nav-bar/nav-bar.component.html @@ -19,7 +19,9 @@ Profit and Loss Balance Sheet Net Transactions - UnPosted Entries + All Entries diff --git a/overlord/src/app/entries/entries-datasource.ts b/overlord/src/app/entries/entries-datasource.ts new file mode 100644 index 00000000..e7a5e850 --- /dev/null +++ b/overlord/src/app/entries/entries-datasource.ts @@ -0,0 +1,45 @@ +import { DataSource } from '@angular/cdk/collections'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { SortDirection } from '@angular/material/sort/sort-direction'; +import { Observable, of as observableOf } from 'rxjs'; + +import { Entries } from './entries'; + +export class EntriesDatasource extends DataSource { + constructor( + public data: Entries[], + public length: number, + private paginator?: MatPaginator, + private sort?: MatSort, + private pageSize?: number, + private pageIndex?: number, + private activeSort?: string, + private sortDirection?: SortDirection, + ) { + super(); + } + + connect(): Observable { + if (this.paginator) { + this.paginator.length = this.length; + if (this.pageSize !== undefined) { + this.paginator.pageSize = this.pageSize; + } + if (this.pageIndex !== undefined) { + this.paginator.pageIndex = this.pageIndex; + } + } + if (this.sort) { + if (this.activeSort !== undefined) { + this.sort.active = this.activeSort; + } + if (this.sortDirection !== undefined) { + this.sort.direction = this.sortDirection; + } + } + return observableOf(this.data); + } + + disconnect() {} +} diff --git a/overlord/src/app/unposted/unposted-resolver.service.spec.ts b/overlord/src/app/entries/entries-resolver.service.spec.ts similarity index 54% rename from overlord/src/app/unposted/unposted-resolver.service.spec.ts rename to overlord/src/app/entries/entries-resolver.service.spec.ts index 8edaf037..30c9e3e6 100644 --- a/overlord/src/app/unposted/unposted-resolver.service.spec.ts +++ b/overlord/src/app/entries/entries-resolver.service.spec.ts @@ -1,17 +1,17 @@ import { HttpClientModule } from '@angular/common/http'; import { inject, TestBed } from '@angular/core/testing'; -import { UnpostedResolver } from './unposted-resolver.service'; +import { EntriesResolver } from './entries-resolver.service'; -describe('UnpostedResolver', () => { +describe('EntriesResolver', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientModule], - providers: [UnpostedResolver], + providers: [EntriesResolver], }); }); - it('should be created', inject([UnpostedResolver], (service: UnpostedResolver) => { + it('should be created', inject([EntriesResolver], (service: EntriesResolver) => { expect(service).toBeTruthy(); })); }); diff --git a/overlord/src/app/entries/entries-resolver.service.ts b/overlord/src/app/entries/entries-resolver.service.ts new file mode 100644 index 00000000..3f89c72a --- /dev/null +++ b/overlord/src/app/entries/entries-resolver.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; +import { Observable } from 'rxjs/internal/Observable'; + +import { EntriesService } from './entries.service'; +import { Report } from './report'; + +@Injectable({ + providedIn: 'root', +}) +export class EntriesResolver implements Resolve { + constructor(private ser: EntriesService) {} + + resolve(route: ActivatedRouteSnapshot): Observable { + const start_date = route.queryParamMap.get('s'); + const finish_date = route.queryParamMap.get('f'); + const posted = + route.queryParamMap.get('p') === null ? null : route.queryParamMap.get('p') === 'true'; + const page_size = + route.queryParamMap.get('ps') === null ? 50 : +(route.queryParamMap.get('ps') as string); + const page_index = + route.queryParamMap.get('pi') === null ? 0 : +(route.queryParamMap.get('pi') as string); + const sort = route.queryParamMap.get('a') ?? 'date'; + const direction = route.queryParamMap.get('d') ?? 'desc'; + const issue_vouchers = + route.queryParamMap.get('i') === null ? false : route.queryParamMap.get('i') === 'true'; + return this.ser.list( + start_date, + finish_date, + posted, + page_size, + page_index, + sort, + direction, + issue_vouchers, + ); + } +} diff --git a/overlord/src/app/entries/entries-routing.module.spec.ts b/overlord/src/app/entries/entries-routing.module.spec.ts new file mode 100644 index 00000000..0762baca --- /dev/null +++ b/overlord/src/app/entries/entries-routing.module.spec.ts @@ -0,0 +1,13 @@ +import { EntriesRoutingModule } from './entries-routing.module'; + +describe('EntriesRoutingModule', () => { + let entriesRoutingModule: EntriesRoutingModule; + + beforeEach(() => { + entriesRoutingModule = new EntriesRoutingModule(); + }); + + it('should create an instance', () => { + expect(entriesRoutingModule).toBeTruthy(); + }); +}); diff --git a/overlord/src/app/entries/entries-routing.module.ts b/overlord/src/app/entries/entries-routing.module.ts new file mode 100644 index 00000000..ac6b2c50 --- /dev/null +++ b/overlord/src/app/entries/entries-routing.module.ts @@ -0,0 +1,30 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { AuthGuard } from '../auth/auth-guard.service'; + +import { EntriesResolver } from './entries-resolver.service'; +import { EntriesComponent } from './entries.component'; + +const entriesRoutes: Routes = [ + { + path: '', + component: EntriesComponent, + canActivate: [AuthGuard], + data: { + permission: 'Ledger', + }, + resolve: { + info: EntriesResolver, + }, + runGuardsAndResolvers: 'always', + }, +]; + +@NgModule({ + imports: [CommonModule, RouterModule.forChild(entriesRoutes)], + exports: [RouterModule], + providers: [EntriesResolver], +}) +export class EntriesRoutingModule {} diff --git a/overlord/src/app/entries/entries.component.css b/overlord/src/app/entries/entries.component.css new file mode 100644 index 00000000..db9f0ff9 --- /dev/null +++ b/overlord/src/app/entries/entries.component.css @@ -0,0 +1,19 @@ +.right { + display: flex; + justify-content: flex-end; +} +.my-margin { + margin: 0 12px; +} +.selected { + background: #fff3cd; +} + +.unposted { + background: #f8d7da; +} + +.mat-column-date, +.mat-column-voucherType { + max-width: 100px; +} diff --git a/overlord/src/app/entries/entries.component.html b/overlord/src/app/entries/entries.component.html new file mode 100644 index 00000000..1453f9db --- /dev/null +++ b/overlord/src/app/entries/entries.component.html @@ -0,0 +1,138 @@ + + + Entries + +
+
+ + + + + + + + + + + +
+
+ + Posted + Not Posted + All + + + Include Issue Entries + +
+
+ + + + + Date + {{ row.date }} + + + + + Type + {{ row.type }} + + + + + Narration + {{ row.narration }} + + + + + Debit + +
    +
  • {{ item }}
  • +
+
+
+ + + + Credit + +
    +
  • {{ item }}
  • +
+
+
+ + + + Amount + {{ row.amount | currency: 'INR' }} + + + + + User + +
    +
  • {{ row.creationDate | localTime }}
  • +
  • {{ row.lastEditDate | localTime }}
  • +
  • {{ row.user.name }}
  • +
+
+
+ + + +
+ + + +
+
diff --git a/overlord/src/app/unposted/unposted.component.spec.ts b/overlord/src/app/entries/entries.component.spec.ts similarity index 66% rename from overlord/src/app/unposted/unposted.component.spec.ts rename to overlord/src/app/entries/entries.component.spec.ts index 43a3e076..c75ffa26 100644 --- a/overlord/src/app/unposted/unposted.component.spec.ts +++ b/overlord/src/app/entries/entries.component.spec.ts @@ -2,23 +2,23 @@ import { HttpClientModule } from '@angular/common/http'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { UnpostedComponent } from './unposted.component'; +import { EntriesComponent } from './entries.component'; -describe('UnpostedComponent', () => { - let component: UnpostedComponent; - let fixture: ComponentFixture; +describe('EntriesComponent', () => { + let component: EntriesComponent; + let fixture: ComponentFixture; beforeEach( waitForAsync(() => { TestBed.configureTestingModule({ imports: [HttpClientModule, RouterTestingModule], - declarations: [UnpostedComponent], + declarations: [EntriesComponent], }).compileComponents(); }), ); beforeEach(() => { - fixture = TestBed.createComponent(UnpostedComponent); + fixture = TestBed.createComponent(EntriesComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/overlord/src/app/entries/entries.component.ts b/overlord/src/app/entries/entries.component.ts new file mode 100644 index 00000000..ce4a511f --- /dev/null +++ b/overlord/src/app/entries/entries.component.ts @@ -0,0 +1,143 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatRadioChange } from '@angular/material/radio'; +import { MatSort } from '@angular/material/sort'; +import { SortDirection } from '@angular/material/sort/sort-direction'; +import { ActivatedRoute, Router } from '@angular/router'; +import * as moment from 'moment'; + +import { EntriesDatasource } from './entries-datasource'; +import { Report } from './report'; + +@Component({ + selector: 'app-entries', + templateUrl: './entries.component.html', + styleUrls: ['./entries.component.css'], +}) +export class EntriesComponent implements OnInit { + @ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator; + @ViewChild(MatSort, { static: true }) sort?: MatSort; + info: Report = new Report(); + dataSource: EntriesDatasource = new EntriesDatasource(this.info.report, 0); + form: FormGroup; + displayedColumns = [ + 'date', + 'voucherType', + 'narration', + 'debitNames', + 'creditNames', + 'amount', + 'user', + ]; + + posted: boolean | null = null; + issue: boolean = false; + constructor(private route: ActivatedRoute, private router: Router, private fb: FormBuilder) { + this.form = this.fb.group({ + startDate: '', + finishDate: '', + posted: '', + issue: '', + }); + } + + ngOnInit() { + this.route.data.subscribe((value) => { + const data = value as { info: Report }; + this.info = data.info; + const queryMap = this.route.snapshot.queryParamMap; + const startDateO = queryMap.get('s'); + const finishDateO = queryMap.get('f'); + const startDate = startDateO !== null ? moment(startDateO, 'DD-MMM-YYYY').toDate() : ''; + const finishDate = finishDateO !== null ? moment(finishDateO, 'DD-MMM-YYYY').toDate() : ''; + const postedO = queryMap.get('p'); + this.posted = postedO !== null ? postedO === 'true' : null; + const pageSizeO = queryMap.get('ps'); + const pageSize = pageSizeO !== null ? +pageSizeO : 50; + const pageIndexO = queryMap.get('pi'); + const pageIndex = pageIndexO !== null ? +pageIndexO : 0; + const activeSortO = queryMap.get('a'); + const activeSort = activeSortO !== null ? (activeSortO as string) : 'date'; + const sortDirectionO = queryMap.get('d'); + const sortDirection = sortDirectionO !== null ? (sortDirectionO as SortDirection) : 'desc'; + const issueO = queryMap.get('i'); + this.issue = issueO !== null ? issueO === 'true' : false; + this.form.setValue({ + startDate: startDate, + finishDate: finishDate, + posted: postedO ?? 'null', + issue: this.issue, + }); + if (this.posted === null || this.posted) { + (this.form.get('issue') as FormControl).enable(); + } else { + (this.form.get('issue') as FormControl).disable(); + } + this.dataSource = new EntriesDatasource( + this.info.report, + this.info.counts, + this.paginator, + this.sort, + pageSize, + pageIndex, + activeSort, + sortDirection, + ); + }); + this.sort?.sortChange.subscribe((x) => + this.router.navigate([], { + relativeTo: this.route, + queryParams: { a: this.sort?.active ?? 'date', d: this.sort?.direction }, + queryParamsHandling: 'merge', + }), + ); + this.paginator?.page.subscribe((x) => + this.router.navigate([], { + relativeTo: this.route, + queryParams: { ps: this.paginator?.pageSize, pi: this.paginator?.pageIndex }, + queryParamsHandling: 'merge', + }), + ); + } + + refresh() { + const formModel = this.form.value; + const startDate = formModel.startDate + ? moment(formModel.startDate).format('DD-MMM-YYYY') + : null; + const finishDate = formModel.finishDate + ? moment(formModel.finishDate).format('DD-MMM-YYYY') + : null; + this.router.navigate([], { + relativeTo: this.route, + queryParams: { s: startDate, f: finishDate }, + queryParamsHandling: 'merge', + }); + } + + togglePosted($event: MatRadioChange) { + if ($event.value === 'true') { + this.posted = true; + } else if ($event.value === 'false') { + this.posted = false; + this.issue = false; + } else { + this.posted = null; + } + this.router.navigate([], { + relativeTo: this.route, + queryParams: { p: this.posted, i: this.issue || null }, + queryParamsHandling: 'merge', + }); + } + + toggleIssue() { + this.issue = !this.issue; + this.router.navigate([], { + relativeTo: this.route, + queryParams: { i: this.issue || null }, + queryParamsHandling: 'merge', + }); + } +} diff --git a/overlord/src/app/entries/entries.module.spec.ts b/overlord/src/app/entries/entries.module.spec.ts new file mode 100644 index 00000000..a0ee9e04 --- /dev/null +++ b/overlord/src/app/entries/entries.module.spec.ts @@ -0,0 +1,13 @@ +import { EntriesModule } from './entries.module'; + +describe('EntriesModule', () => { + let entriesModule: EntriesModule; + + beforeEach(() => { + entriesModule = new EntriesModule(); + }); + + it('should create an instance', () => { + expect(entriesModule).toBeTruthy(); + }); +}); diff --git a/overlord/src/app/unposted/unposted.module.ts b/overlord/src/app/entries/entries.module.ts similarity index 61% rename from overlord/src/app/unposted/unposted.module.ts rename to overlord/src/app/entries/entries.module.ts index f78e608f..823d591e 100644 --- a/overlord/src/app/unposted/unposted.module.ts +++ b/overlord/src/app/entries/entries.module.ts @@ -2,22 +2,32 @@ import { A11yModule } from '@angular/cdk/a11y'; import { CdkTableModule } from '@angular/cdk/table'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { ReactiveFormsModule } from '@angular/forms'; +import { MomentDateAdapter } from '@angular/material-moment-adapter'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatNativeDateModule } from '@angular/material/core'; +import { + DateAdapter, + MAT_DATE_FORMATS, + MAT_DATE_LOCALE, + MatNativeDateModule, +} from '@angular/material/core'; +import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatPaginatorModule } from '@angular/material/paginator'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatRadioModule } from '@angular/material/radio'; import { MatSortModule } from '@angular/material/sort'; import { MatTableModule } from '@angular/material/table'; import { SharedModule } from '../shared/shared.module'; -import { UnpostedRoutingModule } from './unposted-routing.module'; -import { UnpostedComponent } from './unposted.component'; +import { EntriesRoutingModule } from './entries-routing.module'; +import { EntriesComponent } from './entries.component'; export const MY_FORMATS = { parse: { @@ -44,12 +54,20 @@ export const MY_FORMATS = { MatNativeDateModule, MatPaginatorModule, MatProgressSpinnerModule, + MatRadioModule, MatSortModule, MatTableModule, SharedModule, - UnpostedRoutingModule, + EntriesRoutingModule, MatExpansionModule, + MatDatepickerModule, + ReactiveFormsModule, + FlexLayoutModule, + ], + declarations: [EntriesComponent], + providers: [ + { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] }, + { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }, ], - declarations: [UnpostedComponent], }) -export class UnpostedModule {} +export class EntriesModule {} diff --git a/overlord/src/app/unposted/unposted.service.spec.ts b/overlord/src/app/entries/entries.service.spec.ts similarity index 56% rename from overlord/src/app/unposted/unposted.service.spec.ts rename to overlord/src/app/entries/entries.service.spec.ts index ff0b67fe..47f28f3d 100644 --- a/overlord/src/app/unposted/unposted.service.spec.ts +++ b/overlord/src/app/entries/entries.service.spec.ts @@ -1,17 +1,17 @@ import { HttpClientModule } from '@angular/common/http'; import { inject, TestBed } from '@angular/core/testing'; -import { UnpostedService } from './unposted.service'; +import { EntriesService } from './entries.service'; -describe('UnpostedService', () => { +describe('EntriesService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientModule], - providers: [UnpostedService], + providers: [EntriesService], }); }); - it('should be created', inject([UnpostedService], (service: UnpostedService) => { + it('should be created', inject([EntriesService], (service: EntriesService) => { expect(service).toBeTruthy(); })); }); diff --git a/overlord/src/app/entries/entries.service.ts b/overlord/src/app/entries/entries.service.ts new file mode 100644 index 00000000..7ba0cb15 --- /dev/null +++ b/overlord/src/app/entries/entries.service.ts @@ -0,0 +1,44 @@ +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs/internal/Observable'; +import { catchError } from 'rxjs/operators'; + +import { ErrorLoggerService } from '../core/error-logger.service'; + +import { Report } from './report'; + +const url = '/api/entries'; +const serviceName = 'EntriesService'; + +@Injectable({ + providedIn: 'root', +}) +export class EntriesService { + constructor(private http: HttpClient, private log: ErrorLoggerService) {} + + list( + start_date: string | null, + finish_date: string | null, + posted: boolean | null, + page_size: number, + page_index: number, + sort: string, + direction: string, + issue: boolean, + ): Observable { + let params = new HttpParams(); + if (start_date !== null) params = params.set('s', start_date); + if (finish_date !== null) params = params.set('f', finish_date); + if (posted !== null) params = params.set('p', posted.toString()); + params = params + .set('ps', page_size) + .set('pi', page_index) + .set('a', sort) + .set('d', direction) + .set('i', issue.toString()); + + return this.http + .get(url, { params }) + .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + } +} diff --git a/overlord/src/app/entries/entries.ts b/overlord/src/app/entries/entries.ts new file mode 100644 index 00000000..91217dba --- /dev/null +++ b/overlord/src/app/entries/entries.ts @@ -0,0 +1,32 @@ +import { User } from '../core/user'; + +export class Entries { + id: string; + date: string; + url: string[]; + type: string; + posted: boolean; + narration: string; + debitNames: string[]; + creditNames: string[]; + amount: number; + creationDate: string; + lastEditDate: string; + user: User; + + public constructor(init?: Partial) { + this.id = ''; + this.date = ''; + this.url = []; + this.type = ''; + this.posted = false; + this.narration = ''; + this.debitNames = []; + this.creditNames = []; + this.amount = 0; + this.creationDate = ''; + this.lastEditDate = ''; + this.user = new User(); + Object.assign(this, init); + } +} diff --git a/overlord/src/app/entries/report.ts b/overlord/src/app/entries/report.ts new file mode 100644 index 00000000..9bf81443 --- /dev/null +++ b/overlord/src/app/entries/report.ts @@ -0,0 +1,12 @@ +import { Entries } from './entries'; + +export class Report { + counts: number; + report: Entries[]; + + public constructor(init?: Partial) { + this.counts = 0; + this.report = []; + Object.assign(this, init); + } +} diff --git a/overlord/src/app/purchase/purchase.component.ts b/overlord/src/app/purchase/purchase.component.ts index 69130058..cc340fd1 100644 --- a/overlord/src/app/purchase/purchase.component.ts +++ b/overlord/src/app/purchase/purchase.component.ts @@ -364,20 +364,21 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy { productSelected(event: MatAutocompleteSelectedEvent): void { const product: Product = event.option.value; + const addRowForm: FormControl = this.form.get('addRow') as FormControl; this.product = product; - ((this.form.get('addRow') as FormControl).get('price') as FormControl).setValue(product.price); + (addRowForm.get('price') as FormControl).setValue(product.price); if (product.isRateContracted) { - ((this.form.get('addRow') as FormControl).get('price') as FormControl).disable(); - ((this.form.get('addRow') as FormControl).get('tax') as FormControl).disable(); - ((this.form.get('addRow') as FormControl).get('discount') as FormControl).disable(); - ((this.form.get('addRow') as FormControl).get('tax') as FormControl).setValue('RC'); - ((this.form.get('addRow') as FormControl).get('discount') as FormControl).setValue('RC'); + (addRowForm.get('price') as FormControl).disable(); + (addRowForm.get('tax') as FormControl).disable(); + (addRowForm.get('discount') as FormControl).disable(); + (addRowForm.get('tax') as FormControl).setValue('RC'); + (addRowForm.get('discount') as FormControl).setValue('RC'); } else { - ((this.form.get('addRow') as FormControl).get('price') as FormControl).enable(); - ((this.form.get('addRow') as FormControl).get('tax') as FormControl).enable(); - ((this.form.get('addRow') as FormControl).get('discount') as FormControl).enable(); - ((this.form.get('addRow') as FormControl).get('tax') as FormControl).setValue(''); - ((this.form.get('addRow') as FormControl).get('discount') as FormControl).setValue(''); + (addRowForm.get('price') as FormControl).enable(); + (addRowForm.get('tax') as FormControl).enable(); + (addRowForm.get('discount') as FormControl).enable(); + (addRowForm.get('tax') as FormControl).setValue(''); + (addRowForm.get('discount') as FormControl).setValue(''); } } diff --git a/overlord/src/app/unposted/unposted-datasource.ts b/overlord/src/app/unposted/unposted-datasource.ts deleted file mode 100644 index 215ab5f1..00000000 --- a/overlord/src/app/unposted/unposted-datasource.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { EventEmitter } from '@angular/core'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; -import { MatSort, Sort } from '@angular/material/sort'; -import { merge, Observable, of as observableOf } from 'rxjs'; -import { map } from 'rxjs/operators'; - -import { Unposted } from './unposted'; - -/** Simple sort comparator for example ID/Name columns (for client-side sorting). */ -const compare = (a: string | number, b: string | number, isAsc: boolean) => - (a < b ? -1 : 1) * (isAsc ? 1 : -1); - -export class UnpostedDataSource extends DataSource { - constructor(public data: Unposted[], private paginator?: MatPaginator, private sort?: MatSort) { - super(); - } - - connect(): Observable { - const dataMutations: (Observable | EventEmitter | EventEmitter)[] = - [observableOf(this.data)]; - if (this.paginator) { - dataMutations.push((this.paginator as MatPaginator).page); - } - if (this.sort) { - dataMutations.push((this.sort as MatSort).sortChange); - } - - // Set the paginators length - if (this.paginator) { - this.paginator.length = this.data.length; - } - - return merge(...dataMutations).pipe( - map(() => this.getPagedData(this.getSortedData([...this.data]))), - ); - } - - disconnect() {} - - private getPagedData(data: Unposted[]) { - if (this.paginator === undefined) { - return data; - } - const startIndex = this.paginator.pageIndex * this.paginator.pageSize; - return data.splice(startIndex, this.paginator.pageSize); - } - - private getSortedData(data: Unposted[]) { - if (this.sort === undefined) { - return data; - } - if (!this.sort.active || this.sort.direction === '') { - return data; - } - const sort = this.sort as MatSort; - - return data.sort((a: Unposted, b: Unposted) => { - const isAsc = sort.direction === 'asc'; - switch (sort.active) { - case 'date': - return compare(a.date, b.date, isAsc); - case 'type': - return compare(a.type, b.type, isAsc); - case 'debitAmount': - return compare(+a.debitAmount, +b.debitAmount, isAsc); - case 'creditAmount': - return compare(+a.creditAmount, +b.creditAmount, isAsc); - default: - return 0; - } - }); - } -} diff --git a/overlord/src/app/unposted/unposted-resolver.service.ts b/overlord/src/app/unposted/unposted-resolver.service.ts deleted file mode 100644 index 4557bc6a..00000000 --- a/overlord/src/app/unposted/unposted-resolver.service.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Resolve } from '@angular/router'; -import { Observable } from 'rxjs/internal/Observable'; - -import { Unposted } from './unposted'; -import { UnpostedService } from './unposted.service'; - -@Injectable({ - providedIn: 'root', -}) -export class UnpostedResolver implements Resolve { - constructor(private ser: UnpostedService) {} - - resolve(): Observable { - return this.ser.list(); - } -} diff --git a/overlord/src/app/unposted/unposted-routing.module.spec.ts b/overlord/src/app/unposted/unposted-routing.module.spec.ts deleted file mode 100644 index 196c5639..00000000 --- a/overlord/src/app/unposted/unposted-routing.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { UnpostedRoutingModule } from './unposted-routing.module'; - -describe('UnpostedRoutingModule', () => { - let unpostedRoutingModule: UnpostedRoutingModule; - - beforeEach(() => { - unpostedRoutingModule = new UnpostedRoutingModule(); - }); - - it('should create an instance', () => { - expect(unpostedRoutingModule).toBeTruthy(); - }); -}); diff --git a/overlord/src/app/unposted/unposted-routing.module.ts b/overlord/src/app/unposted/unposted-routing.module.ts deleted file mode 100644 index 60223c8c..00000000 --- a/overlord/src/app/unposted/unposted-routing.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { AuthGuard } from '../auth/auth-guard.service'; - -import { UnpostedResolver } from './unposted-resolver.service'; -import { UnpostedComponent } from './unposted.component'; - -const unpostedRoutes: Routes = [ - { - path: '', - component: UnpostedComponent, - canActivate: [AuthGuard], - data: { - permission: 'post-vouchers', - }, - resolve: { - info: UnpostedResolver, - }, - }, -]; - -@NgModule({ - imports: [CommonModule, RouterModule.forChild(unpostedRoutes)], - exports: [RouterModule], - providers: [UnpostedResolver], -}) -export class UnpostedRoutingModule {} diff --git a/overlord/src/app/unposted/unposted.component.css b/overlord/src/app/unposted/unposted.component.css deleted file mode 100644 index 4add356c..00000000 --- a/overlord/src/app/unposted/unposted.component.css +++ /dev/null @@ -1,7 +0,0 @@ -.right { - display: flex; - justify-content: flex-end; -} -.my-margin { - margin: 0 12px; -} diff --git a/overlord/src/app/unposted/unposted.component.html b/overlord/src/app/unposted/unposted.component.html deleted file mode 100644 index 1860b376..00000000 --- a/overlord/src/app/unposted/unposted.component.html +++ /dev/null @@ -1,108 +0,0 @@ - - - Unposted - - refresh - Refresh - - - - - Self aware panel - - Currently I am {{ panelOpenState ? 'open' : 'closed' }} - - - - Unposted - -

- - All userscv - - - Unposted - -
- - - - - Date - {{ row.date }} - - - - - Type - {{ row.type }} - - - - - Narration - {{ row.narration }} - - - - - Debit - {{ row.debitName }} - - - - - Amount - {{ - row.debitAmount | currency: 'INR' | accounting - }} - - - - - Credit - {{ row.creditName }} - - - - - Amount - {{ - row.creditAmount | currency: 'INR' | accounting - }} - - - - - - - - - -
diff --git a/overlord/src/app/unposted/unposted.component.ts b/overlord/src/app/unposted/unposted.component.ts deleted file mode 100644 index 44094d71..00000000 --- a/overlord/src/app/unposted/unposted.component.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort } from '@angular/material/sort'; -import { ActivatedRoute, Router } from '@angular/router'; - -import { Unposted } from './unposted'; -import { UnpostedDataSource } from './unposted-datasource'; -import { UnpostedService } from './unposted.service'; - -@Component({ - selector: 'app-unposted', - templateUrl: './unposted.component.html', - styleUrls: ['./unposted.component.css'], -}) -export class UnpostedComponent implements OnInit { - @ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator; - @ViewChild(MatSort, { static: true }) sort?: MatSort; - info: Unposted[] = []; - dataSource: UnpostedDataSource = new UnpostedDataSource(this.info); - /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns = [ - 'date', - 'voucherType', - 'narration', - 'debitName', - 'debitAmount', - 'creditName', - 'creditAmount', - ]; - - panelOpenState = false; - unposted: boolean | undefined = undefined; - constructor( - private route: ActivatedRoute, - private router: Router, - private ser: UnpostedService, - ) {} - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: Unposted[] }; - - this.info = data.info; - }); - this.dataSource = new UnpostedDataSource(this.info, this.paginator, this.sort); - } - - refresh() { - this.ser.list().subscribe((info: Unposted[]) => { - this.info = info; - }); - } - - toggleUnposted() { - if (this.unposted === undefined) { - this.unposted = false; - } else if (!this.unposted) { - this.unposted = true; - } else { - this.unposted = undefined; - } - } -} diff --git a/overlord/src/app/unposted/unposted.module.spec.ts b/overlord/src/app/unposted/unposted.module.spec.ts deleted file mode 100644 index 40e2965b..00000000 --- a/overlord/src/app/unposted/unposted.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { UnpostedModule } from './unposted.module'; - -describe('UnpostedModule', () => { - let unpostedModule: UnpostedModule; - - beforeEach(() => { - unpostedModule = new UnpostedModule(); - }); - - it('should create an instance', () => { - expect(unpostedModule).toBeTruthy(); - }); -}); diff --git a/overlord/src/app/unposted/unposted.service.ts b/overlord/src/app/unposted/unposted.service.ts deleted file mode 100644 index c8bbbdce..00000000 --- a/overlord/src/app/unposted/unposted.service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/internal/Observable'; -import { catchError } from 'rxjs/operators'; - -import { ErrorLoggerService } from '../core/error-logger.service'; - -import { Unposted } from './unposted'; - -const url = '/api/unposted'; -const serviceName = 'UnpostedService'; - -@Injectable({ - providedIn: 'root', -}) -export class UnpostedService { - constructor(private http: HttpClient, private log: ErrorLoggerService) {} - - list(): Observable { - return this.http - .get(url) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; - } -} diff --git a/overlord/src/app/unposted/unposted.ts b/overlord/src/app/unposted/unposted.ts deleted file mode 100644 index c1f35f73..00000000 --- a/overlord/src/app/unposted/unposted.ts +++ /dev/null @@ -1,24 +0,0 @@ -export class Unposted { - id: string; - date: string; - url: string[]; - type: string; - narration: string; - debitName: string; - debitAmount: number; - creditName: string; - creditAmount: number; - - public constructor(init?: Partial) { - this.id = ''; - this.date = ''; - this.url = []; - this.type = ''; - this.narration = ''; - this.debitName = ''; - this.debitAmount = 0; - this.creditName = ''; - this.creditAmount = 0; - Object.assign(this, init); - } -}