Fix: import script to fit the new structure of voucher table (is_printed field removed, voucher_type != KOT is now assumed to be printed)
Fix: Take-away bill type is now removed Fix: Table overview now shows the right amounts Voucher Save and Update should now work Discounts now working (permissions are not checked)
This commit is contained in:
@ -1,12 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { Product } from '../core/product';
|
||||
import { ModifiersComponent } from './modifiers/modifiers.component';
|
||||
import { ModifierCategoryService } from '../modifier-categories/modifier-category.service';
|
||||
import { ModifierCategory } from '../core/modifier-category';
|
||||
import { Bill, Inventory, Kot, PrintType } from './bills/bill';
|
||||
import {VoucherService} from './bills/voucher.service';
|
||||
import { VoucherService } from './bills/voucher.service';
|
||||
import { ToasterService } from "../core/toaster.service";
|
||||
import { tap } from "rxjs/operators";
|
||||
|
||||
@Injectable()
|
||||
export class BillService {
|
||||
@ -16,6 +19,7 @@ export class BillService {
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
private toaster: ToasterService,
|
||||
private ser: VoucherService,
|
||||
private modifierCategoryService: ModifierCategoryService
|
||||
) {
|
||||
@ -37,7 +41,8 @@ export class BillService {
|
||||
productId: i.product.id,
|
||||
isHappyHour: i.isHappyHour,
|
||||
isPrinted: true,
|
||||
info: `${i.product.name} (${i.product.units}) @ ${i.price}`,
|
||||
info: `${i.product.name} (${i.product.units}) @ ${i.price} - ${i.discount * 100}%`,
|
||||
price: i.price,
|
||||
quantity: i.quantity,
|
||||
discount: i.discount,
|
||||
taxRate: i.taxRate,
|
||||
@ -61,7 +66,7 @@ export class BillService {
|
||||
product: product,
|
||||
productId: product.id,
|
||||
isHappyHour: product.hasHappyHour,
|
||||
info: `${product.name} (${product.units}) @ ${product.price}`,
|
||||
info: `${product.name} (${product.units}) @ ${product.price} - ${0}%`,
|
||||
price: product.price,
|
||||
quantity: 1,
|
||||
discount: 0,
|
||||
@ -128,8 +133,18 @@ export class BillService {
|
||||
this.showModifier(item);
|
||||
}
|
||||
|
||||
printKot(guest_book_id: string): void {
|
||||
const nk = new Kot({
|
||||
discount(discounts:{id: string, name: string, discount: number}[]): void {
|
||||
this.data.forEach(x=> {
|
||||
if (!x.isKot) {
|
||||
x.discount = discounts.find(d => d.id === x.product.saleCategory.id).discount / 100;
|
||||
x.info = `${x.product.name} (${x.product.units}) @ ${x.price} - ${x.discount * 100}%`;
|
||||
}
|
||||
});
|
||||
this.dataObs.next(this.data);
|
||||
}
|
||||
|
||||
private getKot(): Kot {
|
||||
return new Kot({
|
||||
inventories: this.data.filter(x => !x.isKot && !x.isPrinted).map(y => new Inventory({
|
||||
product: y.product,
|
||||
quantity: y.quantity,
|
||||
@ -141,15 +156,32 @@ export class BillService {
|
||||
tax: y.tax
|
||||
}))
|
||||
});
|
||||
let item = JSON.parse(JSON.stringify(this.bill))
|
||||
item.kots.push(nk);
|
||||
this.ser.saveOrUpdate(item, PrintType.Kot, guest_book_id, true).subscribe(x =>
|
||||
console.log(x)
|
||||
}
|
||||
|
||||
printKot(guest_book_id: string): Observable<Bill> {
|
||||
let item = JSON.parse(JSON.stringify(this.bill));
|
||||
let newKot = this.getKot();
|
||||
if (newKot.inventories.length == 0) {
|
||||
this.toaster.show('Error', 'Cannot print a blank KOT\nPlease add some products!');
|
||||
}
|
||||
item.kots.push(newKot);
|
||||
return this.ser.saveOrUpdate(item, PrintType.Kot, guest_book_id, true).pipe(
|
||||
tap(x => console.log(x))
|
||||
);
|
||||
}
|
||||
|
||||
printBill(): boolean {
|
||||
return false;
|
||||
printBill(guest_book_id: string): Observable<Bill> {
|
||||
let item = JSON.parse(JSON.stringify(this.bill));
|
||||
item.kots.forEach(k => {
|
||||
k.inventories.forEach(i => {
|
||||
i.discount = this.data.find(x => !x.isKot && x.id === i.id).discount;
|
||||
})
|
||||
});
|
||||
console.log(item);
|
||||
item.kots.push(this.getKot());
|
||||
return this.ser.saveOrUpdate(item, PrintType.Bill, guest_book_id, true).pipe(
|
||||
tap(x => console.log(x))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ export class Bill {
|
||||
settlements: any[];
|
||||
void: boolean;
|
||||
voidReason: string;
|
||||
printed: boolean;
|
||||
voucherType: string;
|
||||
serial: number;
|
||||
kots: Kot[];
|
||||
@ -59,7 +58,7 @@ export class Bill {
|
||||
|
||||
export enum PrintType {
|
||||
Kot = 'KOT',
|
||||
Bill = 'BILL',
|
||||
Bill = 'REGULAR_BILL',
|
||||
NoCharge = 'NO_CHARGE',
|
||||
Staff = 'STAFF'
|
||||
}
|
||||
|
||||
16
bookie/src/app/sales/discount/discount-datasource.ts
Normal file
16
bookie/src/app/sales/discount/discount-datasource.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { DataSource } from '@angular/cdk/collections';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
|
||||
export class DiscountDataSource extends DataSource<{name: string, discount: number}> {
|
||||
|
||||
constructor(private data: {name: string, discount: number}[]) {
|
||||
super();
|
||||
}
|
||||
|
||||
connect(): Observable<{name: string, discount: number}[]> {
|
||||
return observableOf(this.data);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
}
|
||||
}
|
||||
4
bookie/src/app/sales/discount/discount.component.css
Normal file
4
bookie/src/app/sales/discount/discount.component.css
Normal file
@ -0,0 +1,4 @@
|
||||
.right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
30
bookie/src/app/sales/discount/discount.component.html
Normal file
30
bookie/src/app/sales/discount/discount.component.html
Normal file
@ -0,0 +1,30 @@
|
||||
<h2 mat-dialog-title>Discount</h2>
|
||||
<mat-dialog-content>
|
||||
<form [formGroup]="form" fxLayout="column">
|
||||
<mat-table #table [dataSource]="dataSource" formArrayName="discounts">
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Discount Column -->
|
||||
<ng-container matColumnDef="discount">
|
||||
<mat-header-cell *matHeaderCellDef class="center" fxFlex>Discount</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row; let i = index" class="center" [formGroupName]="i" fxFlex>
|
||||
<mat-form-field>
|
||||
<input matInput type="number" formControlName="discount" autocomplete="off">
|
||||
</mat-form-field>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button [mat-dialog-close]="false">Cancel</button>
|
||||
<button mat-button (click)="accept()" color="primary">Ok</button>
|
||||
</mat-dialog-actions>
|
||||
25
bookie/src/app/sales/discount/discount.component.spec.ts
Normal file
25
bookie/src/app/sales/discount/discount.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DiscountComponent } from './discount.component';
|
||||
|
||||
describe('DiscountComponent', () => {
|
||||
let component: DiscountComponent;
|
||||
let fixture: ComponentFixture<DiscountComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DiscountComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DiscountComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
52
bookie/src/app/sales/discount/discount.component.ts
Normal file
52
bookie/src/app/sales/discount/discount.component.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FormArray, FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||
import { DiscountDataSource } from "./discount-datasource";
|
||||
|
||||
@Component({
|
||||
selector: 'app-modifiers',
|
||||
templateUrl: './discount.component.html',
|
||||
styleUrls: ['./discount.component.css']
|
||||
})
|
||||
export class DiscountComponent {
|
||||
list: any[];
|
||||
form: FormGroup;
|
||||
dataSource: DiscountDataSource;
|
||||
|
||||
displayedColumns = ['name', 'discount'];
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DiscountComponent>,
|
||||
private fb: FormBuilder,
|
||||
@Inject(MAT_DIALOG_DATA) public data: Observable<any[]>
|
||||
) {
|
||||
this.createForm();
|
||||
this.data.subscribe((list: any[]) => {
|
||||
this.list = list;
|
||||
this.form.setControl('discounts', this.fb.array(
|
||||
this.list.map(
|
||||
x => this.fb.group({
|
||||
name: [x.name],
|
||||
discount: ["", [Validators.min(0), Validators.max(100)]]
|
||||
})
|
||||
)
|
||||
));
|
||||
this.dataSource = new DiscountDataSource(list);
|
||||
});
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.form = this.fb.group({
|
||||
discounts: ''
|
||||
});
|
||||
}
|
||||
|
||||
accept(): void {
|
||||
const array = this.form.get('discounts') as FormArray;
|
||||
this.list.forEach((item, index) => {
|
||||
item.discount = Math.max(Math.min(array.controls[index].value.discount, 100), 0);
|
||||
});
|
||||
this.dialogRef.close(this.list);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,9 @@
|
||||
queryParamsHandling="preserve">
|
||||
<h3 class="item-name">Add Product</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="discount()">
|
||||
<h3 class="item-name">Discount</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="printKot()">
|
||||
<h3 class="item-name">Print KOT</h3>
|
||||
</mat-card>
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { AuthService } from '../../auth/auth.service';
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { MatDialog } from "@angular/material";
|
||||
import { mergeMap, tap } from "rxjs/operators";
|
||||
import { Observable, of as observableOf } from "rxjs";
|
||||
import { BillService } from '../bill.service';
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ToasterService } from "../../core/toaster.service";
|
||||
import { DiscountComponent } from "../discount/discount.component";
|
||||
import { SaleCategoryService } from "../../sale-category/sale-category.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-sales-home',
|
||||
@ -10,19 +14,17 @@ import { ActivatedRoute } from "@angular/router";
|
||||
styleUrls: ['./sales-home.component.css']
|
||||
})
|
||||
export class SalesHomeComponent implements OnInit {
|
||||
public nameObject = new Subject<string>();
|
||||
|
||||
constructor(private route: ActivatedRoute, private auth: AuthService, private bs: BillService) {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private dialog: MatDialog,
|
||||
private toaster: ToasterService,
|
||||
private mcSer: SaleCategoryService,
|
||||
private bs: BillService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.auth.userObservable.subscribe((user) => {
|
||||
if (user.isAuthenticated) {
|
||||
this.nameObject.next(user.name);
|
||||
} else {
|
||||
this.nameObject.next(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
printKot() {
|
||||
@ -30,10 +32,48 @@ export class SalesHomeComponent implements OnInit {
|
||||
if (this.route.snapshot.queryParamMap.has("guest")) {
|
||||
guestBookId = this.route.snapshot.queryParamMap.get("guest");
|
||||
}
|
||||
this.bs.printKot(guestBookId);
|
||||
this.bs.printKot(guestBookId).subscribe(x => {
|
||||
this.toaster.show('Success', '');
|
||||
this.router.navigate(['/sales']);
|
||||
});
|
||||
}
|
||||
|
||||
discount(): void {
|
||||
this.showDiscount().subscribe();
|
||||
}
|
||||
|
||||
showDiscount(): Observable<boolean | { id: string, name: string, discount: number }[]> {
|
||||
const dialogRef = this.dialog.open(DiscountComponent, {
|
||||
// width: '750px',
|
||||
data: this.mcSer.listForDiscount()
|
||||
});
|
||||
return dialogRef.afterClosed().pipe(
|
||||
tap((result: boolean | { id: string, name: string, discount: number }[]) => {
|
||||
if (!!result) {
|
||||
this.bs.discount(result as { id: string, name: string, discount: number }[]);
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
printBill() {
|
||||
this.bs.printBill();
|
||||
const canGiveDiscount = true;
|
||||
let guestBookId = null;
|
||||
if (this.route.snapshot.queryParamMap.has("guest")) {
|
||||
guestBookId = this.route.snapshot.queryParamMap.get("guest");
|
||||
}
|
||||
let discObs = null
|
||||
if (!canGiveDiscount) {
|
||||
discObs = this.showDiscount();
|
||||
} else {
|
||||
discObs = observableOf("");
|
||||
}
|
||||
discObs.pipe(
|
||||
mergeMap(x => this.bs.printBill(guestBookId))
|
||||
).subscribe(x => {
|
||||
this.toaster.show('Success', '');
|
||||
this.router.navigate(['/sales']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
|
||||
import { ModifierCategory } from '../../core/modifier-category';
|
||||
import { Modifier } from '../../core/modifier';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material';
|
||||
import {Observable} from 'rxjs';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-modifiers',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div mat-dialog-content>
|
||||
<mat-dialog-content>
|
||||
<form [formGroup]="form">
|
||||
<div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
|
||||
fxLayoutGap.lt-md="0px">
|
||||
@ -9,9 +9,8 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button [mat-dialog-close]="false">Cancel</button>
|
||||
<button mat-button (click)="accept()" color="primary">Ok</button>
|
||||
</div>
|
||||
|
||||
</mat-dialog-actions>
|
||||
|
||||
@ -25,19 +25,21 @@ import { BillsComponent } from './bills/bills.component';
|
||||
import { SalesHomeComponent } from './home/sales-home.component';
|
||||
import { BillService } from './bill.service';
|
||||
import { QuantityComponent } from './quantity/quantity.component';
|
||||
import { DiscountComponent } from "./discount/discount.component";
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
BillService
|
||||
],
|
||||
declarations: [
|
||||
RunningTablesComponent,
|
||||
MenuCategoriesComponent,
|
||||
ProductsComponent,
|
||||
ModifiersComponent,
|
||||
BillsComponent,
|
||||
SalesHomeComponent,
|
||||
QuantityComponent
|
||||
DiscountComponent,
|
||||
MenuCategoriesComponent,
|
||||
ModifiersComponent,
|
||||
ProductsComponent,
|
||||
QuantityComponent,
|
||||
RunningTablesComponent,
|
||||
SalesHomeComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -59,6 +61,7 @@ import { QuantityComponent } from './quantity/quantity.component';
|
||||
SalesRoutingModule
|
||||
],
|
||||
entryComponents: [
|
||||
DiscountComponent,
|
||||
ModifiersComponent,
|
||||
QuantityComponent
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user