Breaking: Discount is applicable on sale category and not on menu category

Fix the import, etc on this.
While entering discount in sale, it checks the max allowed.
This commit is contained in:
2020-12-16 11:49:22 +05:30
parent e229ecefa2
commit e4500f0d46
48 changed files with 353 additions and 277 deletions

View File

@ -4,7 +4,6 @@ import { Product } from './product';
export class MenuCategory {
id: string | undefined;
name: string;
discountLimit: number;
isActive: boolean;
isFixture: boolean;
sortOrder: number;
@ -14,7 +13,6 @@ export class MenuCategory {
public constructor(init?: Partial<MenuCategory>) {
this.id = undefined;
this.name = '';
this.discountLimit = 0;
this.isActive = true;
this.isFixture = false;
this.sortOrder = 0;

View File

@ -8,8 +8,8 @@ export class Product {
code: number;
name: string;
units: string;
menuCategory: MenuCategory;
saleCategory: SaleCategory;
menuCategory?: MenuCategory;
saleCategory?: SaleCategory;
price: number;
hasHappyHour: boolean;
isNotAvailable: boolean;
@ -25,8 +25,6 @@ export class Product {
this.code = 0;
this.name = '';
this.units = '';
this.menuCategory = new MenuCategory();
this.saleCategory = new SaleCategory();
this.price = 0;
this.hasHappyHour = false;
this.isNotAvailable = false;

View File

@ -3,12 +3,13 @@ import { Tax } from './tax';
export class SaleCategory {
id: string | undefined;
name: string;
tax: Tax;
discountLimit: number;
tax?: Tax;
public constructor(init?: Partial<SaleCategory>) {
this.id = undefined;
this.name = '';
this.tax = new Tax();
this.discountLimit = 1;
Object.assign(this, init);
}
}

View File

@ -17,25 +17,6 @@
<input matInput #nameElement placeholder="Name" formControlName="name" />
</mat-form-field>
</div>
<div
fxLayout="row"
fxLayoutAlign="space-around start"
fxLayout.lt-md="column"
fxLayoutGap="20px"
fxLayoutGap.lt-md="0px"
>
<mat-form-field fxFlex>
<mat-label>Discount Limit</mat-label>
<input
matInput
type="number"
placeholder="Discount Limit"
formControlName="discountLimit"
class="right-align"
/>
<span matSuffix>%</span>
</mat-form-field>
</div>
<div
fxLayout="row"
fxLayoutAlign="space-around start"

View File

@ -29,7 +29,6 @@ export class MenuCategoryDetailComponent implements OnInit, AfterViewInit {
// Create form
this.form = this.fb.group({
name: '',
discountLimit: '',
isActive: '',
});
}
@ -45,7 +44,6 @@ export class MenuCategoryDetailComponent implements OnInit, AfterViewInit {
this.item = item;
this.form.setValue({
name: this.item.name,
discountLimit: this.item.discountLimit,
isActive: this.item.isActive,
});
}
@ -98,7 +96,6 @@ export class MenuCategoryDetailComponent implements OnInit, AfterViewInit {
getItem(): MenuCategory {
const formModel = this.form.value;
this.item.name = formModel.name;
this.item.discountLimit = +formModel.discountLimit;
this.item.isActive = formModel.isActive;
return this.item;
}

View File

@ -24,12 +24,6 @@
>
</ng-container>
<!-- Discount Limit Column -->
<ng-container matColumnDef="discountLimit">
<mat-header-cell *matHeaderCellDef>Discount Limit</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.discountLimit | percent: '1.2-2' }}</mat-cell>
</ng-container>
<!-- Is Active Column -->
<ng-container matColumnDef="isActive">
<mat-header-cell *matHeaderCellDef>Active?</mat-header-cell>

View File

@ -21,7 +21,7 @@ export class MenuCategoryListComponent implements OnInit {
data: BehaviorSubject<MenuCategory[]> = new BehaviorSubject<MenuCategory[]>(this.list);
dataSource: MenuCategoryListDatasource = new MenuCategoryListDatasource(this.data);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'discountLimit', 'isActive', 'isFixture'];
displayedColumns = ['name', 'isActive', 'isFixture'];
constructor(
private route: ActivatedRoute,
@ -37,9 +37,6 @@ export class MenuCategoryListComponent implements OnInit {
ngOnInit() {
this.route.data.subscribe((value) => {
const data = value as { list: MenuCategory[] };
data.list.forEach((x) => {
x.discountLimit /= 100;
});
this.data.next(data.list);
});
this.dataSource = new MenuCategoryListDatasource(this.data);

View File

@ -1,8 +1,9 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { catchError } from 'rxjs/operators';
import { BeerSaleReport } from '../beer-sale-report/beer-sale-report';
import { ErrorLoggerService } from '../core/error-logger.service';
import { MenuCategory } from '../core/menu-category';
@ -27,9 +28,13 @@ export class MenuCategoryService {
) as Observable<MenuCategory>;
}
list(): Observable<MenuCategory[]> {
list(shoudHaveActiveProducts: boolean | undefined = false): Observable<MenuCategory[]> {
const options = { params: new HttpParams() };
if (shoudHaveActiveProducts !== undefined) {
options.params = options.params.set('p', 'true');
}
return this.http
.get<MenuCategory[]>(`${url}/list`)
.get<MenuCategory[]>(`${url}/list`, options)
.pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable<MenuCategory[]>;
}

View File

@ -63,8 +63,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
code: this.item.code || '(Auto)',
name: this.item.name || '',
units: this.item.units || '',
menuCategory: this.item.menuCategory.id ? this.item.menuCategory.id : '',
saleCategory: this.item.saleCategory.id ? this.item.saleCategory.id : '',
menuCategory: this.item.menuCategory ? this.item.menuCategory.id : '',
saleCategory: this.item.saleCategory ? this.item.saleCategory.id : '',
price: this.item.price || '',
hasHappyHour: this.item.hasHappyHour,
isNotAvailable: this.item.isNotAvailable,
@ -121,7 +121,13 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
const formModel = this.form.value;
this.item.name = formModel.name;
this.item.units = formModel.units;
if (this.item.menuCategory === null || this.item.menuCategory === undefined) {
this.item.menuCategory = new MenuCategory();
}
this.item.menuCategory.id = formModel.menuCategory;
if (this.item.saleCategory === null || this.item.saleCategory === undefined) {
this.item.saleCategory = new SaleCategory();
}
this.item.saleCategory.id = formModel.saleCategory;
this.item.price = +formModel.price;
this.item.hasHappyHour = formModel.hasHappyHour;

View File

@ -2,6 +2,7 @@ import { DataSource } from '@angular/cdk/collections';
import { merge, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { MenuCategory } from '../../core/menu-category';
import { Product } from '../../core/product';
export class ProductListDataSource extends DataSource<Product> {
@ -44,9 +45,9 @@ export class ProductListDataSource extends DataSource<Product> {
// eslint-disable-next-line class-methods-use-this
private getFilteredData(data: Product[], filter: string): Product[] {
if (filter === undefined) {
if (filter === null || filter === undefined || filter === '') {
return data;
}
return data.filter((x) => x.menuCategory.id === filter);
return data.filter((x) => (x.menuCategory as MenuCategory).id === filter);
}
}

View File

@ -85,7 +85,7 @@ export class ProductListComponent implements OnInit {
this.list = this.dataSource.filteredData;
} else {
this.list = this.list
.filter((x) => x.menuCategory.id !== this.dataSource.filterValue)
.filter((x) => (x.menuCategory as MenuCategory).id !== this.dataSource.filterValue)
.concat(this.dataSource.filteredData);
}
this.data.next(this.list);

View File

@ -17,6 +17,25 @@
<input matInput #nameElement placeholder="Name" formControlName="name" />
</mat-form-field>
</div>
<div
fxLayout="row"
fxLayoutAlign="space-around start"
fxLayout.lt-md="column"
fxLayoutGap="20px"
fxLayoutGap.lt-md="0px"
>
<mat-form-field fxFlex>
<mat-label>Discount Limit</mat-label>
<input
matInput
type="number"
placeholder="Discount Limit"
formControlName="discountLimit"
class="right-align"
/>
<span matSuffix>%</span>
</mat-form-field>
</div>
<div
fxLayout="row"
fxLayoutAlign="space-around start"

View File

@ -2,6 +2,7 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angula
import { FormBuilder, FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { round } from 'mathjs';
import { SaleCategory } from '../../core/sale-category';
import { Tax } from '../../core/tax';
@ -31,6 +32,7 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit {
// Create form
this.form = this.fb.group({
name: '',
discountLimit: '',
tax: '',
});
}
@ -47,7 +49,8 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit {
this.item = item;
this.form.setValue({
name: this.item.name,
tax: this.item.tax.id ? this.item.tax.id : '',
discountLimit: this.item.discountLimit * 100,
tax: this.item.tax ? this.item.tax.id : '',
});
}
@ -99,6 +102,10 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit {
getItem(): SaleCategory {
const formModel = this.form.value;
this.item.name = formModel.name;
this.item.discountLimit = round(+formModel.discountLimit / 100, 5);
if (this.item.tax === null || this.item.tax === undefined) {
this.item.tax = new Tax();
}
this.item.tax.id = formModel.tax;
return this.item;
}

View File

@ -16,6 +16,12 @@
>
</ng-container>
<!-- Discount Limit Column -->
<ng-container matColumnDef="discountLimit">
<mat-header-cell *matHeaderCellDef>Discount Limit</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.discountLimit | percent: '1.2-2' }}</mat-cell>
</ng-container>
<!-- Tax Column -->
<ng-container matColumnDef="tax">
<mat-header-cell *matHeaderCellDef>Tax</mat-header-cell>

View File

@ -20,7 +20,7 @@ export class SaleCategoryListComponent implements OnInit {
dataSource: SaleCategoryListDatasource = new SaleCategoryListDatasource(this.data);
list: SaleCategory[] = [];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'tax'];
displayedColumns = ['name', 'discountLimit', 'tax'];
constructor(
private route: ActivatedRoute,

View File

@ -33,11 +33,11 @@ export class SaleCategoryService {
.pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable<SaleCategory[]>;
}
listForDiscount(): Observable<{ name: string; discount: number }[]> {
listForDiscount(): Observable<{ name: string; discount: number; discountLimit: number }[]> {
return this.http
.get<{ name: string; discount: number }[]>(`${url}/for-discount`)
.get<{ name: string; discount: number; discountLimit: number }[]>(`${url}/for-discount`)
.pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable<
{ name: string; discount: number }[]
{ name: string; discount: number; discountLimit: number }[]
>;
}

View File

@ -1,7 +1,7 @@
import { SelectionModel } from '@angular/cdk/collections';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import * as math from 'mathjs';
import { round } from 'mathjs';
import { BehaviorSubject } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
@ -9,6 +9,7 @@ import { BillViewItem } from '../core/bill-view-item';
import { ModifierCategory } from '../core/modifier-category';
import { Product } from '../core/product';
import { ReceivePaymentItem } from '../core/receive-payment-item';
import { SaleCategory } from '../core/sale-category';
import { Table } from '../core/table';
import { ToasterService } from '../core/toaster.service';
import { ModifierCategoryService } from '../modifier-categories/modifier-category.service';
@ -63,7 +64,7 @@ export class BillService {
productId: i.product.id,
isHappyHour: i.isHappyHour,
isPrinted: true,
info: `${i.product.name} @ ${i.price} - ${math.round(i.discount * 100, 2)}%`,
info: `${i.product.name} @ ${i.price} - ${round(i.discount * 100, 2)}%`,
price: i.price,
quantity: i.quantity,
discount: i.discount,
@ -182,13 +183,11 @@ export class BillService {
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) as {
id: string;
name: string;
discount: number;
}).discount / 100;
x.info = `${x.product.name} @ ${x.price} - ${math.round(x.discount * 100, 2)}%`;
const e = discounts.find((d) => d.id === (x.product.saleCategory as SaleCategory).id);
if (e !== undefined) {
x.discount = e.discount;
x.info = `${x.product.name} @ ${x.price} - ${round(x.discount * 100, 2)}%`;
}
}
});
this.dataObs.next(this.data);
@ -246,7 +245,7 @@ export class BillService {
updateAmounts() {
this.netAmount.next(
math.round(
round(
this.data
.filter((x) => !x.isKot)
.reduce(
@ -256,7 +255,7 @@ export class BillService {
),
);
this.discountAmount.next(
math.round(
round(
this.data
.filter((x) => !x.isKot)
.reduce(
@ -267,7 +266,7 @@ export class BillService {
),
);
this.taxAmount.next(
math.round(
round(
this.data
.filter((x) => !x.isKot)
.reduce(
@ -278,7 +277,7 @@ export class BillService {
),
);
this.amount.next(
math.round(
round(
this.data
.filter((x) => !x.isKot)
.reduce(
@ -291,7 +290,7 @@ export class BillService {
}
amountVal(): number {
return math.round(
return round(
this.bill.kots.reduce(
(ka: number, k: Kot) =>
ka +

View File

@ -14,6 +14,7 @@
<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-hint>Maximum Discount {{ row.discountLimit | percent: '1.2-2' }}</mat-hint>
</mat-form-field>
</mat-cell>
</ng-container>

View File

@ -1,6 +1,7 @@
import { Component, Inject } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { round } from 'mathjs';
import { Observable } from 'rxjs';
import { DiscountDataSource } from './discount-datasource';
@ -11,7 +12,7 @@ import { DiscountDataSource } from './discount-datasource';
styleUrls: ['./discount.component.css'],
})
export class DiscountComponent {
list: { name: string; discount: number }[] = [];
list: { name: string; discount: number; discountLimit: number }[] = [];
form: FormGroup;
dataSource: DiscountDataSource = new DiscountDataSource([]);
@ -20,12 +21,13 @@ export class DiscountComponent {
constructor(
public dialogRef: MatDialogRef<DiscountComponent>,
private fb: FormBuilder,
@Inject(MAT_DIALOG_DATA) public data: Observable<{ name: string; discount: number }[]>,
@Inject(MAT_DIALOG_DATA)
public data: Observable<{ name: string; discount: number; discountLimit: number }[]>,
) {
this.form = this.fb.group({
discounts: '',
});
this.data.subscribe((list: { name: string; discount: number }[]) => {
this.data.subscribe((list: { name: string; discount: number; discountLimit: number }[]) => {
this.list = list;
this.form.setControl(
'discounts',
@ -33,7 +35,7 @@ export class DiscountComponent {
this.list.map((x) =>
this.fb.group({
name: [x.name],
discount: ['', [Validators.min(0), Validators.max(100)]],
discount: ['', [Validators.min(0), Validators.max(x.discountLimit * 100)]],
}),
),
),
@ -45,7 +47,10 @@ export class DiscountComponent {
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);
item.discount = Math.max(
Math.min(round(array.controls[index].value.discount / 100, 5), item.discountLimit),
0,
);
});
this.dialogRef.close(this.list);
}

View File

@ -12,6 +12,6 @@ export class MenuCategoriesResolver implements Resolve<MenuCategory[]> {
constructor(private ser: MenuCategoryService) {}
resolve(): Observable<MenuCategory[]> {
return this.ser.list();
return this.ser.list(true);
}
}