diff --git a/DB/migrate.cmd b/DB/migrate.cmd index 4ddcf3f..a1edede 100644 --- a/DB/migrate.cmd +++ b/DB/migrate.cmd @@ -16,7 +16,7 @@ call:copyQuery m-Sections "SELECT 'INSERT INTO sections(id, name) VALUES (''' + call:copyQuery n-Printers "SELECT 'INSERT INTO printers(id, name, address, cut_code) VALUES (''' + CAST(NewID() AS Nvarchar(36)) + ''', ''' + Printer + ''', ''' + Printer + ''', ''' + CutCode + ''');' FROM Test.dbo.PrintLocations GROUP BY Printer, CutCode;" call:copyQuery o-SectionPrinters "SELECT 'INSERT INTO section_printers(id, menu_category_id, section_id, printer_id, copies) VALUES (''' + CAST(PrintLocationID AS Nvarchar(36)) + ''', ' + COALESCE('''' + CAST(ProductGroupID AS Nvarchar(36)) + '''','null') + ', ' + '(select id from sections where name = ''' + Location + ''')' + ', ' + '(select id from printers where name = ''' + Printer + ''')' + ', ' + CAST(Copies AS nvarchar(36)) + ');' FROM Test.dbo.PrintLocations;" -call:copyQuery p-Vouchers "SELECT 'INSERT INTO vouchers(id, date, pax, user_id, creation_date, last_edit_date, bill_id, food_table_id, customer_id, narration, void_reason, voucher_type, kot_id) VALUES (''' + CAST(VoucherID AS Nvarchar(36)) + ''', ' + '''' + CONVERT(Nvarchar(36), Date, 126) + ''', ' + COALESCE(CAST(Pax AS Nvarchar(36)), 'null') + ', ''' + CAST(UserID AS Nvarchar(36)) + ''', ' + '''' + CONVERT(Nvarchar(36), CreationDate, 126) + ''', ' + '''' + CONVERT(Nvarchar(36), LastEditDate, 126) + ''', ' + COALESCE(CAST(BillID AS Nvarchar(36)), 'null') + ', ' + '''' + CAST(TableID AS Nvarchar(36)) + ''', ' + '''' + CAST(CustomerID AS Nvarchar(36)) + ''', ' + COALESCE('''' + REPLACE(Narration, '''', '''''') + '''', 'null') + ', ' + COALESCE('''' + REPLACE(VoidReason, '''', '''''') + '''', 'null') + ', ' + CASE WHEN Printed = 0 THEN '0' WHEN Void = 1 THEN '5' ELSE CAST(VoucherType AS Nvarchar(36)) END + ', ' + CAST(KotID AS Nvarchar(36)) + ');' FROM Test.dbo.Vouchers;" +call:copyQuery p-Vouchers "SELECT 'INSERT INTO vouchers(id, date, pax, user_id, creation_date, last_edit_date, bill_id, food_table_id, customer_id, narration, reason, voucher_type, kot_id) VALUES (''' + CAST(VoucherID AS Nvarchar(36)) + ''', ' + '''' + CONVERT(Nvarchar(36), Date, 126) + ''', ' + COALESCE(CAST(Pax AS Nvarchar(36)), 'null') + ', ''' + CAST(UserID AS Nvarchar(36)) + ''', ' + '''' + CONVERT(Nvarchar(36), CreationDate, 126) + ''', ' + '''' + CONVERT(Nvarchar(36), LastEditDate, 126) + ''', ' + COALESCE(CAST(BillID AS Nvarchar(36)), 'null') + ', ' + '''' + CAST(TableID AS Nvarchar(36)) + ''', ' + '''' + CAST(CustomerID AS Nvarchar(36)) + ''', ' + COALESCE('''' + REPLACE(Narration, '''', '''''') + '''', 'null') + ', ' + COALESCE('''' + REPLACE(VoidReason, '''', '''''') + '''', 'null') + ', ' + CASE WHEN Printed = 0 THEN '0' WHEN Void = 1 THEN '5' ELSE CAST(VoucherType AS Nvarchar(36)) END + ', ' + CAST(KotID AS Nvarchar(36)) + ');' FROM Test.dbo.Vouchers;" call:copyQuery q-Kots "SELECT 'INSERT INTO kots(id, voucher_id, code, food_table_id, date, user_id) VALUES (''' + CAST(KotID AS Nvarchar(36)) + ''', ' + '''' + CAST(VoucherID AS Nvarchar(36)) + '''' + ', ' + CAST(Code AS Nvarchar(36)) + ', ' + '''' + CAST(TableID AS Nvarchar(36)) + '''' + ', ' + '''' + CONVERT(Nvarchar(36), Date, 126) + ''', ''' + CAST(UserID AS Nvarchar(36)) + ''');' FROM Test.dbo.Kots;" call:copyQuery r-Inventories "SELECT 'INSERT INTO inventories(id, kot_id, product_id, sort_order, quantity, price, is_happy_hour, tax_rate, tax_id, discount) VALUES (''' + CAST(InventoryID AS Nvarchar(36)) + ''', ' + '''' + CAST(KotID AS Nvarchar(36)) + '''' + ', ' + '''' + CAST(ProductID AS Nvarchar(36)) + '''' + ', ' + CAST(SortOrder AS Nvarchar(36)) + ', ' + CAST(Quantity AS Nvarchar(36)) + ', ' + CAST(Price AS Nvarchar(36)) + ', ' + CASE WHEN IsHappyHour = 1 THEN 'true' ELSE 'false' END + ', ' + CAST(VatRate AS Nvarchar(36)) + ', ' + '''' + CAST(VatID AS Nvarchar(36)) + '''' + ', ' + CAST(Discount AS Nvarchar(36)) + ');' FROM Test.dbo.Inventories;" call:copyQuery s-InventoryModifiers "SELECT 'INSERT INTO inventory_modifiers(id, inventory_id, modifier_id, price) VALUES (''' + CAST(InventoryModifierID AS Nvarchar(36)) + ''', ' + '''' + CAST(InventoryID AS Nvarchar(36)) + '''' + ', ' + '''' + CAST(ModifierID AS Nvarchar(36)) + '''' + ', 0);' FROM Test.dbo.InventoryModifiers;" diff --git a/barker/models/voucher.py b/barker/models/voucher.py index 26a6591..704249b 100644 --- a/barker/models/voucher.py +++ b/barker/models/voucher.py @@ -114,7 +114,7 @@ class Voucher(Base): ) customer_id = Column("customer_id", GUID(), ForeignKey("customers.id")) narration = Column("narration", Unicode(1000), nullable=False) - void_reason = Column("void_reason", Unicode(255)) + reason = Column("reason", Unicode(255)) _voucher_type = Column("voucher_type", Integer, nullable=False) user_id = Column("user_id", GUID(), ForeignKey("users.id"), nullable=False) @@ -170,7 +170,6 @@ class Voucher(Base): self.food_table_id = food_table_id self.customer_id = customer_id self.narration = "" - self.void_reason = None self.voucher_type = voucher_type self.user_id = user_id diff --git a/barker/views/voucher/__init__.py b/barker/views/voucher/__init__.py index b2bba0b..34680e8 100644 --- a/barker/views/voucher/__init__.py +++ b/barker/views/voucher/__init__.py @@ -60,7 +60,7 @@ def check_permissions(item, voucher_type, permissions): if item.voucher_type == VoucherType.VOID: raise ValidationFailure( - "This Bill is already void.\nReason: {0}".format(item.void_reason) + "This Bill is already void.\nReason: {0}".format(item.reason) ) diff --git a/barker/views/voucher/receive_payment.py b/barker/views/voucher/receive_payment.py index 810c0ce..f13ef57 100644 --- a/barker/views/voucher/receive_payment.py +++ b/barker/views/voucher/receive_payment.py @@ -4,7 +4,7 @@ from decimal import Decimal import transaction from pyramid.view import view_config -from barker.models import SettleOption, Voucher, Settlement, Overview +from barker.models import SettleOption, Voucher, Settlement, Overview, VoucherType from barker.models.validation_exception import ValidationError @@ -19,20 +19,30 @@ from barker.models.validation_exception import ValidationError def receive_payment(request): update_table = request.GET["u"] json = request.json_body - for item in json: + amounts = [ + j + for j in json["amounts"] + if j["amount"] != 0 + and j["id"] not in [SettleOption.AMOUNT(), SettleOption.ROUND_OFF()] + ] + for item in amounts: item["amount"] = round(Decimal(item["amount"]), 0) id_ = uuid.UUID(request.matchdict["id"]) item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() + if item.voucher_type in [VoucherType.NO_CHARGE, VoucherType.STAFF]: + item.reason = json["name"].strip().title() + total_amount = item.amount - json.append({"id": SettleOption.AMOUNT(), "amount": -total_amount}) + amounts.append({"id": SettleOption.AMOUNT(), "amount": -total_amount}) round_off = round(total_amount) - total_amount if round_off != 0: - json.append({"id": SettleOption.ROUND_OFF(), "amount": -round_off}) - if sum([i["amount"] for i in json]) != 0: + amounts.append({"id": SettleOption.ROUND_OFF(), "amount": -round_off}) + + if sum([i["amount"] for i in amounts]) != 0: raise ValidationError("Payment received is not equal to bill amount") - for i in (j for j in json if j["amount"] != 0): + for i in amounts: amount = i["amount"] settlement_type_id = i["id"] old = [s for s in item.settlements if s.settled == settlement_type_id] @@ -43,7 +53,7 @@ def receive_payment(request): item.settlements.append(s) request.dbsession.add(s) - allowed = [a["id"] for a in json if a["amount"] != 0] + allowed = [a["id"] for a in amounts] for i in (s for s in item.settlements if s.settled not in allowed): item.settlements.remove(i) request.dbsession.delete(i) @@ -54,5 +64,3 @@ def receive_payment(request): ).delete() transaction.commit() return True - - diff --git a/barker/views/voucher/show.py b/barker/views/voucher/show.py index f62bb3e..5c33da2 100644 --- a/barker/views/voucher/show.py +++ b/barker/views/voucher/show.py @@ -98,7 +98,7 @@ def voucher_info(item): "customer": {"id": item.customer_id, "name": item.customer.name} if item.customer is not None else {}, "settlements": [], "narration": item.narration, - "voidReason": item.void_reason, + "reason": item.reason, "voucherType": item.voucher_type.name, "kotId": item.kot_id, "kots": [ diff --git a/barker/views/voucher/split.py b/barker/views/voucher/split.py index 3e329ad..fc1ca70 100644 --- a/barker/views/voucher/split.py +++ b/barker/views/voucher/split.py @@ -27,7 +27,7 @@ def split_voucher(request): update_table = request.GET["u"] == "true" item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() item.void = True - item.void_reason = "Bill Split" + item.reason = "Bill Split" do_void_settlements(item, request.dbsession) if update_table: request.dbsession.query(Overview).filter( diff --git a/barker/views/voucher/void.py b/barker/views/voucher/void.py index ba75846..1716c98 100644 --- a/barker/views/voucher/void.py +++ b/barker/views/voucher/void.py @@ -22,7 +22,7 @@ def void_voucher(request): item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() item.void = True - item.void_reason = reason + item.reason = reason item.voucher_type = VoucherType.VOID do_void_settlements(item, request.dbsession) diff --git a/bookie/src/app/sales/bill.service.ts b/bookie/src/app/sales/bill.service.ts index 3f6f2e1..1284cf1 100644 --- a/bookie/src/app/sales/bill.service.ts +++ b/bookie/src/app/sales/bill.service.ts @@ -206,8 +206,8 @@ export class BillService { return this.bill.voucherType; } - receivePayment(amounts: { id: string; name: string; amount: number }[]): Observable { - return this.ser.receivePayment(this.bill.id, amounts, true); + receivePayment(amounts: { id: number; name: string; amount: number }[], name: string): Observable { + return this.ser.receivePayment(this.bill.id, amounts, name, true); } moveTable(table: Table): Observable { diff --git a/bookie/src/app/sales/bills/voucher.service.ts b/bookie/src/app/sales/bills/voucher.service.ts index 3e323b5..715d247 100644 --- a/bookie/src/app/sales/bills/voucher.service.ts +++ b/bookie/src/app/sales/bills/voucher.service.ts @@ -79,10 +79,10 @@ export class VoucherService { } } - receivePayment(id: string, amounts: { id: string; name: string; amount: number }[], updateTable: boolean): Observable { + receivePayment(id: string, amounts: { id: number; name: string; amount: number }[], name: string, updateTable: boolean): Observable { const options = {params: new HttpParams().set('receive-payment', '').set('u', updateTable.toString())}; return >this.http.post( - `${url}/${id}`, amounts, options + `${url}/${id}`, {name: name, amounts: amounts}, options ).pipe( catchError(this.log.handleError(serviceName, 'receivePayment')) ); diff --git a/bookie/src/app/sales/home/sales-home.component.ts b/bookie/src/app/sales/home/sales-home.component.ts index 21f9711..9421b3e 100644 --- a/bookie/src/app/sales/home/sales-home.component.ts +++ b/bookie/src/app/sales/home/sales-home.component.ts @@ -15,7 +15,7 @@ import { TableService } from '../../tables/table.service'; import { Table } from '../../core/table'; import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; -import { VoidReasonComponent } from '../void-reason/void-reason.component'; +import { ReasonComponent } from '../reason/reason.component'; @Component({ selector: 'app-sales-home', @@ -184,28 +184,71 @@ export class SalesHomeComponent implements OnInit { return true; } + receivePaymentWithReason(type:string, amount: number): Observable { + const types = { + NO_CHARGE: [ + { + id: 4, + name: 'No Charge', + amount: amount + } + ], + STAFF: [ + { + id: 10, + name: 'Staff Account', + amount: amount + } + ] + }; + return this.dialog.open(ReasonComponent, { + // width: '750px' + data: {title: (type === "NO_CHARGE") ? "NC for whom" : "Staff name"} + }).afterClosed().pipe( + switchMap((value: boolean | string) => { + if (!!value) { + return this.bs.receivePayment(types[type], value as string) + } else { + return throwError("Cancelled"); + } + }) + ); + } + + receiveRegularPayment (type: string, amount: number): Observable { + return this.dialog.open(ReceivePaymentComponent, { + // width: '750px', + data: { + type: type, + amount: amount + } + }).afterClosed().pipe( + switchMap((value: boolean | {id: number, name: string, amount: number}[]) => { + if (!!value) { + return this.bs.receivePayment(value as { id: number, name: string, amount: number }[], '') + } else { + return throwError("Cancelled"); + } + }) + ); + } receivePayment() { if (!this.receivePaymentAllowed()) { return; } const amount = this.bs.amountVal(); const type = this.bs.type(); - const dialogRef = this.dialog.open(ReceivePaymentComponent, { - // width: '750px', - data: { - type: type, - amount: amount - } - }); - dialogRef.afterClosed().subscribe((result: boolean | { id: string, name: string, amount: number }[]) => { - if (!!result) { - this.bs.receivePayment(result as { id: string, name: string, amount: number }[]).subscribe(() => { + let obs: any; + if (type === 'NO_CHARGE' || type === 'STAFF') { + obs = this.receivePaymentWithReason(type, amount); + } else { + obs = this.receiveRegularPayment(type, amount); + } + obs.subscribe(() => { this.toaster.show('Success', ''); this.router.navigate(['/sales']); }); } - }); - } moveTableAllowed(): boolean { if (!this.auth.hasPermission('Move Table') && !this.auth.hasPermission('Merge Tables')) { @@ -269,8 +312,20 @@ export class SalesHomeComponent implements OnInit { if (!this.voidBillAllowed()) { return; } - this.dialog.open(VoidReasonComponent, { + this.dialog.open(ReasonComponent, { // width: '750px' + data: { + title: 'Void Reason', + reasons: [ + 'Discount', + 'Printing fault', + 'Item changed', + 'Quantity reduced', + 'Costing bill for party', + 'Cashier mistake', + 'Management free sale', + ] + } }).afterClosed().pipe( switchMap((x: boolean | string) => { if (!!x) { diff --git a/bookie/src/app/sales/void-reason/void-reason-datasource.ts b/bookie/src/app/sales/reason/reason-datasource.ts similarity index 81% rename from bookie/src/app/sales/void-reason/void-reason-datasource.ts rename to bookie/src/app/sales/reason/reason-datasource.ts index 78c61fd..b3b9a92 100644 --- a/bookie/src/app/sales/void-reason/void-reason-datasource.ts +++ b/bookie/src/app/sales/reason/reason-datasource.ts @@ -1,7 +1,7 @@ import { DataSource } from '@angular/cdk/collections'; import { Observable, of as observableOf } from 'rxjs'; -export class VoidReasonDatasource extends DataSource { +export class ReasonDatasource extends DataSource { constructor(private data: string[]) { super(); diff --git a/bookie/src/app/sales/void-reason/void-reason.component.css b/bookie/src/app/sales/reason/reason.component.css similarity index 100% rename from bookie/src/app/sales/void-reason/void-reason.component.css rename to bookie/src/app/sales/reason/reason.component.css diff --git a/bookie/src/app/sales/reason/reason.component.html b/bookie/src/app/sales/reason/reason.component.html new file mode 100644 index 0000000..95913f3 --- /dev/null +++ b/bookie/src/app/sales/reason/reason.component.html @@ -0,0 +1,25 @@ +

