Feature: The menu engineering report now recalculates the percentages based on filter
This commit is contained in:
@ -37,6 +37,7 @@ export class MenuEngineeringReportDataSource extends DataSource<MenuEngineeringR
|
||||
return merge(observableOf(this.data), this.filter, ...dataMutations)
|
||||
.pipe(
|
||||
map(() => this.getFilteredData([...this.data])),
|
||||
map((x) => this.recalculate(x)),
|
||||
tap((x: MenuEngineeringReportItem[]) => {
|
||||
if (this.paginator) {
|
||||
this.paginator.length = x.length;
|
||||
@ -67,10 +68,10 @@ export class MenuEngineeringReportDataSource extends DataSource<MenuEngineeringR
|
||||
return math_it_up(result.groups['sign'])(x.quantity, +result.groups['amount'] ?? '');
|
||||
}
|
||||
}
|
||||
if (c.startsWith('a:')) {
|
||||
const result = c.match(/^a:(?<sign>=|<=|>=|<|>)(?<amount>\d*)$/);
|
||||
if (c.startsWith('s:')) {
|
||||
const result = c.match(/^s:(?<sign>=|<=|>=|<|>)(?<amount>\d*)$/);
|
||||
if (result && result.groups) {
|
||||
return math_it_up(result.groups['sign'])(x.amount, +result.groups['amount'] ?? '');
|
||||
return math_it_up(result.groups['sign'])(x.sales, +result.groups['amount'] ?? '');
|
||||
}
|
||||
}
|
||||
const itemString = `${x.name} ${x.saleCategory} ${x.menuCategory}`.toLowerCase();
|
||||
@ -80,6 +81,22 @@ export class MenuEngineeringReportDataSource extends DataSource<MenuEngineeringR
|
||||
);
|
||||
}
|
||||
|
||||
private recalculate(data: MenuEngineeringReportItem[]): MenuEngineeringReportItem[] {
|
||||
const gr = data.reduce(function (res: Record<string, { q: number; s: number }>, value: MenuEngineeringReportItem) {
|
||||
if (!res[value['saleCategory']]) {
|
||||
res[value['saleCategory']] = { q: 0, s: 0 };
|
||||
}
|
||||
res[value['saleCategory']].q += value.quantity;
|
||||
res[value['saleCategory']].s += value.sales;
|
||||
return res;
|
||||
}, {});
|
||||
data.forEach((v) => {
|
||||
v.quantityPercent = v.quantity / gr[v.saleCategory].q;
|
||||
v.salesPercent = v.sales / gr[v.saleCategory].s;
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
private getPagedData(data: MenuEngineeringReportItem[]) {
|
||||
if (this.paginator === undefined) {
|
||||
return data;
|
||||
@ -110,8 +127,8 @@ export class MenuEngineeringReportDataSource extends DataSource<MenuEngineeringR
|
||||
return compare(a.menuCategory, b.menuCategory, isAsc);
|
||||
case 'quantity':
|
||||
return compare(a.quantity, b.quantity, isAsc);
|
||||
case 'amount':
|
||||
return compare(a.amount, b.amount, isAsc);
|
||||
case 'sales':
|
||||
return compare(a.sales, b.sales, isAsc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -120,7 +137,7 @@ export class MenuEngineeringReportDataSource extends DataSource<MenuEngineeringR
|
||||
}
|
||||
|
||||
function eq(x: number, y: number) {
|
||||
return x > y;
|
||||
return x === y;
|
||||
}
|
||||
function gt(x: number, y: number) {
|
||||
return x > y;
|
||||
|
||||
@ -6,7 +6,9 @@ export class MenuEngineeringReportItem {
|
||||
saleCategory: string;
|
||||
menuCategory: string;
|
||||
quantity: number;
|
||||
amount: number;
|
||||
quantityPercent: number;
|
||||
sales: number;
|
||||
salesPercent: number;
|
||||
|
||||
public constructor(init?: Partial<MenuEngineeringReportItem>) {
|
||||
this.id = '';
|
||||
@ -16,7 +18,9 @@ export class MenuEngineeringReportItem {
|
||||
this.saleCategory = '';
|
||||
this.menuCategory = '';
|
||||
this.quantity = 0;
|
||||
this.amount = 0;
|
||||
this.quantityPercent = 0;
|
||||
this.sales = 0;
|
||||
this.salesPercent = 0;
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
<input type="text" matInput #filterElement formControlName="filter" autocomplete="off" />
|
||||
<mat-hint
|
||||
>n: Name, sc: Sale Category, mc: Menu Category, q:(=/<=/>=/</>)Quantity,
|
||||
a:(=/<=/>=/</>)Amount</mat-hint
|
||||
s:(=/<=/>=/</>)Sales</mat-hint
|
||||
>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@ -81,13 +81,17 @@
|
||||
<!-- Quantity Column -->
|
||||
<ng-container matColumnDef="quantity">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header class="right">Quantity</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{ row.quantity | number : '1.2-2' }}</mat-cell>
|
||||
<mat-cell *matCellDef="let row" class="right"
|
||||
>{{ row.quantity | number : '1.2-2' }} ({{ row.quantityPercent | percent : '1.2-2' }})</mat-cell
|
||||
>
|
||||
</ng-container>
|
||||
|
||||
<!-- Amount Column -->
|
||||
<ng-container matColumnDef="amount">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header class="right">Amount</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{ row.amount | number : '1.2-2' }}</mat-cell>
|
||||
<!-- Sales Column -->
|
||||
<ng-container matColumnDef="sales">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header class="right">Sales</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right"
|
||||
>{{ row.sales | number : '1.2-2' }} ({{ row.salesPercent | percent : '1.2-2' }})</mat-cell
|
||||
>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
|
||||
@ -33,7 +33,7 @@ export class MenuEngineeringReportComponent implements OnInit {
|
||||
}>;
|
||||
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
displayedColumns = ['name', 'price', 'saleCategory', 'menuCategory', 'quantity', 'amount'];
|
||||
displayedColumns = ['name', 'price', 'saleCategory', 'menuCategory', 'quantity', 'sales'];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -104,7 +104,7 @@ export class MenuEngineeringReportComponent implements OnInit {
|
||||
'Sale Category': 'saleCategory',
|
||||
'Menu Category': 'menuCategory',
|
||||
Quantity: 'quantity',
|
||||
Amount: 'amount',
|
||||
Sales: 'sales',
|
||||
};
|
||||
const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], {
|
||||
type: 'text/csv;charset=utf-8;',
|
||||
|
||||
Reference in New Issue
Block a user