diff --git a/barker/barker/printing/product_sale_report.py b/barker/barker/printing/product_sale_report.py new file mode 100644 index 0000000..a893d3c --- /dev/null +++ b/barker/barker/printing/product_sale_report.py @@ -0,0 +1,53 @@ +import asyncio +import locale +import uuid + +from datetime import datetime, timedelta + +from arq import ArqRedis, create_pool +from sqlalchemy import select +from sqlalchemy.orm import Session + +from ..core.arq import settings as redis_settings +from ..core.config import settings +from ..models.device import Device +from ..models.printer import Printer +from ..models.section_printer import SectionPrinter + + +def print_product_sale_report(report, device_id: uuid.UUID, db: Session): + locale.setlocale(locale.LC_MONETARY, "en_IN") + data = design_product_sale_report(report) + section_id = db.execute(select(Device.section_id).where(Device.id == device_id)).scalar_one() + printer = db.execute( + select(Printer) + .join(SectionPrinter.printer) + .where(SectionPrinter.section_id == section_id) + .where(SectionPrinter.menu_category_id == None) # noqa: E711 + ).scalar_one() + + redis: ArqRedis = asyncio.run(create_pool(redis_settings)) + asyncio.run( + redis.enqueue_job( + "sent_to_printer", data, printer.address, printer.cut_code, _queue_name=f"barker:print:{printer.name}" + ) + ) + + +def design_product_sale_report(report): + now = datetime.now() + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES) + s = f"{report['userName']} @ {now:%d-%b-%Y %H:%M}".center(42) + s += "\n\r" + "-" * 42 + s += "\n\r" f"{report['startDate']} To {report['finishDate']}".center(42) + s += "\n\r" + "-" * 42 + s += "\n\rUnbilled Sale NC Staff Void" + for item in report["amounts"]: + s += f"\n\r{item['name']: ^42.42}" f"\n\r" + (f"{item['kot']: >7.2f} " if "kot" in item else " ") + ( + f"{item['regularBill']: >7.2f} " if "regularBill" in item else " " + ) + (f"{item['noCharge']: >7.2f} " if "noCharge" in item else " ") + ( + f"{item['staff']: >7.2f} " if "staff" in item else " " + ) + ( + f"{item['void']: >7.2f}" if "void" in item else " " + ) + s += "\n\r" + "=" * 42 + return s diff --git a/barker/barker/printing/sale_report.py b/barker/barker/printing/sale_report.py index dc21312..ba4c5af 100644 --- a/barker/barker/printing/sale_report.py +++ b/barker/barker/printing/sale_report.py @@ -43,6 +43,6 @@ def design_sale_report(report: SaleReport): s += "\n\r" f"{report.start_date:%d-%b-%Y} To {report.finish_date:%d-%b-%Y}".center(42) s += "\n\r" + "-" * 42 for item in report.amounts: - s += f"\n\r{item.name: <29.22} {currency_format(item.amount): >12}" + s += f"\n\r{item.name: <29.29} {currency_format(item.amount): >12}" s += "\n\r" + "=" * 42 return s diff --git a/barker/barker/routers/reports/product_sale_report.py b/barker/barker/routers/reports/product_sale_report.py index c763fa4..facc981 100644 --- a/barker/barker/routers/reports/product_sale_report.py +++ b/barker/barker/routers/reports/product_sale_report.py @@ -1,6 +1,8 @@ +import uuid + from datetime import date, datetime, time, timedelta -from fastapi import APIRouter, Depends, Security +from fastapi import APIRouter, Cookie, Depends, Security from sqlalchemy import func, or_, select from sqlalchemy.orm import Session @@ -14,6 +16,7 @@ from ...models.product_version import ProductVersion from ...models.sale_category import SaleCategory from ...models.voucher import Voucher from ...models.voucher_type import VoucherType +from ...printing.product_sale_report import print_product_sale_report from ...schemas import to_camel from ...schemas.user_token import UserToken from . import check_audit_permission, report_finish_date, report_start_date @@ -97,3 +100,22 @@ def product_sale_report(s: date, f: date, db: Session): } ) return info + + +@router.get("/print", response_model=bool) +def print_report( + start_date: date = Depends(report_start_date), + finish_date: date = Depends(report_finish_date), + device_id: uuid.UUID = Cookie(None), + user: UserToken = Security(get_user, scopes=["product-sale-report"]), +) -> bool: + check_audit_permission(start_date, user.permissions) + with SessionFuture() as db: + report = { + "userName": user.name, + "startDate": start_date.strftime("%d-%b-%Y"), + "finishDate": finish_date.strftime("%d-%b-%Y"), + "amounts": product_sale_report(start_date, finish_date, db), + } + print_product_sale_report(report, device_id, db) + return True diff --git a/bookie/src/app/product-sale-report/product-sale-report.component.css b/bookie/src/app/product-sale-report/product-sale-report.component.css index a9626b3..747e946 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.component.css +++ b/bookie/src/app/product-sale-report/product-sale-report.component.css @@ -2,3 +2,7 @@ display: flex; justify-content: flex-end; } + +.spacer { + flex: 1 1 auto; +} 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 b1dcd8a..b14932b 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 @@ -1,9 +1,13 @@ Product Sale Report + +
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 ca644ad..4c94c6a 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 @@ -3,10 +3,12 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; +import { ToasterService } from '../core/toaster.service'; import { ToCsvService } from '../shared/to-csv.service'; import { ProductSaleReport } from './product-sale-report'; import { ProductSaleReportDataSource } from './product-sale-report-datasource'; +import { ProductSaleReportService } from './product-sale-report.service'; @Component({ selector: 'app-product-sale-report', @@ -26,6 +28,8 @@ export class ProductSaleReportComponent implements OnInit { private router: Router, private fb: FormBuilder, private toCsv: ToCsvService, + private toaster: ToasterService, + private ser: ProductSaleReportService, ) { // Create form this.form = this.fb.group({ @@ -65,6 +69,17 @@ export class ProductSaleReportComponent implements OnInit { }); } + print() { + this.ser.print(this.info.startDate, this.info.finishDate).subscribe( + () => { + this.toaster.show('', 'Successfully Printed'); + }, + (error) => { + this.toaster.show('Error', error); + }, + ); + } + exportCsv() { const headers = { Name: 'name', 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 9351377..9c1a1ea 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 @@ -28,4 +28,18 @@ export class ProductSaleReportService { .get(url, options) .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; } + + print(startDate: string | null, finishDate: string | null): Observable { + const printUrl = `${url}/print`; + const options = { params: new HttpParams() }; + if (startDate !== null) { + options.params = options.params.set('s', startDate); + } + if (finishDate !== null) { + options.params = options.params.set('f', finishDate); + } + return this.http + .get(printUrl, options) + .pipe(catchError(this.log.handleError(serviceName, 'print'))) as Observable; + } }