{{ title }}

+ +
+ + + + {{row}} + + + Reason + + + + + + + + +
+
+ + + + diff --git a/bookie/src/app/sales/void-reason/void-reason.component.spec.ts b/bookie/src/app/sales/reason/reason.component.spec.ts similarity index 60% rename from bookie/src/app/sales/void-reason/void-reason.component.spec.ts rename to bookie/src/app/sales/reason/reason.component.spec.ts index 009c74e..ddc3d6f 100644 --- a/bookie/src/app/sales/void-reason/void-reason.component.spec.ts +++ b/bookie/src/app/sales/reason/reason.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { VoidReasonComponent } from './void-reason.component'; +import { ReasonComponent } from './reason.component'; describe('VoidReasonComponent', () => { - let component: VoidReasonComponent; - let fixture: ComponentFixture; + let component: ReasonComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ VoidReasonComponent ] + declarations: [ ReasonComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(VoidReasonComponent); + fixture = TestBed.createComponent(ReasonComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/bookie/src/app/sales/reason/reason.component.ts b/bookie/src/app/sales/reason/reason.component.ts new file mode 100644 index 0000000..b48a7c6 --- /dev/null +++ b/bookie/src/app/sales/reason/reason.component.ts @@ -0,0 +1,41 @@ +import { Component, ElementRef, Inject, ViewChild } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; +import { ReasonDatasource } from './reason-datasource'; +import { FormBuilder, FormGroup } from "@angular/forms"; + +@Component({ + selector: 'app-reason', + templateUrl: './reason.component.html', + styleUrls: ['./reason.component.css'] +}) +export class ReasonComponent { + @ViewChild('son', { static: true }) son: ElementRef; + form: FormGroup; + dataSource: ReasonDatasource; + title: string; + selected: string; + reasons: string[]; + displayedColumns = ['reason']; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) private data:{ title: string, reasons: string[]}, + private fb: FormBuilder + ) { + this.reasons = data.reasons || []; + this.title = data.title; + this.form = this.fb.group({ + son: '' + }); + this.dataSource = new ReasonDatasource(this.reasons); + } + + select(reason: string) { + this.selected = reason.trim(); + return true; + } + + accept(): void { + this.dialogRef.close(this.selected); + } +} diff --git a/bookie/src/app/sales/sales.module.ts b/bookie/src/app/sales/sales.module.ts index 8b2a329..fc26c90 100644 --- a/bookie/src/app/sales/sales.module.ts +++ b/bookie/src/app/sales/sales.module.ts @@ -30,7 +30,7 @@ import { DiscountComponent } from './discount/discount.component'; import { BillTypeComponent } from './bill-type/bill-type.component'; import { ReceivePaymentComponent } from './receive-payment/receive-payment.component'; import { TablesDialogComponent } from './tables-dialog/tables-dialog.component'; -import { VoidReasonComponent } from './void-reason/void-reason.component'; +import { ReasonComponent } from './reason/reason.component'; @NgModule({ providers: [ @@ -48,7 +48,7 @@ import { VoidReasonComponent } from './void-reason/void-reason.component'; RunningTablesComponent, SalesHomeComponent, TablesDialogComponent, - VoidReasonComponent + ReasonComponent ], imports: [ CommonModule, @@ -78,7 +78,7 @@ import { VoidReasonComponent } from './void-reason/void-reason.component'; QuantityComponent, ReceivePaymentComponent, TablesDialogComponent, - VoidReasonComponent + ReasonComponent ] }) export class SalesModule { } diff --git a/bookie/src/app/sales/void-reason/void-reason.component.html b/bookie/src/app/sales/void-reason/void-reason.component.html deleted file mode 100644 index 98d1d4e..0000000 --- a/bookie/src/app/sales/void-reason/void-reason.component.html +++ /dev/null @@ -1,16 +0,0 @@ -

Reason

- - - - - - {{row}} - - - - - - - - - diff --git a/bookie/src/app/sales/void-reason/void-reason.component.ts b/bookie/src/app/sales/void-reason/void-reason.component.ts deleted file mode 100644 index 095d3a2..0000000 --- a/bookie/src/app/sales/void-reason/void-reason.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material'; -import { VoidReasonDatasource } from './void-reason-datasource'; - -@Component({ - selector: 'app-void-reason', - templateUrl: './void-reason.component.html', - styleUrls: ['./void-reason.component.css'] -}) -export class VoidReasonComponent { - dataSource: VoidReasonDatasource; - selected: string; - reasons = [ - 'Discount', - 'Printing fault', - 'Item changed', - 'Quantity reduced', - 'Costing bill for party', - 'Cashier mistake', - 'Management free sale', - 'Other' - ]; - displayedColumns = ['reason']; - - constructor( - public dialogRef: MatDialogRef - ) { - this.dataSource = new VoidReasonDatasource(this.reasons); - } - - select(reason: string) { - this.selected = reason; - } - - accept(): void { - this.dialogRef.close(this.selected); - } -}