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:
Amritanshu
2019-08-08 13:31:30 +05:30
parent 7d06a2f961
commit c81b92c336
24 changed files with 534 additions and 249 deletions

View File

@ -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))
);
}
}

View File

@ -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'
}

View 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() {
}
}

View File

@ -0,0 +1,4 @@
.right {
display: flex;
justify-content: flex-end;
}

View 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>

View 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();
});
});

View 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);
}
}

View File

@ -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>

View File

@ -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']);
});
}
}

View File

@ -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',

View File

@ -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>

View File

@ -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
]