From 55d5017254352bb8b7bdd53c894410894361740d Mon Sep 17 00:00:00 2001 From: Amritanshu Date: Tue, 17 Dec 2024 08:46:29 +0530 Subject: [PATCH] Product sale report can now be section wise --- .../routers/reports/product_sale_report.py | 38 ++++---- barker/barker/routers/reports/sale_report.py | 1 + .../product-sale-report.component.html | 17 +++- .../product-sale-report.component.ts | 87 ++++++++----------- .../product-sale-report.resolver.ts | 3 +- .../product-sale-report.routes.ts | 2 + .../product-sale-report.service.ts | 10 ++- .../product-sale-report.ts | 2 + .../app/sale-report/sale-report.component.ts | 21 ++--- 9 files changed, 98 insertions(+), 83 deletions(-) diff --git a/barker/barker/routers/reports/product_sale_report.py b/barker/barker/routers/reports/product_sale_report.py index 60db011..20cf7be 100644 --- a/barker/barker/routers/reports/product_sale_report.py +++ b/barker/barker/routers/reports/product_sale_report.py @@ -1,15 +1,16 @@ import uuid from datetime import date, datetime, time, timedelta -from typing import Any +from typing import Annotated, Any -from fastapi import APIRouter, Cookie, Depends, Security +from fastapi import APIRouter, Cookie, Depends, Query, Security from sqlalchemy import func, or_, select from sqlalchemy.orm import Session from ...core.config import settings from ...core.security import get_current_active_user as get_user from ...db.session import SessionFuture +from ...models.food_table import FoodTable from ...models.inventory import Inventory from ...models.kot import Kot from ...models.menu_category import MenuCategory @@ -31,6 +32,7 @@ router = APIRouter() def product_sale_report_view( start_date: date = Depends(report_start_date), finish_date: date = Depends(report_finish_date), + section: Annotated[uuid.UUID | None, Query()] = None, user: UserToken = Security(get_user, scopes=["product-sale-report"]), ): check_audit_permission(start_date, user.permissions) @@ -38,11 +40,12 @@ def product_sale_report_view( return { "startDate": start_date.strftime("%d-%b-%Y"), "finishDate": finish_date.strftime("%d-%b-%Y"), - "amounts": product_sale_report(start_date, finish_date, db), + "sectionId": str(section) if section is not None else None, + "amounts": product_sale_report(start_date, finish_date, section, db), } -def product_sale_report(s: date, f: date, db: Session): +def product_sale_report(s: date, f: date, id_: uuid.UUID, db: Session): start_date = datetime.combine(s, time()) + timedelta( minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES ) @@ -51,7 +54,7 @@ def product_sale_report(s: date, f: date, db: Session): ) day = func.date_trunc("day", Voucher.date - timedelta(minutes=settings.NEW_DAY_OFFSET_MINUTES)).label("day") - list_ = db.execute( + query = ( select( ProductVersion.id, ProductVersion.full_name, @@ -65,6 +68,7 @@ def product_sale_report(s: date, f: date, db: Session): .join(Product.versions) .join(ProductVersion.sale_category) .join(ProductVersion.menu_category) + .join(Voucher.food_table) .where( Voucher.date >= start_date, Voucher.date <= finish_date, @@ -77,16 +81,18 @@ def product_sale_report(s: date, f: date, db: Session): ProductVersion.valid_till >= day, ), ) - .group_by( - SaleCategory.name, - MenuCategory.name, - ProductVersion.id, - ProductVersion.full_name, - Voucher.voucher_type, - Inventory.is_happy_hour, - ) - .order_by(SaleCategory.name, MenuCategory.name, ProductVersion.full_name) - ).all() + ) + if id_: + query = query.where(FoodTable.section_id == id_) + query = query.group_by( + SaleCategory.name, + MenuCategory.name, + ProductVersion.id, + ProductVersion.full_name, + Voucher.voucher_type, + Inventory.is_happy_hour, + ).order_by(SaleCategory.name, MenuCategory.name, ProductVersion.full_name) + list_ = db.execute(query).all() info: list[Any] = [] for id_, name, v_type, hh, quantity in list_: type_ = to_camel(VoucherType(v_type).name) @@ -111,6 +117,7 @@ def product_sale_report(s: date, f: date, db: Session): def print_report( start_date: date = Depends(report_start_date), finish_date: date = Depends(report_finish_date), + section: Annotated[uuid.UUID | None, Query()] = None, device_id: uuid.UUID = Cookie(None), user: UserToken = Security(get_user, scopes=["product-sale-report"]), ) -> bool: @@ -120,6 +127,7 @@ def print_report( "userName": user.name, "startDate": start_date.strftime("%d-%b-%Y"), "finishDate": finish_date.strftime("%d-%b-%Y"), + "sectionId": str(section) if section is not None else None, "amounts": product_sale_report(start_date, finish_date, db), } print_product_sale_report(report, device_id, db) diff --git a/barker/barker/routers/reports/sale_report.py b/barker/barker/routers/reports/sale_report.py index 6e9e791..9ad49d8 100644 --- a/barker/barker/routers/reports/sale_report.py +++ b/barker/barker/routers/reports/sale_report.py @@ -137,6 +137,7 @@ def print_report( report = SaleReport( start_date=start_date, finish_date=finish_date, + section_id=section, amounts=( get_sale(start_date, finish_date, section, db) + [SaleReportItem(name="--", amount=Decimal(0))] diff --git a/bookie/src/app/product-sale-report/product-sale-report.component.html b/bookie/src/app/product-sale-report/product-sale-report.component.html index d5d6458..bbe26fa 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.component.html +++ b/bookie/src/app/product-sale-report/product-sale-report.component.html @@ -14,7 +14,7 @@
- + Start Date - + Finish Date - + + Section + + -- All -- + @for (p of sections; track p.id) { + + {{ p.name }} + + } + + +
diff --git a/bookie/src/app/product-sale-report/product-sale-report.component.ts b/bookie/src/app/product-sale-report/product-sale-report.component.ts index e1b15a6..5fd6b5c 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.component.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.component.ts @@ -1,27 +1,18 @@ import { DecimalPipe } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; -import { MatIconButton, MatButton } from '@angular/material/button'; -import { MatCard, MatCardHeader, MatCardTitleGroup, MatCardTitle, MatCardContent } from '@angular/material/card'; -import { MatDatepickerInput, MatDatepickerToggle, MatDatepicker } from '@angular/material/datepicker'; -import { MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field'; -import { MatIcon } from '@angular/material/icon'; -import { MatInput } from '@angular/material/input'; -import { - MatTable, - MatColumnDef, - MatHeaderCellDef, - MatHeaderCell, - MatCellDef, - MatCell, - MatHeaderRowDef, - MatHeaderRow, - MatRowDef, - MatRow, -} from '@angular/material/table'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; +import { Section } from '../core/section'; import { ToasterService } from '../core/toaster.service'; import { ToCsvService } from '../shared/to-csv.service'; @@ -34,41 +25,26 @@ import { ProductSaleReportService } from './product-sale-report.service'; templateUrl: './product-sale-report.component.html', styleUrls: ['./product-sale-report.component.css'], imports: [ - MatCard, - MatCardHeader, - MatCardTitleGroup, - MatCardTitle, - MatIconButton, - MatIcon, - MatCardContent, + MatCardModule, + MatButtonModule, ReactiveFormsModule, - MatFormField, - MatLabel, - MatInput, - MatDatepickerInput, - MatDatepickerToggle, - MatSuffix, - MatDatepicker, - MatButton, - MatTable, - MatColumnDef, - MatHeaderCellDef, - MatHeaderCell, - MatCellDef, - MatCell, - MatHeaderRowDef, - MatHeaderRow, - MatRowDef, - MatRow, + MatFormFieldModule, + MatInputModule, + MatIconModule, + MatDatepickerModule, + MatTableModule, + MatSelectModule, DecimalPipe, ], }) export class ProductSaleReportComponent implements OnInit { + sections: Section[] = []; info: ProductSaleReport = new ProductSaleReport(); dataSource: ProductSaleReportDataSource = new ProductSaleReportDataSource(this.info.amounts); form: FormGroup<{ startDate: FormControl; finishDate: FormControl; + section: FormControl; }>; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ @@ -85,16 +61,19 @@ export class ProductSaleReportComponent implements OnInit { this.form = new FormGroup({ startDate: new FormControl(new Date(), { nonNullable: true }), finishDate: new FormControl(new Date(), { nonNullable: true }), + section: new FormControl(null), }); } ngOnInit() { this.route.data.subscribe((value) => { - const data = value as { info: ProductSaleReport }; + const data = value as { sections: Section[]; info: ProductSaleReport }; + this.sections = data.sections; this.info = data.info; this.form.setValue({ startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), + section: this.info.sectionId || null, }); this.dataSource = new ProductSaleReportDataSource(this.info.amounts); }); @@ -102,25 +81,33 @@ export class ProductSaleReportComponent implements OnInit { show() { const info = this.getInfo(); + const params = { + startDate: info.startDate, + finishDate: info.finishDate, + } as { startDate: string; finishDate: string; section?: string }; + if (info.sectionId) { + params['section'] = info.sectionId; + } this.router.navigate(['product-sale-report'], { - queryParams: { - startDate: info.startDate, - finishDate: info.finishDate, - }, + queryParams: params, }); } getInfo(): ProductSaleReport { const formModel = this.form.value; - return new ProductSaleReport({ + const data = new ProductSaleReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), }); + if (formModel.section) { + data.sectionId = formModel.section; + } + return data; } print() { - this.ser.print(this.info.startDate, this.info.finishDate).subscribe({ + this.ser.print(this.info.startDate, this.info.finishDate, this.info.sectionId).subscribe({ next: () => { this.toaster.show('', 'Successfully Printed'); }, diff --git a/bookie/src/app/product-sale-report/product-sale-report.resolver.ts b/bookie/src/app/product-sale-report/product-sale-report.resolver.ts index 489417b..eb80f52 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.resolver.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.resolver.ts @@ -7,5 +7,6 @@ import { ProductSaleReportService } from './product-sale-report.service'; export const productSaleReportResolver: ResolveFn = (route) => { const startDate = route.queryParamMap.get('startDate') ?? null; const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(ProductSaleReportService).get(startDate, finishDate); + const section = route.queryParamMap.get('section') ?? null; + return inject(ProductSaleReportService).get(startDate, finishDate, section); }; diff --git a/bookie/src/app/product-sale-report/product-sale-report.routes.ts b/bookie/src/app/product-sale-report/product-sale-report.routes.ts index 8d4e4dd..b193b9d 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.routes.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.routes.ts @@ -1,6 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; +import { sectionListResolver } from '../sections/section-list.resolver'; import { ProductSaleReportComponent } from './product-sale-report.component'; import { productSaleReportResolver } from './product-sale-report.resolver'; @@ -14,6 +15,7 @@ export const routes: Routes = [ permission: 'Product Sale Report', }, resolve: { + sections: sectionListResolver, info: productSaleReportResolver, }, runGuardsAndResolvers: 'always', diff --git a/bookie/src/app/product-sale-report/product-sale-report.service.ts b/bookie/src/app/product-sale-report/product-sale-report.service.ts index 9274f55..af241a8 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.service.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.service.ts @@ -19,7 +19,7 @@ export class ProductSaleReportService { private log: ErrorLoggerService, ) {} - get(startDate: string | null, finishDate: string | null): Observable { + get(startDate: string | null, finishDate: string | null, section: string | null): Observable { const options = { params: new HttpParams() }; if (startDate !== null) { options.params = options.params.set('s', startDate); @@ -27,12 +27,15 @@ export class ProductSaleReportService { if (finishDate !== null) { options.params = options.params.set('f', finishDate); } + if (section !== null) { + options.params = options.params.set('section', section); + } return this.http .get(url, options) .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; } - print(startDate: string | null, finishDate: string | null): Observable { + print(startDate: string | null, finishDate: string | null, section: string | null): Observable { const printUrl = `${url}/print`; const options = { params: new HttpParams() }; if (startDate !== null) { @@ -41,6 +44,9 @@ export class ProductSaleReportService { if (finishDate !== null) { options.params = options.params.set('f', finishDate); } + if (section !== null) { + options.params = options.params.set('section', section); + } return this.http .get(printUrl, options) .pipe(catchError(this.log.handleError(serviceName, 'print'))) as Observable; diff --git a/bookie/src/app/product-sale-report/product-sale-report.ts b/bookie/src/app/product-sale-report/product-sale-report.ts index 8e86bf1..101f4d5 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.ts @@ -3,11 +3,13 @@ import { ProductSaleReportItem } from './product-sale-report-item'; export class ProductSaleReport { startDate: string; finishDate: string; + sectionId: string | null; amounts: ProductSaleReportItem[]; public constructor(init?: Partial) { this.startDate = ''; this.finishDate = ''; + this.sectionId = null; this.amounts = []; Object.assign(this, init); } diff --git a/bookie/src/app/sale-report/sale-report.component.ts b/bookie/src/app/sale-report/sale-report.component.ts index 87dac61..30483ab 100644 --- a/bookie/src/app/sale-report/sale-report.component.ts +++ b/bookie/src/app/sale-report/sale-report.component.ts @@ -1,13 +1,13 @@ import { CurrencyPipe } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; -import { MatIconButton, MatButton } from '@angular/material/button'; +import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatOptionModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; -import { MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field'; -import { MatIcon } from '@angular/material/icon'; -import { MatInput } from '@angular/material/input'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; @@ -27,19 +27,16 @@ import { SaleReportService } from './sale-report.service'; styleUrls: ['./sale-report.component.css'], imports: [ MatCardModule, - MatIconButton, - MatIcon, + MatButtonModule, ReactiveFormsModule, - MatFormField, - MatLabel, - MatInput, + MatFormFieldModule, + MatIconModule, + MatInputModule, MatDatepickerModule, - MatSuffix, - MatButton, MatTableModule, - CurrencyPipe, MatOptionModule, MatSelectModule, + CurrencyPipe, ], }) export class SaleReportComponent implements OnInit {