techlify-inventory-common 18.1.0 → 18.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/inventory-common/inventory-common-routing.module.mjs +11 -1
- package/esm2022/lib/inventory-common/inventory-common.module.mjs +8 -4
- package/esm2022/lib/inventory-common/inventory-dashboard-page/inventory-dashboard-page.component.mjs +10 -8
- package/esm2022/lib/inventory-common/inventory-value-report.service.mjs +21 -0
- package/esm2022/lib/inventory-common/low-stock-report.service.mjs +23 -0
- package/esm2022/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.component.mjs +9 -7
- package/esm2022/lib/inventory-common/product/product-list/product-list.component.mjs +3 -3
- package/esm2022/lib/inventory-common/product/product-quick-search/product-quick-search.component.mjs +92 -0
- package/esm2022/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.mjs +18 -0
- package/esm2022/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.mjs +170 -0
- package/esm2022/lib/inventory-common/reports/low-stock-report/low-stock-report.component.mjs +165 -0
- package/esm2022/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.mjs +64 -0
- package/esm2022/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.mjs +43 -0
- package/esm2022/lib/inventory-common/supplier/supplier.module.mjs +11 -3
- package/esm2022/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.mjs +6 -65
- package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs → techlify-inventory-common-category.module-BKEBFEeZ.mjs} +9 -9
- package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs.map → techlify-inventory-common-category.module-BKEBFEeZ.mjs.map} +1 -1
- package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs → techlify-inventory-common-measure.module-CZHhYoQd.mjs} +9 -9
- package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs.map → techlify-inventory-common-measure.module-CZHhYoQd.mjs.map} +1 -1
- package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs} +2 -4
- package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs.map → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs.map} +1 -1
- package/fesm2022/{techlify-inventory-common-supplier.module-Bwa7gx14.mjs → techlify-inventory-common-supplier.module-CFDwJ-TS.mjs} +251 -218
- package/fesm2022/techlify-inventory-common-supplier.module-CFDwJ-TS.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs +3143 -0
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common.mjs +1 -1
- package/lib/inventory-common/inventory-common.module.d.ts +2 -1
- package/lib/inventory-common/inventory-value-report.service.d.ts +9 -0
- package/lib/inventory-common/low-stock-report.service.d.ts +10 -0
- package/lib/inventory-common/product/product-quick-search/product-quick-search.component.d.ts +15 -0
- package/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.d.ts +6 -0
- package/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.d.ts +26 -0
- package/lib/inventory-common/reports/low-stock-report/low-stock-report.component.d.ts +26 -0
- package/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.d.ts +18 -0
- package/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.d.ts +13 -0
- package/lib/inventory-common/supplier/supplier.module.d.ts +3 -1
- package/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.d.ts +0 -8
- package/package.json +1 -1
- package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs +0 -1168
- package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs +0 -436
- package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs +0 -302
- package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs +0 -253
- package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs +0 -177
- package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-supplier.module-Bwa7gx14.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs +0 -14
- package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs +0 -495
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs.map +0 -1
|
@@ -0,0 +1,3143 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, Component, Input, Inject, EventEmitter, Output, forwardRef, NgModule } from '@angular/core';
|
|
3
|
+
import * as i2 from '@angular/router';
|
|
4
|
+
import { RouterModule, RouterLink, RouterLinkActive } from '@angular/router';
|
|
5
|
+
import moment from 'moment';
|
|
6
|
+
import * as i1 from 'ngx-techlify-core';
|
|
7
|
+
import { TechlifyServiceBaseClass, TechlifyListingControllerInterface, TechlifyFormComponentInterface, Timeline, AuthenticationGuard, SearchableSelectorModule, TimelineFilterModule, MaterialModule, ImportCsvModule, ColumnSelectorModule } from 'ngx-techlify-core';
|
|
8
|
+
import * as i3 from '@angular/material/icon';
|
|
9
|
+
import { MatIcon } from '@angular/material/icon';
|
|
10
|
+
import * as i4$1 from '@angular/material/card';
|
|
11
|
+
import { MatCard, MatCardContent, MatCardModule } from '@angular/material/card';
|
|
12
|
+
import * as i4 from '@angular/common';
|
|
13
|
+
import { NgIf, CommonModule, NgForOf, CurrencyPipe, DatePipe } from '@angular/common';
|
|
14
|
+
import * as i14 from '@angular/material/table';
|
|
15
|
+
import { MatTableDataSource, MatTableModule, MatCell, MatCellDef, MatColumnDef, MatHeaderCell, MatHeaderRow, MatTable, MatHeaderCellDef, MatHeaderRowDef, MatRowDef, MatRow, MatFooterCell, MatFooterRow, MatFooterRowDef, MatFooterCellDef } from '@angular/material/table';
|
|
16
|
+
import * as i7 from '@angular/material/progress-bar';
|
|
17
|
+
import { MatProgressBar, MatProgressBarModule } from '@angular/material/progress-bar';
|
|
18
|
+
import * as i10 from 'ngx-infinite-scroll';
|
|
19
|
+
import { InfiniteScrollModule, InfiniteScrollDirective } from 'ngx-infinite-scroll';
|
|
20
|
+
import * as i2$1 from 'angular-google-charts';
|
|
21
|
+
import { ChartType, GoogleChartsModule } from 'angular-google-charts';
|
|
22
|
+
import * as i7$2 from '@angular/material/form-field';
|
|
23
|
+
import { MatFormFieldModule, MatFormField, MatLabel } from '@angular/material/form-field';
|
|
24
|
+
import * as i9 from '@angular/material/input';
|
|
25
|
+
import { MatInputModule, MatInput } from '@angular/material/input';
|
|
26
|
+
import * as i2$2 from '@angular/forms';
|
|
27
|
+
import { Validators, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule, FormControl } from '@angular/forms';
|
|
28
|
+
import { BehaviorSubject, lastValueFrom, debounceTime as debounceTime$1, distinctUntilChanged } from 'rxjs';
|
|
29
|
+
import * as i13 from '@angular/material/sort';
|
|
30
|
+
import { MatSortHeader, MatSort } from '@angular/material/sort';
|
|
31
|
+
import * as i2$3 from '@angular/material/tooltip';
|
|
32
|
+
import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';
|
|
33
|
+
import { __decorate } from 'tslib';
|
|
34
|
+
import * as i1$1 from '@angular/material/dialog';
|
|
35
|
+
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
36
|
+
import * as i4$2 from 'ngx-spinner';
|
|
37
|
+
import * as i7$1 from '@angular/material/button';
|
|
38
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
39
|
+
import * as i10$1 from '@angular/flex-layout';
|
|
40
|
+
import { FlexLayoutModule, FlexModule } from '@angular/flex-layout';
|
|
41
|
+
import { debounceTime } from 'rxjs/operators';
|
|
42
|
+
import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
|
|
43
|
+
import * as i11 from '@angular/material/core';
|
|
44
|
+
import * as i12 from '@angular/material/select';
|
|
45
|
+
import * as i9$1 from '@angular/material/datepicker';
|
|
46
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
47
|
+
import { HttpParams } from '@angular/common/http';
|
|
48
|
+
import * as i12$1 from '@angular/material/button-toggle';
|
|
49
|
+
import * as i3$1 from '@angular/material/divider';
|
|
50
|
+
|
|
51
|
+
class ProductService extends TechlifyServiceBaseClass {
|
|
52
|
+
dataManager;
|
|
53
|
+
httpService;
|
|
54
|
+
constructor(dataManager, httpService) {
|
|
55
|
+
super(httpService, "products");
|
|
56
|
+
this.dataManager = dataManager;
|
|
57
|
+
this.httpService = httpService;
|
|
58
|
+
}
|
|
59
|
+
getProducts(filters) {
|
|
60
|
+
return this.dataManager.GET(`api/products`, filters);
|
|
61
|
+
}
|
|
62
|
+
getProduct(id) {
|
|
63
|
+
return this.dataManager.GET(`api/products/${id}`);
|
|
64
|
+
}
|
|
65
|
+
createProduct(model) {
|
|
66
|
+
return this.dataManager.POST(`api/products`, model);
|
|
67
|
+
}
|
|
68
|
+
updateProducts(model) {
|
|
69
|
+
return this.dataManager.PUT(`api/products/${model.id}`, model);
|
|
70
|
+
}
|
|
71
|
+
deleteProduct(id) {
|
|
72
|
+
return this.dataManager.DELETE(`api/products/${id}`);
|
|
73
|
+
}
|
|
74
|
+
getProductMeasures(filters) {
|
|
75
|
+
return this.dataManager.GET(`api/product-measures`, filters);
|
|
76
|
+
}
|
|
77
|
+
createProductMeasure(model) {
|
|
78
|
+
return this.dataManager.POST(`api/product-measures`, model);
|
|
79
|
+
}
|
|
80
|
+
updateProductMeasure(model) {
|
|
81
|
+
return this.dataManager.PUT(`api/product-measures/${model.id}`, model);
|
|
82
|
+
}
|
|
83
|
+
summary(params) {
|
|
84
|
+
return this.httpService.get("api/products-summary", { params });
|
|
85
|
+
}
|
|
86
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductService, deps: [{ token: i1.DataManager }, { token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
87
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductService, providedIn: "root" });
|
|
88
|
+
}
|
|
89
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductService, decorators: [{
|
|
90
|
+
type: Injectable,
|
|
91
|
+
args: [{
|
|
92
|
+
providedIn: "root",
|
|
93
|
+
}]
|
|
94
|
+
}], ctorParameters: () => [{ type: i1.DataManager }, { type: i1.HttpService }] });
|
|
95
|
+
|
|
96
|
+
class LowStockProductsWidgetComponent extends TechlifyListingControllerInterface {
|
|
97
|
+
productService;
|
|
98
|
+
displayedColumns = ["#", "Product", "Stock", "Reorder Point"];
|
|
99
|
+
constructor(productService) {
|
|
100
|
+
super();
|
|
101
|
+
this.productService = productService;
|
|
102
|
+
this.lastPage = 0;
|
|
103
|
+
this.perPage = 1000;
|
|
104
|
+
}
|
|
105
|
+
ngOnInit() {
|
|
106
|
+
this.loadData();
|
|
107
|
+
}
|
|
108
|
+
loadData() {
|
|
109
|
+
const params = {
|
|
110
|
+
page: this.page,
|
|
111
|
+
perPage: this.perPage,
|
|
112
|
+
is_low_stock: true,
|
|
113
|
+
num_items: this.perPage + "|" + this.page,
|
|
114
|
+
};
|
|
115
|
+
this.isWorking = true;
|
|
116
|
+
this.productService.index(params).subscribe({
|
|
117
|
+
next: (response) => {
|
|
118
|
+
this.models = this.models?.concat(response?.data);
|
|
119
|
+
this.lastPage = response?.last_page;
|
|
120
|
+
this.isWorking = false;
|
|
121
|
+
},
|
|
122
|
+
error: () => (this.isWorking = false),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
126
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LowStockProductsWidgetComponent, selector: "app-low-stock-products-widget", usesInheritance: true, ngImport: i0, template: "<mat-card style=\"max-height: 460px; overflow: auto\">\n <mat-card-content>\n <h3>Low Stock Products</h3>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef>Stock</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.current_stock }}</td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.reorder_point }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: i10.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], preserveWhitespaces: true });
|
|
127
|
+
}
|
|
128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetComponent, decorators: [{
|
|
129
|
+
type: Component,
|
|
130
|
+
args: [{ selector: "app-low-stock-products-widget", template: "<mat-card style=\"max-height: 460px; overflow: auto\">\n <mat-card-content>\n <h3>Low Stock Products</h3>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef>Stock</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.current_stock }}</td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.reorder_point }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
|
|
131
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
132
|
+
|
|
133
|
+
class ProductSummaryChartComponent {
|
|
134
|
+
productService;
|
|
135
|
+
height = 400;
|
|
136
|
+
title = 'Product Summary';
|
|
137
|
+
constructor(productService) {
|
|
138
|
+
this.productService = productService;
|
|
139
|
+
}
|
|
140
|
+
chart = {
|
|
141
|
+
title: 'Pie Chart',
|
|
142
|
+
type: ChartType.PieChart,
|
|
143
|
+
data: [],
|
|
144
|
+
options: {
|
|
145
|
+
pieSliceText: 'value'
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
isLoading = false;
|
|
149
|
+
ngOnInit() {
|
|
150
|
+
this.loadData();
|
|
151
|
+
}
|
|
152
|
+
loadData() {
|
|
153
|
+
const params = {
|
|
154
|
+
include: 'products_aggregated',
|
|
155
|
+
group_by: 'category_id',
|
|
156
|
+
};
|
|
157
|
+
this.isLoading = true;
|
|
158
|
+
this.productService.summary(params).subscribe({
|
|
159
|
+
next: (response) => {
|
|
160
|
+
let data = [];
|
|
161
|
+
response?.products_aggregated?.forEach((item) => {
|
|
162
|
+
data.push([item?.title, item?.product_count]);
|
|
163
|
+
});
|
|
164
|
+
this.chart.data = data;
|
|
165
|
+
this.isLoading = false;
|
|
166
|
+
},
|
|
167
|
+
error: () => (this.isLoading = false)
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
171
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductSummaryChartComponent, isStandalone: true, selector: "app-product-summary-chart", inputs: { height: "height", title: "title" }, ngImport: i0, template: "<mat-card>\n <mat-card-content>\n <h3>{{ title }}</h3>\n </mat-card-content>\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n <mat-card-content *ngIf=\"chart.data?.length > 0\">\n <google-chart class=\"w-100\" [height]=\"height\" [type]=\"chart.type\" [data]=\"chart.data\" [columns]=\"chart.columns\"\n [options]=\"chart.options\">\n </google-chart>\n </mat-card-content>\n</mat-card>", styles: [""], dependencies: [{ kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: GoogleChartsModule }, { kind: "component", type: i2$1.GoogleChartComponent, selector: "google-chart", inputs: ["type", "data", "columns", "title", "width", "height", "options", "formatters", "dynamicResize"], outputs: ["ready", "error", "select", "mouseover", "mouseleave"], exportAs: ["googleChart"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], preserveWhitespaces: true });
|
|
172
|
+
}
|
|
173
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartComponent, decorators: [{
|
|
174
|
+
type: Component,
|
|
175
|
+
args: [{ selector: 'app-product-summary-chart', standalone: true, imports: [
|
|
176
|
+
MatCard,
|
|
177
|
+
MatCardContent,
|
|
178
|
+
GoogleChartsModule,
|
|
179
|
+
MatProgressBar,
|
|
180
|
+
NgIf
|
|
181
|
+
], template: "<mat-card>\n <mat-card-content>\n <h3>{{ title }}</h3>\n </mat-card-content>\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n <mat-card-content *ngIf=\"chart.data?.length > 0\">\n <google-chart class=\"w-100\" [height]=\"height\" [type]=\"chart.type\" [data]=\"chart.data\" [columns]=\"chart.columns\"\n [options]=\"chart.options\">\n </google-chart>\n </mat-card-content>\n</mat-card>" }]
|
|
182
|
+
}], ctorParameters: () => [{ type: ProductService }], propDecorators: { height: [{
|
|
183
|
+
type: Input
|
|
184
|
+
}], title: [{
|
|
185
|
+
type: Input
|
|
186
|
+
}] } });
|
|
187
|
+
|
|
188
|
+
const errorMessages$1 = {
|
|
189
|
+
title: {
|
|
190
|
+
required: "Please Enter Title",
|
|
191
|
+
},
|
|
192
|
+
description: {
|
|
193
|
+
required: "Please Enter Description",
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
class ProductMeasureFormComponent {
|
|
197
|
+
productService;
|
|
198
|
+
fb;
|
|
199
|
+
dialogRef;
|
|
200
|
+
data;
|
|
201
|
+
spinnerService;
|
|
202
|
+
formValidatorService;
|
|
203
|
+
errorService;
|
|
204
|
+
alertService;
|
|
205
|
+
productMeasureForm;
|
|
206
|
+
isWorking = false;
|
|
207
|
+
isUpdate = false;
|
|
208
|
+
constructor(productService, fb, dialogRef, data, spinnerService, formValidatorService, errorService, alertService) {
|
|
209
|
+
this.productService = productService;
|
|
210
|
+
this.fb = fb;
|
|
211
|
+
this.dialogRef = dialogRef;
|
|
212
|
+
this.data = data;
|
|
213
|
+
this.spinnerService = spinnerService;
|
|
214
|
+
this.formValidatorService = formValidatorService;
|
|
215
|
+
this.errorService = errorService;
|
|
216
|
+
this.alertService = alertService;
|
|
217
|
+
this.productMeasureForm = this.fb.group({
|
|
218
|
+
id: [""],
|
|
219
|
+
title: ["", Validators.compose([Validators.required])],
|
|
220
|
+
description: ["", Validators.compose([Validators.required])],
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
ngOnInit() {
|
|
224
|
+
if (this.data.details) {
|
|
225
|
+
this.isUpdate = true;
|
|
226
|
+
this.productMeasureForm.patchValue(this.data.details);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async save() {
|
|
230
|
+
if (!this.productMeasureForm.valid) {
|
|
231
|
+
this.alertService.addAlert("Please Fill All Required Fields", "warn");
|
|
232
|
+
this.productMeasureForm.markAllAsTouched();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let productMeasure = this.productMeasureForm.value;
|
|
236
|
+
try {
|
|
237
|
+
this.spinnerService.show();
|
|
238
|
+
this.isWorking = true;
|
|
239
|
+
let result = this.isUpdate
|
|
240
|
+
? await this.productService.updateProductMeasure(productMeasure)
|
|
241
|
+
: await this.productService.createProductMeasure(productMeasure);
|
|
242
|
+
this.dialogRef.close(result);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
this.errorService.handleError(error);
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
this.isWorking = false;
|
|
249
|
+
this.spinnerService.hide();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Method to evaluate form fields
|
|
254
|
+
*/
|
|
255
|
+
isFieldValid(field) {
|
|
256
|
+
return this.formValidatorService.isFieldValid(field, this.productMeasureForm);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Method to find error in form fields
|
|
260
|
+
*/
|
|
261
|
+
getErrorMessage(field) {
|
|
262
|
+
return this.formValidatorService.getErrorMessage(field, this.productMeasureForm, errorMessages$1);
|
|
263
|
+
}
|
|
264
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasureFormComponent, deps: [{ token: ProductService }, { token: i2$2.FormBuilder }, { token: i1$1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: i4$2.NgxSpinnerService }, { token: i1.FormValidatorService }, { token: i1.ErrorHandlerService }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
265
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductMeasureFormComponent, selector: "app-product-measure-form", ngImport: i0, template: "<div>\n <form [formGroup]=\"productMeasureForm\" (ngSubmit)=\"save()\">\n <h3 class=\"text-center\">Create/Update Product Measure</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Title\"\n formControlName=\"title\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('title')\"\n >{{ getErrorMessage(\"title\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('description')\"\n >{{ getErrorMessage(\"description\") }}\n </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"dialogRef.close()\"\n >\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">\n Save\n </button>\n </div>\n </div>\n </div>\n </form>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i10$1.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10$1.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], preserveWhitespaces: true });
|
|
266
|
+
}
|
|
267
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasureFormComponent, decorators: [{
|
|
268
|
+
type: Component,
|
|
269
|
+
args: [{ selector: "app-product-measure-form", template: "<div>\n <form [formGroup]=\"productMeasureForm\" (ngSubmit)=\"save()\">\n <h3 class=\"text-center\">Create/Update Product Measure</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Title\"\n formControlName=\"title\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('title')\"\n >{{ getErrorMessage(\"title\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('description')\"\n >{{ getErrorMessage(\"description\") }}\n </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"dialogRef.close()\"\n >\n Cancel\n </button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">\n Save\n </button>\n </div>\n </div>\n </div>\n </form>\n</div>\n" }]
|
|
270
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2$2.FormBuilder }, { type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
|
|
271
|
+
type: Inject,
|
|
272
|
+
args: [MAT_DIALOG_DATA]
|
|
273
|
+
}] }, { type: i4$2.NgxSpinnerService }, { type: i1.FormValidatorService }, { type: i1.ErrorHandlerService }, { type: i1.AlertService }] });
|
|
274
|
+
|
|
275
|
+
let ProductMeasuresListComponent = class ProductMeasuresListComponent {
|
|
276
|
+
fb;
|
|
277
|
+
dialog;
|
|
278
|
+
filterService;
|
|
279
|
+
activatedRoute;
|
|
280
|
+
productService;
|
|
281
|
+
filterFormGroup;
|
|
282
|
+
lastPage;
|
|
283
|
+
page = 1;
|
|
284
|
+
perPage = 25;
|
|
285
|
+
totalItems = 0;
|
|
286
|
+
currentPage = 1;
|
|
287
|
+
num_items = 25;
|
|
288
|
+
routeFilters;
|
|
289
|
+
productMeasures = [];
|
|
290
|
+
columnDefinitions = [
|
|
291
|
+
{ def: "#", isShow: true },
|
|
292
|
+
{ def: "Title", isShow: true },
|
|
293
|
+
{ def: "Description", isShow: true },
|
|
294
|
+
{ def: "Actions", isShow: true },
|
|
295
|
+
];
|
|
296
|
+
displayedColumns = ["#", "Title", "Description", "Actions"];
|
|
297
|
+
dataSource = new MatTableDataSource();
|
|
298
|
+
constructor(fb, dialog, filterService, activatedRoute, productService) {
|
|
299
|
+
this.fb = fb;
|
|
300
|
+
this.dialog = dialog;
|
|
301
|
+
this.filterService = filterService;
|
|
302
|
+
this.activatedRoute = activatedRoute;
|
|
303
|
+
this.productService = productService;
|
|
304
|
+
this.filterFormGroup = this.fb.group({
|
|
305
|
+
num_items: [this.num_items + "|" + this.currentPage],
|
|
306
|
+
search: [""],
|
|
307
|
+
type_ids: [""],
|
|
308
|
+
sort_by: [""],
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
ngOnInit() {
|
|
312
|
+
this.patchFiltersFromRoute();
|
|
313
|
+
this.listenForChanges();
|
|
314
|
+
this.loadData();
|
|
315
|
+
}
|
|
316
|
+
listenForChanges() {
|
|
317
|
+
this.filterFormGroup.valueChanges
|
|
318
|
+
.pipe(debounceTime(500), untilDestroyed(this))
|
|
319
|
+
.subscribe((changes) => {
|
|
320
|
+
this.filterService.applyFilterToRoute(this.activatedRoute, this.filterFormGroup.value);
|
|
321
|
+
this.reload();
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
patchFiltersFromRoute() {
|
|
325
|
+
this.routeFilters = this.filterService.getFiltersFromRoute(this.activatedRoute, this.filterFormGroup.value);
|
|
326
|
+
this.filterFormGroup.setValue(this.routeFilters);
|
|
327
|
+
if (this.routeFilters.type_ids) {
|
|
328
|
+
this.filterFormGroup
|
|
329
|
+
.get("type_ids")
|
|
330
|
+
.setValue(this.routeFilters.type_ids.split(",").map(Number));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
async loadData() {
|
|
334
|
+
let filters = this.filterFormGroup.value;
|
|
335
|
+
filters.page = this.page;
|
|
336
|
+
filters.per_page = this.perPage;
|
|
337
|
+
filters.type_ids = filters.type_ids.toString();
|
|
338
|
+
filters.num_items = this.num_items + "|" + this.currentPage;
|
|
339
|
+
let res = await this.productService.getProductMeasures(filters);
|
|
340
|
+
if (this.productMeasures.length < 1) {
|
|
341
|
+
this.productMeasures = res.data;
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
res.data.forEach((item) => this.productMeasures.push(item));
|
|
345
|
+
}
|
|
346
|
+
this.dataSource = new MatTableDataSource(this.productMeasures);
|
|
347
|
+
this.totalItems = res.total;
|
|
348
|
+
this.lastPage = res.last_page || this.page;
|
|
349
|
+
}
|
|
350
|
+
reload() {
|
|
351
|
+
this.productMeasures = [];
|
|
352
|
+
this.currentPage = 1;
|
|
353
|
+
this.loadData();
|
|
354
|
+
}
|
|
355
|
+
modifyProductMeasure(model) {
|
|
356
|
+
const dialogRef = this.dialog.open(ProductMeasureFormComponent, {
|
|
357
|
+
width: "600px",
|
|
358
|
+
data: {
|
|
359
|
+
details: model,
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
363
|
+
if (result) {
|
|
364
|
+
this.reload();
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
onScroll() {
|
|
369
|
+
if (this.totalItems > this.productMeasures.length) {
|
|
370
|
+
this.currentPage += 1;
|
|
371
|
+
this.loadData();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
assignFilter(column, direction) {
|
|
375
|
+
if (column) {
|
|
376
|
+
return this.filterFormGroup
|
|
377
|
+
.get("sort_by")
|
|
378
|
+
?.setValue(column + "|" + direction);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
sortColumn(event) {
|
|
382
|
+
var direction = event.direction.toString().toUpperCase();
|
|
383
|
+
this.assignFilter(event.active, direction);
|
|
384
|
+
}
|
|
385
|
+
// eslint-disable-next-line @angular-eslint/use-lifecycle-interface
|
|
386
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
387
|
+
ngOnDestroy() {
|
|
388
|
+
//Called once, before the instance is destroyed.
|
|
389
|
+
//Add 'implements OnDestroy' to the class.
|
|
390
|
+
}
|
|
391
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasuresListComponent, deps: [{ token: i2$2.FormBuilder }, { token: i1$1.MatDialog }, { token: i1.FilterService }, { token: i2.ActivatedRoute }, { token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
392
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductMeasuresListComponent, selector: "app-product-measure-list", ngImport: i0, template: "<div fxLayout=\"column\">\n <div class=\"text-center\" fxLayoutAlign=\"center center\">\n <h3 fxLayout>\n <span class=\"mt-1\"> Product Measures </span>\n <button\n mat-raised-button\n class=\"ml-2\"\n color=\"primary\"\n (click)=\"modifyProductMeasure()\"\n >\n <mat-icon>add</mat-icon>\n Product Measure\n </button>\n </h3>\n </div>\n\n <div fxLayout>\n <form [formGroup]=\"filterFormGroup\" fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Item Name, Description, etc.\"\n formControlName=\"search\"\n />\n </mat-form-field>\n </form>\n\n <mat-form-field class=\"ml-2\" fxFlex=\"0 1 calc(11.11% - 0.5rem)\">\n <mat-label>Columns</mat-label>\n <mat-select [(ngModel)]=\"displayedColumns\" multiple name=\"column\">\n <mat-option\n *ngFor=\"let column of columnDefinitions\"\n [value]=\"column.def\"\n [disabled]=\"!column.isShow\"\n >\n {{ column?.def }}</mat-option\n >\n </mat-select>\n </mat-form-field>\n </div>\n\n <table\n mat-table\n #table\n [dataSource]=\"dataSource\"\n class=\"mat-elevation-z8 w-100 mt-4 table-hover\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n infiniteScrollContainer=\"mat-sidenav-content\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"Title\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Title</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.title }}</td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Description</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.description }}</td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary\" fxLayoutGap=\"1rem\">\n <button mat-icon-button (click)=\"modifyProductMeasure(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i11.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i10$1.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i10$1.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], preserveWhitespaces: true });
|
|
393
|
+
};
|
|
394
|
+
ProductMeasuresListComponent = __decorate([
|
|
395
|
+
UntilDestroy()
|
|
396
|
+
], ProductMeasuresListComponent);
|
|
397
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasuresListComponent, decorators: [{
|
|
398
|
+
type: Component,
|
|
399
|
+
args: [{ selector: "app-product-measure-list", template: "<div fxLayout=\"column\">\n <div class=\"text-center\" fxLayoutAlign=\"center center\">\n <h3 fxLayout>\n <span class=\"mt-1\"> Product Measures </span>\n <button\n mat-raised-button\n class=\"ml-2\"\n color=\"primary\"\n (click)=\"modifyProductMeasure()\"\n >\n <mat-icon>add</mat-icon>\n Product Measure\n </button>\n </h3>\n </div>\n\n <div fxLayout>\n <form [formGroup]=\"filterFormGroup\" fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field>\n <input\n matInput\n placeholder=\"Item Name, Description, etc.\"\n formControlName=\"search\"\n />\n </mat-form-field>\n </form>\n\n <mat-form-field class=\"ml-2\" fxFlex=\"0 1 calc(11.11% - 0.5rem)\">\n <mat-label>Columns</mat-label>\n <mat-select [(ngModel)]=\"displayedColumns\" multiple name=\"column\">\n <mat-option\n *ngFor=\"let column of columnDefinitions\"\n [value]=\"column.def\"\n [disabled]=\"!column.isShow\"\n >\n {{ column?.def }}</mat-option\n >\n </mat-select>\n </mat-form-field>\n </div>\n\n <table\n mat-table\n #table\n [dataSource]=\"dataSource\"\n class=\"mat-elevation-z8 w-100 mt-4 table-hover\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n infiniteScrollContainer=\"mat-sidenav-content\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"Title\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Title</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.title }}</td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Description</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.description }}</td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary\" fxLayoutGap=\"1rem\">\n <button mat-icon-button (click)=\"modifyProductMeasure(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n</div>\n" }]
|
|
400
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1$1.MatDialog }, { type: i1.FilterService }, { type: i2.ActivatedRoute }, { type: ProductService }] });
|
|
401
|
+
|
|
402
|
+
class TechlifyFormService {
|
|
403
|
+
_isListUpdated = new BehaviorSubject(false);
|
|
404
|
+
isListUpdated() {
|
|
405
|
+
return this._isListUpdated.asObservable();
|
|
406
|
+
}
|
|
407
|
+
listUpdated(val) {
|
|
408
|
+
this._isListUpdated.next(val);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
class ProductFormService extends TechlifyFormService {
|
|
413
|
+
constructor() {
|
|
414
|
+
super();
|
|
415
|
+
}
|
|
416
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
417
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, providedIn: "root" });
|
|
418
|
+
}
|
|
419
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, decorators: [{
|
|
420
|
+
type: Injectable,
|
|
421
|
+
args: [{
|
|
422
|
+
providedIn: "root",
|
|
423
|
+
}]
|
|
424
|
+
}], ctorParameters: () => [] });
|
|
425
|
+
|
|
426
|
+
const initial_quantity = 0;
|
|
427
|
+
const reorder_point = 10;
|
|
428
|
+
const errorMessages = {
|
|
429
|
+
type_id: {
|
|
430
|
+
required: "Please Enter Type",
|
|
431
|
+
},
|
|
432
|
+
name: {
|
|
433
|
+
required: "Please Enter Name",
|
|
434
|
+
},
|
|
435
|
+
sale_price: {
|
|
436
|
+
required: "Please Enter Sales Price",
|
|
437
|
+
},
|
|
438
|
+
minimum_price: {
|
|
439
|
+
required: "Please Enter Minimum Price",
|
|
440
|
+
},
|
|
441
|
+
reorder_point: {
|
|
442
|
+
required: "Please Enter Reorder Point",
|
|
443
|
+
},
|
|
444
|
+
};
|
|
445
|
+
class ProductFormComponent {
|
|
446
|
+
productService;
|
|
447
|
+
fb;
|
|
448
|
+
formValidatorService;
|
|
449
|
+
alertService;
|
|
450
|
+
datePipe;
|
|
451
|
+
productFormService;
|
|
452
|
+
productForm;
|
|
453
|
+
isWorking = false;
|
|
454
|
+
isUpdate = false;
|
|
455
|
+
saved = new EventEmitter();
|
|
456
|
+
cancelled = new EventEmitter();
|
|
457
|
+
product;
|
|
458
|
+
displayedFormFields = [
|
|
459
|
+
"name",
|
|
460
|
+
"product type",
|
|
461
|
+
"sku",
|
|
462
|
+
"description",
|
|
463
|
+
"product measure",
|
|
464
|
+
"reorder point",
|
|
465
|
+
"initial quantity",
|
|
466
|
+
"initial quantity date",
|
|
467
|
+
"sales price",
|
|
468
|
+
"minimum price",
|
|
469
|
+
"maximum price",
|
|
470
|
+
"income account",
|
|
471
|
+
"expense account",
|
|
472
|
+
];
|
|
473
|
+
displayedFormSections = [
|
|
474
|
+
"basic information",
|
|
475
|
+
"inventory information",
|
|
476
|
+
"sales information",
|
|
477
|
+
"accounts information",
|
|
478
|
+
];
|
|
479
|
+
constructor(productService, fb, formValidatorService, alertService, datePipe, productFormService) {
|
|
480
|
+
this.productService = productService;
|
|
481
|
+
this.fb = fb;
|
|
482
|
+
this.formValidatorService = formValidatorService;
|
|
483
|
+
this.alertService = alertService;
|
|
484
|
+
this.datePipe = datePipe;
|
|
485
|
+
this.productFormService = productFormService;
|
|
486
|
+
this.productForm = this.fb.group({
|
|
487
|
+
id: [""],
|
|
488
|
+
type_id: [1, Validators.compose([Validators.required])],
|
|
489
|
+
sku: [""],
|
|
490
|
+
name: ["", Validators.compose([Validators.required])],
|
|
491
|
+
initial_quantity: [initial_quantity],
|
|
492
|
+
initial_quantity_date: [moment().format()],
|
|
493
|
+
reorder_point: [reorder_point, Validators.compose([Validators.required])],
|
|
494
|
+
description: [""],
|
|
495
|
+
sale_price: [0, Validators.compose([Validators.required])],
|
|
496
|
+
income_account_id: [""],
|
|
497
|
+
expense_account_id: [""],
|
|
498
|
+
measure_id: [1],
|
|
499
|
+
minimum_price: ["", Validators.compose([Validators.required])],
|
|
500
|
+
maximum_price: [""],
|
|
501
|
+
condition_type_id: [1],
|
|
502
|
+
current_quantity: [],
|
|
503
|
+
category_ids: [""],
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
ngOnInit() {
|
|
507
|
+
if (this.product?.id) {
|
|
508
|
+
this.isUpdate = true;
|
|
509
|
+
let data = { ...this.product };
|
|
510
|
+
if (this.product?.categories?.length > 0) {
|
|
511
|
+
data.category_ids = this.product.categories.map((category) => category?.id);
|
|
512
|
+
}
|
|
513
|
+
if (data?.initial_quantity_date) {
|
|
514
|
+
data.initial_quantity_date = moment(data.initial_quantity_date).toISOString();
|
|
515
|
+
}
|
|
516
|
+
this.productForm.patchValue(data);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
async save() {
|
|
520
|
+
this.productForm.markAllAsTouched();
|
|
521
|
+
if (this.productForm.invalid) {
|
|
522
|
+
this.alertService.addAlert("Please Fill All Required Fields", "warn");
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
let product = this.productForm.value;
|
|
526
|
+
if (product.maximum_price <= 0 || !product.maximum_price) {
|
|
527
|
+
product.maximum_price = product.minimum_price;
|
|
528
|
+
}
|
|
529
|
+
if (product?.initial_quantity_date) {
|
|
530
|
+
product.initial_quantity_date = moment(product.initial_quantity_date).format("YYYY-MM-DD");
|
|
531
|
+
}
|
|
532
|
+
this.isWorking = true;
|
|
533
|
+
product.with = "type,measure,incomeAccount,expenseAccount";
|
|
534
|
+
let request = this.productService.store(product);
|
|
535
|
+
if (this.isUpdate) {
|
|
536
|
+
request = this.productService.update(product);
|
|
537
|
+
}
|
|
538
|
+
request.subscribe({
|
|
539
|
+
next: (response) => {
|
|
540
|
+
this.saved.emit(response?.item);
|
|
541
|
+
this.isWorking = false;
|
|
542
|
+
this.productFormService.listUpdated(true);
|
|
543
|
+
this.alertService.addAlert("Product saved successfully!", "success");
|
|
544
|
+
},
|
|
545
|
+
error: () => (this.isWorking = false),
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Method to evaluate form fields
|
|
550
|
+
*/
|
|
551
|
+
isFieldValid(field) {
|
|
552
|
+
return this.formValidatorService.isFieldValid(field, this.productForm);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Method to find error in form fields
|
|
556
|
+
*/
|
|
557
|
+
getErrorMessage(field) {
|
|
558
|
+
return this.formValidatorService.getErrorMessage(field, this.productForm, errorMessages);
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Checks displayed Form Fields array for form field and returns boolean result
|
|
562
|
+
*/
|
|
563
|
+
isFormFieldShown(fieldName) {
|
|
564
|
+
return (this.displayedFormFields.length > 0 &&
|
|
565
|
+
this.displayedFormFields.includes(fieldName));
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Checks displayed Form Section array for form section and returns boolean result
|
|
569
|
+
*/
|
|
570
|
+
isFormSectionShown(sectionName) {
|
|
571
|
+
return (this.displayedFormSections.length > 0 &&
|
|
572
|
+
this.displayedFormSections.includes(sectionName));
|
|
573
|
+
}
|
|
574
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormComponent, deps: [{ token: ProductService }, { token: i2$2.FormBuilder }, { token: i1.FormValidatorService }, { token: i1.AlertService }, { token: i4.DatePipe }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
|
|
575
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductFormComponent, selector: "app-product-form", inputs: { product: "product", displayedFormFields: "displayedFormFields", displayedFormSections: "displayedFormSections" }, outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<form [formGroup]=\"productForm\" (submit)=\"save()\">\n <h3 class=\"text-center\">{{ product?.id ? \"Update\" : \"Create\" }} Product</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('basic information')\">\n <h3><strong>Basic Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('name')\">\n <input matInput placeholder=\"Name\" formControlName=\"name\" required />\n <mat-error *ngIf=\"isFieldValid('name')\"\n >{{ getErrorMessage(\"name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product type')\">\n <mat-label>Product Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\"\n >{{ getErrorMessage(\"type_id\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sku')\">\n <input matInput placeholder=\"SKU\" formControlName=\"sku\" />\n <mat-error *ngIf=\"isFieldValid('sku')\"\n >{{ getErrorMessage(\"sku\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('category_ids')\">\n {{ getErrorMessage(\"category_ids\") }}\n </mat-error>\n </mat-form-field>\n </div>\n\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"100%\" *ngIf=\"isFormFieldShown('description')\">\n <textarea\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n ></textarea>\n </mat-form-field>\n </div>\n </div>\n\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('inventory information')\">\n <h3><strong>Inventory Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('product measure')\"\n >\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\"\n >{{ getErrorMessage(\"measure_id\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input\n matInput\n placeholder=\"Reorder Point\"\n formControlName=\"reorder_point\"\n type=\"number\"\n />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\"\n >{{ getErrorMessage(\"reorder_point\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity')\"\n >\n <input\n matInput\n placeholder=\"Initial Quantity\"\n formControlName=\"initial_quantity\"\n />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\"\n >{{ getErrorMessage(\"initial_quantity\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity date')\"\n >\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle\n matSuffix\n [for]=\"pickerInitialQuantityDate\"\n ></mat-datepicker-toggle>\n <mat-datepicker #pickerInitialQuantityDate></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('initial_quantity_date')\"\n >{{ getErrorMessage(\"initial_quantity_date\") }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('sales information')\">\n <h3><strong>Sale Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sales price')\">\n <input\n matInput\n placeholder=\"Selling Price\"\n formControlName=\"sale_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('sale_price')\"\n >{{ getErrorMessage(\"sale_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('condition types')\"\n >\n <mat-label>Condition</mat-label>\n <app-searchable-selector\n apiUrl=\"api/condition-types\"\n formControlName=\"condition_type_id\"\n ></app-searchable-selector>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('minimum price')\">\n <input\n matInput\n placeholder=\"Minimum Price\"\n formControlName=\"minimum_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('minimum_price')\"\n >{{ getErrorMessage(\"minimum_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input\n matInput\n placeholder=\"Maximum Price\"\n formControlName=\"maximum_price\"\n type=\"number\"\n step=\"any\"\n />\n </mat-form-field>\n </div>\n </div>\n <!-- <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('accounts information')\">-->\n <!-- <h3><strong>Accounts Information</strong></h3>-->\n <!-- <div fxLayout fxLayoutGap=\"0.5rem\">-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('income account')\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"income_account_id\"> </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('expense account')\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"expense_account_id\">-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- </div>-->\n <!-- </div>-->\n <div fxFlex=\"100%\" fxLayout fxLayoutAlign=\"end\" fxLayoutGap=\"1rem\">\n <button\n [disabled]=\"isWorking\"\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"cancelled.emit(true)\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n class=\"mt-2\"\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i10$1.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i10$1.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], preserveWhitespaces: true });
|
|
576
|
+
}
|
|
577
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormComponent, decorators: [{
|
|
578
|
+
type: Component,
|
|
579
|
+
args: [{ selector: "app-product-form", template: "<form [formGroup]=\"productForm\" (submit)=\"save()\">\n <h3 class=\"text-center\">{{ product?.id ? \"Update\" : \"Create\" }} Product</h3>\n <div fxLayout=\"column\">\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('basic information')\">\n <h3><strong>Basic Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('name')\">\n <input matInput placeholder=\"Name\" formControlName=\"name\" required />\n <mat-error *ngIf=\"isFieldValid('name')\"\n >{{ getErrorMessage(\"name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product type')\">\n <mat-label>Product Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\"\n >{{ getErrorMessage(\"type_id\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sku')\">\n <input matInput placeholder=\"SKU\" formControlName=\"sku\" />\n <mat-error *ngIf=\"isFieldValid('sku')\"\n >{{ getErrorMessage(\"sku\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('category_ids')\">\n {{ getErrorMessage(\"category_ids\") }}\n </mat-error>\n </mat-form-field>\n </div>\n\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"100%\" *ngIf=\"isFormFieldShown('description')\">\n <textarea\n matInput\n placeholder=\"Description\"\n formControlName=\"description\"\n ></textarea>\n </mat-form-field>\n </div>\n </div>\n\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('inventory information')\">\n <h3><strong>Inventory Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('product measure')\"\n >\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_id\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\"\n >{{ getErrorMessage(\"measure_id\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input\n matInput\n placeholder=\"Reorder Point\"\n formControlName=\"reorder_point\"\n type=\"number\"\n />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\"\n >{{ getErrorMessage(\"reorder_point\") }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity')\"\n >\n <input\n matInput\n placeholder=\"Initial Quantity\"\n formControlName=\"initial_quantity\"\n />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\"\n >{{ getErrorMessage(\"initial_quantity\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('initial quantity date')\"\n >\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle\n matSuffix\n [for]=\"pickerInitialQuantityDate\"\n ></mat-datepicker-toggle>\n <mat-datepicker #pickerInitialQuantityDate></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('initial_quantity_date')\"\n >{{ getErrorMessage(\"initial_quantity_date\") }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('sales information')\">\n <h3><strong>Sale Information</strong></h3>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('sales price')\">\n <input\n matInput\n placeholder=\"Selling Price\"\n formControlName=\"sale_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('sale_price')\"\n >{{ getErrorMessage(\"sale_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field\n fxFlex=\"50%\"\n *ngIf=\"isFormFieldShown('condition types')\"\n >\n <mat-label>Condition</mat-label>\n <app-searchable-selector\n apiUrl=\"api/condition-types\"\n formControlName=\"condition_type_id\"\n ></app-searchable-selector>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('minimum price')\">\n <input\n matInput\n placeholder=\"Minimum Price\"\n formControlName=\"minimum_price\"\n required\n type=\"number\"\n step=\"any\"\n />\n <mat-error *ngIf=\"isFieldValid('minimum_price')\"\n >{{ getErrorMessage(\"minimum_price\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input\n matInput\n placeholder=\"Maximum Price\"\n formControlName=\"maximum_price\"\n type=\"number\"\n step=\"any\"\n />\n </mat-form-field>\n </div>\n </div>\n <!-- <div fxLayout=\"column\" *ngIf=\"isFormSectionShown('accounts information')\">-->\n <!-- <h3><strong>Accounts Information</strong></h3>-->\n <!-- <div fxLayout fxLayoutGap=\"0.5rem\">-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('income account')\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"income_account_id\"> </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('expense account')\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector apiUrl=\"api/accounts\" formControlName=\"expense_account_id\">-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- </div>-->\n <!-- </div>-->\n <div fxFlex=\"100%\" fxLayout fxLayoutAlign=\"end\" fxLayoutGap=\"1rem\">\n <button\n [disabled]=\"isWorking\"\n mat-button\n class=\"mt-2\"\n type=\"button\"\n (click)=\"cancelled.emit(true)\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n class=\"mt-2\"\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n" }]
|
|
580
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2$2.FormBuilder }, { type: i1.FormValidatorService }, { type: i1.AlertService }, { type: i4.DatePipe }, { type: ProductFormService }], propDecorators: { saved: [{
|
|
581
|
+
type: Output
|
|
582
|
+
}], cancelled: [{
|
|
583
|
+
type: Output
|
|
584
|
+
}], product: [{
|
|
585
|
+
type: Input
|
|
586
|
+
}], displayedFormFields: [{
|
|
587
|
+
type: Input
|
|
588
|
+
}], displayedFormSections: [{
|
|
589
|
+
type: Input
|
|
590
|
+
}] } });
|
|
591
|
+
|
|
592
|
+
class StockReceiptService extends TechlifyServiceBaseClass {
|
|
593
|
+
constructor(httpService) {
|
|
594
|
+
super(httpService, "stock-receipts");
|
|
595
|
+
}
|
|
596
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
597
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, providedIn: "root" });
|
|
598
|
+
}
|
|
599
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, decorators: [{
|
|
600
|
+
type: Injectable,
|
|
601
|
+
args: [{
|
|
602
|
+
providedIn: "root",
|
|
603
|
+
}]
|
|
604
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
605
|
+
|
|
606
|
+
class SupplierService {
|
|
607
|
+
httpService;
|
|
608
|
+
constructor(httpService) {
|
|
609
|
+
this.httpService = httpService;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* get all suppliers from API
|
|
613
|
+
*
|
|
614
|
+
* @param filters Any attributes to filter suppliers by
|
|
615
|
+
*/
|
|
616
|
+
index(filters) {
|
|
617
|
+
let queries = new HttpParams({ fromObject: filters });
|
|
618
|
+
return this.httpService.get(`api/suppliers`, { params: queries });
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* get individual supplier from API (for view page)
|
|
622
|
+
*
|
|
623
|
+
* @param id ID of the supplier being requested
|
|
624
|
+
*/
|
|
625
|
+
show(id) {
|
|
626
|
+
return this.httpService.get(`api/suppliers/${id}`);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* store a new supplier in the DB
|
|
630
|
+
*
|
|
631
|
+
* @param model data from the supplier form that will be stored in the DB
|
|
632
|
+
*/
|
|
633
|
+
store(model) {
|
|
634
|
+
return this.httpService.post(`api/suppliers`, model);
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* update a supplier in the DB
|
|
638
|
+
*
|
|
639
|
+
* @param model.id ID of the supplier being updated
|
|
640
|
+
* @param model data from the supplier form that will be updated in the DB
|
|
641
|
+
*/
|
|
642
|
+
update(model) {
|
|
643
|
+
return this.httpService.put(`api/suppliers/${model?.id}`, model);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* delete a supplier from the DB
|
|
647
|
+
*
|
|
648
|
+
* @param id ID of the supplier being deleted
|
|
649
|
+
*/
|
|
650
|
+
destroy(id) {
|
|
651
|
+
return this.httpService.delete(`api/suppliers/${id}`);
|
|
652
|
+
}
|
|
653
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
654
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, providedIn: "root" });
|
|
655
|
+
}
|
|
656
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, decorators: [{
|
|
657
|
+
type: Injectable,
|
|
658
|
+
args: [{
|
|
659
|
+
providedIn: "root",
|
|
660
|
+
}]
|
|
661
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
662
|
+
|
|
663
|
+
class SupplierFormComponent extends TechlifyFormComponentInterface {
|
|
664
|
+
fb;
|
|
665
|
+
alertService;
|
|
666
|
+
spinnerService;
|
|
667
|
+
dialogRef;
|
|
668
|
+
errorService;
|
|
669
|
+
data;
|
|
670
|
+
supplierService;
|
|
671
|
+
errorMessages = {
|
|
672
|
+
contact_name: {
|
|
673
|
+
required: "Contact Name is required",
|
|
674
|
+
},
|
|
675
|
+
company_name: {
|
|
676
|
+
required: "Company Name is required",
|
|
677
|
+
},
|
|
678
|
+
address: {
|
|
679
|
+
required: "Address is required",
|
|
680
|
+
},
|
|
681
|
+
phone: {
|
|
682
|
+
required: "Phone is required",
|
|
683
|
+
},
|
|
684
|
+
details: {
|
|
685
|
+
required: "Details is required",
|
|
686
|
+
},
|
|
687
|
+
email: {
|
|
688
|
+
required: "Email is required",
|
|
689
|
+
},
|
|
690
|
+
supplier_type_id: {
|
|
691
|
+
required: "Supplier Type is required",
|
|
692
|
+
},
|
|
693
|
+
};
|
|
694
|
+
isWorking = false;
|
|
695
|
+
isUpdateMode = false;
|
|
696
|
+
supplierForm;
|
|
697
|
+
constructor(fb, formValidatorService, alertService, spinnerService, dialogRef, errorService, data, supplierService) {
|
|
698
|
+
super(formValidatorService);
|
|
699
|
+
this.fb = fb;
|
|
700
|
+
this.alertService = alertService;
|
|
701
|
+
this.spinnerService = spinnerService;
|
|
702
|
+
this.dialogRef = dialogRef;
|
|
703
|
+
this.errorService = errorService;
|
|
704
|
+
this.data = data;
|
|
705
|
+
this.supplierService = supplierService;
|
|
706
|
+
this.supplierForm = this.fb.group({
|
|
707
|
+
id: [""],
|
|
708
|
+
contact_name: [""],
|
|
709
|
+
company_name: ["", Validators.compose([Validators.required])],
|
|
710
|
+
details: [""],
|
|
711
|
+
address: [""],
|
|
712
|
+
phone: [""],
|
|
713
|
+
email: [""],
|
|
714
|
+
supplier_type_id: ["",],
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
ngOnInit() {
|
|
718
|
+
if (this.data.details) {
|
|
719
|
+
this.isUpdateMode = true;
|
|
720
|
+
this.supplierForm.patchValue(this.data.details);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
async submit() {
|
|
724
|
+
if (!this.supplierForm.valid) {
|
|
725
|
+
this.alertService.addAlert("Please Fill All Required Fields", "warn");
|
|
726
|
+
this.supplierForm.markAllAsTouched();
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
var supplier = this.supplierForm.value;
|
|
730
|
+
try {
|
|
731
|
+
this.spinnerService.show();
|
|
732
|
+
this.isWorking = true;
|
|
733
|
+
let result = this.isUpdateMode
|
|
734
|
+
? await lastValueFrom(this.supplierService.update(supplier))
|
|
735
|
+
: await lastValueFrom(this.supplierService.store(supplier));
|
|
736
|
+
this.dialogRef.close(result);
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
this.errorService.handleError(error);
|
|
740
|
+
}
|
|
741
|
+
finally {
|
|
742
|
+
this.isWorking = false;
|
|
743
|
+
this.spinnerService.hide();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/**Method to evaluate form fields*/
|
|
747
|
+
isFieldValid(field) {
|
|
748
|
+
return this.formValidatorService.isFieldValid(field, this.supplierForm);
|
|
749
|
+
}
|
|
750
|
+
/**Method to find error in form fields*/
|
|
751
|
+
getErrorMessage(field) {
|
|
752
|
+
return this.formValidatorService.getErrorMessage(field, this.supplierForm, this.errorMessages);
|
|
753
|
+
}
|
|
754
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierFormComponent, deps: [{ token: i2$2.FormBuilder }, { token: i1.FormValidatorService }, { token: i1.AlertService }, { token: i4$2.NgxSpinnerService }, { token: i1$1.MatDialogRef }, { token: i1.ErrorHandlerService }, { token: MAT_DIALOG_DATA }, { token: SupplierService }], target: i0.ɵɵFactoryTarget.Component });
|
|
755
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SupplierFormComponent, selector: "app-supplier-form", usesInheritance: true, ngImport: i0, template: "<form\n (ngSubmit)=\"submit()\"\n [formGroup]=\"supplierForm\"\n class=\"mat-typography\"\n>\n <div class=\"d-flex flex-column justify-content-start gap-2\" mat-dialog-content>\n <h2 class=\"mb-2\">{{ isUpdateMode ? 'Edit' : 'Create' }} Supplier</h2>\n <mat-form-field>\n <mat-label>Company Name</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"company_name\"\n matInput\n placeholder=\"Company Name\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('company_name')\">\n {{ getErrorMessage(\"company_name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Contact Name</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"contact_name\"\n matInput\n placeholder=\"Contact Name\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Types</mat-label>\n <app-searchable-selector\n apiUrl=\"api/supplier-types\"\n formControlName=\"supplier_type_id\"\n titleField=\"title\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Phone</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"phone\"\n matInput\n placeholder=\"Phone\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Email</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"email\"\n matInput\n placeholder=\"Email\"\n type=\"email\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Address</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"address\"\n matInput\n placeholder=\"Address\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Details</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"details\"\n matInput\n placeholder=\"Details\"\n />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n (click)=\"dialogRef.close()\"\n [disabled]=\"isWorking\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n color=\"primary\"\n mat-raised-button\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], preserveWhitespaces: true });
|
|
756
|
+
}
|
|
757
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierFormComponent, decorators: [{
|
|
758
|
+
type: Component,
|
|
759
|
+
args: [{ selector: "app-supplier-form", template: "<form\n (ngSubmit)=\"submit()\"\n [formGroup]=\"supplierForm\"\n class=\"mat-typography\"\n>\n <div class=\"d-flex flex-column justify-content-start gap-2\" mat-dialog-content>\n <h2 class=\"mb-2\">{{ isUpdateMode ? 'Edit' : 'Create' }} Supplier</h2>\n <mat-form-field>\n <mat-label>Company Name</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"company_name\"\n matInput\n placeholder=\"Company Name\"\n required\n />\n <mat-error *ngIf=\"isFieldValid('company_name')\">\n {{ getErrorMessage(\"company_name\") }}\n </mat-error>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Contact Name</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"contact_name\"\n matInput\n placeholder=\"Contact Name\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Types</mat-label>\n <app-searchable-selector\n apiUrl=\"api/supplier-types\"\n formControlName=\"supplier_type_id\"\n titleField=\"title\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Phone</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"phone\"\n matInput\n placeholder=\"Phone\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Email</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"email\"\n matInput\n placeholder=\"Email\"\n type=\"email\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Address</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"address\"\n matInput\n placeholder=\"Address\"\n />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Details</mat-label>\n <input\n autocomplete=\"off\"\n formControlName=\"details\"\n matInput\n placeholder=\"Details\"\n />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n (click)=\"dialogRef.close()\"\n [disabled]=\"isWorking\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n <button\n [disabled]=\"isWorking\"\n color=\"primary\"\n mat-raised-button\n type=\"submit\"\n >\n Save\n </button>\n </div>\n </div>\n</form>\n" }]
|
|
760
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1.FormValidatorService }, { type: i1.AlertService }, { type: i4$2.NgxSpinnerService }, { type: i1$1.MatDialogRef }, { type: i1.ErrorHandlerService }, { type: undefined, decorators: [{
|
|
761
|
+
type: Inject,
|
|
762
|
+
args: [MAT_DIALOG_DATA]
|
|
763
|
+
}] }, { type: SupplierService }] });
|
|
764
|
+
|
|
765
|
+
class PayeeSelectorComponent {
|
|
766
|
+
label = "Payee";
|
|
767
|
+
appearance = "fill";
|
|
768
|
+
required = false;
|
|
769
|
+
showAddButton = false;
|
|
770
|
+
multiple = false;
|
|
771
|
+
value;
|
|
772
|
+
onChange = () => { };
|
|
773
|
+
onTouch = () => { };
|
|
774
|
+
writeValue(value) {
|
|
775
|
+
this.value = value;
|
|
776
|
+
this.onChange(value);
|
|
777
|
+
this.onTouch(value);
|
|
778
|
+
}
|
|
779
|
+
registerOnChange(fn) {
|
|
780
|
+
this.onChange = fn;
|
|
781
|
+
}
|
|
782
|
+
registerOnTouched(fn) {
|
|
783
|
+
this.onTouch = fn;
|
|
784
|
+
}
|
|
785
|
+
SupplierFormComponent = SupplierFormComponent;
|
|
786
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
787
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PayeeSelectorComponent, selector: "app-payee-selector", inputs: { label: "label", appearance: "appearance", required: "required", showAddButton: "showAddButton", multiple: "multiple" }, providers: [
|
|
788
|
+
{
|
|
789
|
+
provide: NG_VALUE_ACCESSOR,
|
|
790
|
+
useExisting: forwardRef(() => PayeeSelectorComponent),
|
|
791
|
+
multi: true,
|
|
792
|
+
},
|
|
793
|
+
], ngImport: i0, template: "<mat-form-field [appearance]=\"appearance\" class=\"w-100\">\n <mat-label>{{ label }}</mat-label>\n <app-searchable-selector\n apiUrl=\"api/suppliers\"\n titleField=\"company_name\"\n sortBy=\"company_name|asc\"\n [required]=\"required\"\n [(ngModel)]=\"value\"\n #payeeSelector=\"ngModel\"\n name=\"payeeSelector\"\n [add]=\"showAddButton\"\n [itemComponent]=\"SupplierFormComponent\"\n (ngModelChange)=\"onChange($event)\"\n [addConfig]=\"{ width: '600px' }\"\n [ngModelOptions]=\"{ standalone: true }\"\n [multiple]=\"multiple\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"payeeSelector.invalid && payeeSelector.touched\">\n The payee field is required.\n </mat-error>\n</mat-form-field>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], preserveWhitespaces: true });
|
|
794
|
+
}
|
|
795
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorComponent, decorators: [{
|
|
796
|
+
type: Component,
|
|
797
|
+
args: [{ selector: "app-payee-selector", providers: [
|
|
798
|
+
{
|
|
799
|
+
provide: NG_VALUE_ACCESSOR,
|
|
800
|
+
useExisting: forwardRef(() => PayeeSelectorComponent),
|
|
801
|
+
multi: true,
|
|
802
|
+
},
|
|
803
|
+
], template: "<mat-form-field [appearance]=\"appearance\" class=\"w-100\">\n <mat-label>{{ label }}</mat-label>\n <app-searchable-selector\n apiUrl=\"api/suppliers\"\n titleField=\"company_name\"\n sortBy=\"company_name|asc\"\n [required]=\"required\"\n [(ngModel)]=\"value\"\n #payeeSelector=\"ngModel\"\n name=\"payeeSelector\"\n [add]=\"showAddButton\"\n [itemComponent]=\"SupplierFormComponent\"\n (ngModelChange)=\"onChange($event)\"\n [addConfig]=\"{ width: '600px' }\"\n [ngModelOptions]=\"{ standalone: true }\"\n [multiple]=\"multiple\"\n >\n </app-searchable-selector>\n <mat-error *ngIf=\"payeeSelector.invalid && payeeSelector.touched\">\n The payee field is required.\n </mat-error>\n</mat-form-field>\n" }]
|
|
804
|
+
}], propDecorators: { label: [{
|
|
805
|
+
type: Input
|
|
806
|
+
}], appearance: [{
|
|
807
|
+
type: Input
|
|
808
|
+
}], required: [{
|
|
809
|
+
type: Input
|
|
810
|
+
}], showAddButton: [{
|
|
811
|
+
type: Input
|
|
812
|
+
}], multiple: [{
|
|
813
|
+
type: Input
|
|
814
|
+
}] } });
|
|
815
|
+
|
|
816
|
+
class StockReceiptFormComponent extends TechlifyFormComponentInterface {
|
|
817
|
+
formBuilder;
|
|
818
|
+
stockReceiptService;
|
|
819
|
+
alertService;
|
|
820
|
+
dateUtils;
|
|
821
|
+
product;
|
|
822
|
+
stockReceipt;
|
|
823
|
+
saved = new EventEmitter();
|
|
824
|
+
cancelled = new EventEmitter();
|
|
825
|
+
isWorking;
|
|
826
|
+
constructor(formValidatorService, formBuilder, stockReceiptService, alertService, dateUtils) {
|
|
827
|
+
super(formValidatorService);
|
|
828
|
+
this.formBuilder = formBuilder;
|
|
829
|
+
this.stockReceiptService = stockReceiptService;
|
|
830
|
+
this.alertService = alertService;
|
|
831
|
+
this.dateUtils = dateUtils;
|
|
832
|
+
this.errorMessages = {
|
|
833
|
+
date: {
|
|
834
|
+
required: "The date field is required.",
|
|
835
|
+
},
|
|
836
|
+
quantity: {
|
|
837
|
+
required: "The quantity field is required.",
|
|
838
|
+
},
|
|
839
|
+
purchase_price: {
|
|
840
|
+
required: "The purchase price field is required.",
|
|
841
|
+
},
|
|
842
|
+
};
|
|
843
|
+
this.form = this.formBuilder.group({
|
|
844
|
+
id: [""],
|
|
845
|
+
supplier_id: [""],
|
|
846
|
+
date: [new Date(), Validators.required],
|
|
847
|
+
quantity: [1, Validators.required],
|
|
848
|
+
purchase_price: [0, Validators.required],
|
|
849
|
+
amount: [0],
|
|
850
|
+
particulars: [""],
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
ngOnInit() {
|
|
854
|
+
this.form
|
|
855
|
+
.get("quantity")
|
|
856
|
+
?.valueChanges.pipe(debounceTime$1(500))
|
|
857
|
+
.subscribe(() => this.updateTotalAmount());
|
|
858
|
+
this.form
|
|
859
|
+
.get("purchase_price")
|
|
860
|
+
?.valueChanges.pipe(debounceTime$1(500))
|
|
861
|
+
.subscribe(() => this.updateTotalAmount());
|
|
862
|
+
if (this.stockReceipt) {
|
|
863
|
+
let data = { ...this.stockReceipt };
|
|
864
|
+
if (data.date) {
|
|
865
|
+
data.date = new Date(data.date);
|
|
866
|
+
}
|
|
867
|
+
this.form.patchValue(data);
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
// on create for set default quantity and purchase price from last record
|
|
871
|
+
if (this.product?.last_stock_receipt) {
|
|
872
|
+
const { quantity, purchase_price } = this.product.last_stock_receipt;
|
|
873
|
+
this.form.patchValue({
|
|
874
|
+
quantity,
|
|
875
|
+
purchase_price,
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
save() {
|
|
881
|
+
if (this.form.invalid) {
|
|
882
|
+
this.alertService.addAlert("Please check the form for errors", "error");
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
const data = {
|
|
886
|
+
product_id: this.product?.id,
|
|
887
|
+
...this.form.value,
|
|
888
|
+
};
|
|
889
|
+
if (data.date) {
|
|
890
|
+
data.date = this.dateUtils.getYYYYMMDDString(data.date);
|
|
891
|
+
}
|
|
892
|
+
this.isWorking = true;
|
|
893
|
+
let request = this.stockReceiptService.store(data);
|
|
894
|
+
if (this.stockReceipt?.id) {
|
|
895
|
+
request = this.stockReceiptService.update(data);
|
|
896
|
+
}
|
|
897
|
+
request.subscribe({
|
|
898
|
+
next: (response) => {
|
|
899
|
+
this.isWorking = false;
|
|
900
|
+
this.saved.emit(response?.item);
|
|
901
|
+
this.alertService.addAlert("Stock Receipt Saved Successfully!", "success");
|
|
902
|
+
},
|
|
903
|
+
error: () => (this.isWorking = false),
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
updateTotalAmount() {
|
|
907
|
+
const { purchase_price, quantity } = this.form.value;
|
|
908
|
+
const amount = parseFloat(purchase_price) * parseFloat(quantity) || 0;
|
|
909
|
+
this.form.get("amount")?.setValue(amount);
|
|
910
|
+
}
|
|
911
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormComponent, deps: [{ token: i1.FormValidatorService }, { token: i2$2.FormBuilder }, { token: StockReceiptService }, { token: i1.AlertService }, { token: i1.DateUtils }], target: i0.ɵɵFactoryTarget.Component });
|
|
912
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockReceiptFormComponent, selector: "app-stock-receipt-form", inputs: { product: "product", stockReceipt: "stockReceipt" }, outputs: { saved: "saved", cancelled: "cancelled" }, usesInheritance: true, ngImport: i0, template: "<h3 class=\"text-center\">\n {{ stockReceipt?.id ? \"Edit\" : \"Receive\" }} Stock for {{ product?.name }}\n</h3>\n<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column gap-1 justify-content-start\"\n (submit)=\"save()\"\n>\n <app-payee-selector\n label=\"Supplier\"\n formControlName=\"supplier_id\"\n appearance=\"fill\"\n [showAddButton]=\"true\"\n ></app-payee-selector>\n\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input\n matInput\n [matDatepicker]=\"datePicker\"\n formControlName=\"date\"\n (focus)=\"datePicker.open()\"\n />\n <mat-datepicker #datePicker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">\n {{ getErrorMessage(\"date\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput formControlName=\"quantity\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('quantity')\">\n {{ getErrorMessage(\"quantity\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Purchase Price</mat-label>\n <input matInput formControlName=\"purchase_price\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('purchase_price')\">\n {{ getErrorMessage(\"purchase_price\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Total Value</mat-label>\n <input matInput formControlName=\"amount\" readonly type=\"number\" min=\"0\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput formControlName=\"particulars\" rows=\"3\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n >\n Save\n </button>\n <button\n [disabled]=\"isWorking\"\n (click)=\"cancelled.emit()\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</form>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PayeeSelectorComponent, selector: "app-payee-selector", inputs: ["label", "appearance", "required", "showAddButton", "multiple"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], preserveWhitespaces: true });
|
|
913
|
+
}
|
|
914
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormComponent, decorators: [{
|
|
915
|
+
type: Component,
|
|
916
|
+
args: [{ selector: "app-stock-receipt-form", template: "<h3 class=\"text-center\">\n {{ stockReceipt?.id ? \"Edit\" : \"Receive\" }} Stock for {{ product?.name }}\n</h3>\n<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column gap-1 justify-content-start\"\n (submit)=\"save()\"\n>\n <app-payee-selector\n label=\"Supplier\"\n formControlName=\"supplier_id\"\n appearance=\"fill\"\n [showAddButton]=\"true\"\n ></app-payee-selector>\n\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input\n matInput\n [matDatepicker]=\"datePicker\"\n formControlName=\"date\"\n (focus)=\"datePicker.open()\"\n />\n <mat-datepicker #datePicker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">\n {{ getErrorMessage(\"date\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput formControlName=\"quantity\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('quantity')\">\n {{ getErrorMessage(\"quantity\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Purchase Price</mat-label>\n <input matInput formControlName=\"purchase_price\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('purchase_price')\">\n {{ getErrorMessage(\"purchase_price\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Total Value</mat-label>\n <input matInput formControlName=\"amount\" readonly type=\"number\" min=\"0\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput formControlName=\"particulars\" rows=\"3\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n >\n Save\n </button>\n <button\n [disabled]=\"isWorking\"\n (click)=\"cancelled.emit()\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</form>\n" }]
|
|
917
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: StockReceiptService }, { type: i1.AlertService }, { type: i1.DateUtils }], propDecorators: { product: [{
|
|
918
|
+
type: Input
|
|
919
|
+
}], stockReceipt: [{
|
|
920
|
+
type: Input
|
|
921
|
+
}], saved: [{
|
|
922
|
+
type: Output
|
|
923
|
+
}], cancelled: [{
|
|
924
|
+
type: Output
|
|
925
|
+
}] } });
|
|
926
|
+
|
|
927
|
+
class StockReceiptFormButtonComponent {
|
|
928
|
+
matDialog;
|
|
929
|
+
product;
|
|
930
|
+
stockReceipt;
|
|
931
|
+
icon;
|
|
932
|
+
saved = new EventEmitter();
|
|
933
|
+
matDialogRef;
|
|
934
|
+
constructor(matDialog) {
|
|
935
|
+
this.matDialog = matDialog;
|
|
936
|
+
}
|
|
937
|
+
showStockReceiptForm(templateRef) {
|
|
938
|
+
this.matDialogRef = this.matDialog.open(templateRef, { width: "500px" });
|
|
939
|
+
}
|
|
940
|
+
onStockReceiptSaved(item) {
|
|
941
|
+
this.matDialogRef.close();
|
|
942
|
+
this.saved.emit(item);
|
|
943
|
+
}
|
|
944
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormButtonComponent, deps: [{ token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
945
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockReceiptFormButtonComponent, selector: "app-stock-receipt-form-button", inputs: { product: "product", stockReceipt: "stockReceipt", icon: "icon" }, outputs: { saved: "saved" }, ngImport: i0, template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n [class.text-primary]=\"icon\"\n matTooltip=\"Stock Receipt\"\n (click)=\"showStockReceiptForm(stockReceiptFormTemplate)\"\n>\n {{ stockReceipt ? \"edit\" : icon ?? \"download\" }}\n</span>\n\n<ng-template #stockReceiptFormTemplate>\n <app-stock-receipt-form\n mat-dialog-content\n [product]=\"product\"\n [stockReceipt]=\"stockReceipt\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onStockReceiptSaved($event)\"\n ></app-stock-receipt-form>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i2$3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: StockReceiptFormComponent, selector: "app-stock-receipt-form", inputs: ["product", "stockReceipt"], outputs: ["saved", "cancelled"] }], preserveWhitespaces: true });
|
|
946
|
+
}
|
|
947
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormButtonComponent, decorators: [{
|
|
948
|
+
type: Component,
|
|
949
|
+
args: [{ selector: "app-stock-receipt-form-button", template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n [class.text-primary]=\"icon\"\n matTooltip=\"Stock Receipt\"\n (click)=\"showStockReceiptForm(stockReceiptFormTemplate)\"\n>\n {{ stockReceipt ? \"edit\" : icon ?? \"download\" }}\n</span>\n\n<ng-template #stockReceiptFormTemplate>\n <app-stock-receipt-form\n mat-dialog-content\n [product]=\"product\"\n [stockReceipt]=\"stockReceipt\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onStockReceiptSaved($event)\"\n ></app-stock-receipt-form>\n</ng-template>\n" }]
|
|
950
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }], propDecorators: { product: [{
|
|
951
|
+
type: Input
|
|
952
|
+
}], stockReceipt: [{
|
|
953
|
+
type: Input
|
|
954
|
+
}], icon: [{
|
|
955
|
+
type: Input
|
|
956
|
+
}], saved: [{
|
|
957
|
+
type: Output
|
|
958
|
+
}] } });
|
|
959
|
+
|
|
960
|
+
class StockIssuanceService extends TechlifyServiceBaseClass {
|
|
961
|
+
constructor(httpService) {
|
|
962
|
+
super(httpService, "stock-issuances");
|
|
963
|
+
}
|
|
964
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
965
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, providedIn: "root" });
|
|
966
|
+
}
|
|
967
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, decorators: [{
|
|
968
|
+
type: Injectable,
|
|
969
|
+
args: [{
|
|
970
|
+
providedIn: "root",
|
|
971
|
+
}]
|
|
972
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
973
|
+
|
|
974
|
+
class StockIssueFormComponent extends TechlifyFormComponentInterface {
|
|
975
|
+
formBuilder;
|
|
976
|
+
stockIssuanceService;
|
|
977
|
+
alertService;
|
|
978
|
+
dateUtils;
|
|
979
|
+
product;
|
|
980
|
+
stockIssuance;
|
|
981
|
+
issuableType;
|
|
982
|
+
issuableId;
|
|
983
|
+
saved = new EventEmitter();
|
|
984
|
+
cancelled = new EventEmitter();
|
|
985
|
+
isWorking;
|
|
986
|
+
constructor(formValidatorService, formBuilder, stockIssuanceService, alertService, dateUtils) {
|
|
987
|
+
super(formValidatorService);
|
|
988
|
+
this.formBuilder = formBuilder;
|
|
989
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
990
|
+
this.alertService = alertService;
|
|
991
|
+
this.dateUtils = dateUtils;
|
|
992
|
+
this.errorMessages = {
|
|
993
|
+
date: {
|
|
994
|
+
required: "The date field is required.",
|
|
995
|
+
},
|
|
996
|
+
quantity: {
|
|
997
|
+
required: "The quantity field is required.",
|
|
998
|
+
},
|
|
999
|
+
};
|
|
1000
|
+
this.form = this.formBuilder.group({
|
|
1001
|
+
id: [""],
|
|
1002
|
+
product_id: [""],
|
|
1003
|
+
date: [new Date(), Validators.required],
|
|
1004
|
+
quantity: [1, Validators.required],
|
|
1005
|
+
particulars: [""],
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
ngOnInit() {
|
|
1009
|
+
if (this.product) {
|
|
1010
|
+
this.form.get("product_id")?.setValue(this.product?.id);
|
|
1011
|
+
}
|
|
1012
|
+
if (this.stockIssuance) {
|
|
1013
|
+
let data = { ...this.stockIssuance };
|
|
1014
|
+
if (data.date) {
|
|
1015
|
+
data.date = new Date(data.date);
|
|
1016
|
+
}
|
|
1017
|
+
this.form.patchValue(data);
|
|
1018
|
+
}
|
|
1019
|
+
else {
|
|
1020
|
+
// on create for set default quantity from last record
|
|
1021
|
+
if (this.product?.last_stock_issuance) {
|
|
1022
|
+
const { quantity } = this.product.last_stock_issuance;
|
|
1023
|
+
this.form.patchValue({
|
|
1024
|
+
quantity,
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
save() {
|
|
1030
|
+
if (this.form.invalid) {
|
|
1031
|
+
this.alertService.addAlert("Please check the form for errors", "error");
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
const data = {
|
|
1035
|
+
product_id: this.product?.id,
|
|
1036
|
+
...this.form.value,
|
|
1037
|
+
};
|
|
1038
|
+
if (data.date) {
|
|
1039
|
+
data.date = this.dateUtils.getYYYYMMDDString(data.date);
|
|
1040
|
+
}
|
|
1041
|
+
if (this.issuableId && this.issuableType) {
|
|
1042
|
+
data.issuable_type = this.issuableType;
|
|
1043
|
+
data.issuable_id = this.issuableId;
|
|
1044
|
+
}
|
|
1045
|
+
this.isWorking = true;
|
|
1046
|
+
let request = this.stockIssuanceService.store(data);
|
|
1047
|
+
if (this.stockIssuance?.id) {
|
|
1048
|
+
request = this.stockIssuanceService.update(data);
|
|
1049
|
+
}
|
|
1050
|
+
request.subscribe({
|
|
1051
|
+
next: (response) => {
|
|
1052
|
+
this.isWorking = false;
|
|
1053
|
+
this.saved.emit(response?.item);
|
|
1054
|
+
this.alertService.addAlert("Stock Issuance Saved Successfully!", "success");
|
|
1055
|
+
},
|
|
1056
|
+
error: () => (this.isWorking = false),
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
onProductChange(product) {
|
|
1060
|
+
this.product = product;
|
|
1061
|
+
}
|
|
1062
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormComponent, deps: [{ token: i1.FormValidatorService }, { token: i2$2.FormBuilder }, { token: StockIssuanceService }, { token: i1.AlertService }, { token: i1.DateUtils }], target: i0.ɵɵFactoryTarget.Component });
|
|
1063
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockIssueFormComponent, selector: "app-stock-issue-form", inputs: { product: "product", stockIssuance: "stockIssuance", issuableType: "issuableType", issuableId: "issuableId" }, outputs: { saved: "saved", cancelled: "cancelled" }, usesInheritance: true, ngImport: i0, template: "<h3 class=\"text-center\">\n {{ stockIssuance?.id ? \"Edit\" : \"Issue\" }} Stock for {{ product?.name }}\n</h3>\n<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column gap-1 justify-content-start\"\n (submit)=\"save()\"\n>\n <mat-form-field *ngIf=\"!product\">\n <mat-label>Product</mat-label>\n <app-searchable-selector\n formControlName=\"product_id\"\n apiUrl=\"api/products\"\n titleField=\"name\"\n (selectedValueChange)=\"onProductChange($event)\"\n ></app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input\n matInput\n [matDatepicker]=\"datePicker\"\n formControlName=\"date\"\n (focus)=\"datePicker.open()\"\n />\n <mat-datepicker #datePicker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">\n {{ getErrorMessage(\"date\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput formControlName=\"quantity\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('quantity')\">\n {{ getErrorMessage(\"quantity\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput formControlName=\"particulars\" rows=\"3\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n >\n Save\n </button>\n <button\n [disabled]=\"isWorking\"\n (click)=\"cancelled.emit()\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</form>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }], preserveWhitespaces: true });
|
|
1064
|
+
}
|
|
1065
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormComponent, decorators: [{
|
|
1066
|
+
type: Component,
|
|
1067
|
+
args: [{ selector: "app-stock-issue-form", template: "<h3 class=\"text-center\">\n {{ stockIssuance?.id ? \"Edit\" : \"Issue\" }} Stock for {{ product?.name }}\n</h3>\n<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column gap-1 justify-content-start\"\n (submit)=\"save()\"\n>\n <mat-form-field *ngIf=\"!product\">\n <mat-label>Product</mat-label>\n <app-searchable-selector\n formControlName=\"product_id\"\n apiUrl=\"api/products\"\n titleField=\"name\"\n (selectedValueChange)=\"onProductChange($event)\"\n ></app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input\n matInput\n [matDatepicker]=\"datePicker\"\n formControlName=\"date\"\n (focus)=\"datePicker.open()\"\n />\n <mat-datepicker #datePicker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">\n {{ getErrorMessage(\"date\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput formControlName=\"quantity\" type=\"number\" min=\"0\" />\n <mat-error *ngIf=\"isFieldValid('quantity')\">\n {{ getErrorMessage(\"quantity\") }}\n </mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput formControlName=\"particulars\" rows=\"3\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button\n [disabled]=\"isWorking\"\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n >\n Save\n </button>\n <button\n [disabled]=\"isWorking\"\n (click)=\"cancelled.emit()\"\n mat-flat-button\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</form>\n" }]
|
|
1068
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: StockIssuanceService }, { type: i1.AlertService }, { type: i1.DateUtils }], propDecorators: { product: [{
|
|
1069
|
+
type: Input
|
|
1070
|
+
}], stockIssuance: [{
|
|
1071
|
+
type: Input
|
|
1072
|
+
}], issuableType: [{
|
|
1073
|
+
type: Input
|
|
1074
|
+
}], issuableId: [{
|
|
1075
|
+
type: Input
|
|
1076
|
+
}], saved: [{
|
|
1077
|
+
type: Output
|
|
1078
|
+
}], cancelled: [{
|
|
1079
|
+
type: Output
|
|
1080
|
+
}] } });
|
|
1081
|
+
|
|
1082
|
+
class StockIssueFormButtonComponent {
|
|
1083
|
+
matDialog;
|
|
1084
|
+
product;
|
|
1085
|
+
stockIssuance;
|
|
1086
|
+
icon;
|
|
1087
|
+
issuableType;
|
|
1088
|
+
issuableId;
|
|
1089
|
+
saved = new EventEmitter();
|
|
1090
|
+
matDialogRef;
|
|
1091
|
+
constructor(matDialog) {
|
|
1092
|
+
this.matDialog = matDialog;
|
|
1093
|
+
}
|
|
1094
|
+
showStockIssuanceForm(templateRef) {
|
|
1095
|
+
this.matDialogRef = this.matDialog.open(templateRef, { width: "500px" });
|
|
1096
|
+
}
|
|
1097
|
+
onStockIssuanceSaved(item) {
|
|
1098
|
+
this.matDialogRef.close();
|
|
1099
|
+
this.saved.emit(item);
|
|
1100
|
+
}
|
|
1101
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormButtonComponent, deps: [{ token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
1102
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockIssueFormButtonComponent, selector: "app-stock-issue-form-button", inputs: { product: "product", stockIssuance: "stockIssuance", icon: "icon", issuableType: "issuableType", issuableId: "issuableId" }, outputs: { saved: "saved" }, ngImport: i0, template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n [class.text-primary]=\"icon\"\n matTooltip=\"Stock Issuance\"\n (click)=\"showStockIssuanceForm(stockIssuanceFormTemplate)\"\n>\n {{ stockIssuance ? \"edit\" : icon ?? \"upload\" }}\n</span>\n\n<ng-template #stockIssuanceFormTemplate>\n <app-stock-issue-form\n mat-dialog-content\n [product]=\"product\"\n [stockIssuance]=\"stockIssuance\"\n [issuableType]=\"issuableType\"\n [issuableId]=\"issuableId\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onStockIssuanceSaved($event)\"\n ></app-stock-issue-form>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i2$3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: StockIssueFormComponent, selector: "app-stock-issue-form", inputs: ["product", "stockIssuance", "issuableType", "issuableId"], outputs: ["saved", "cancelled"] }], preserveWhitespaces: true });
|
|
1103
|
+
}
|
|
1104
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormButtonComponent, decorators: [{
|
|
1105
|
+
type: Component,
|
|
1106
|
+
args: [{ selector: "app-stock-issue-form-button", template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n [class.text-primary]=\"icon\"\n matTooltip=\"Stock Issuance\"\n (click)=\"showStockIssuanceForm(stockIssuanceFormTemplate)\"\n>\n {{ stockIssuance ? \"edit\" : icon ?? \"upload\" }}\n</span>\n\n<ng-template #stockIssuanceFormTemplate>\n <app-stock-issue-form\n mat-dialog-content\n [product]=\"product\"\n [stockIssuance]=\"stockIssuance\"\n [issuableType]=\"issuableType\"\n [issuableId]=\"issuableId\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onStockIssuanceSaved($event)\"\n ></app-stock-issue-form>\n</ng-template>\n" }]
|
|
1107
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }], propDecorators: { product: [{
|
|
1108
|
+
type: Input
|
|
1109
|
+
}], stockIssuance: [{
|
|
1110
|
+
type: Input
|
|
1111
|
+
}], icon: [{
|
|
1112
|
+
type: Input
|
|
1113
|
+
}], issuableType: [{
|
|
1114
|
+
type: Input
|
|
1115
|
+
}], issuableId: [{
|
|
1116
|
+
type: Input
|
|
1117
|
+
}], saved: [{
|
|
1118
|
+
type: Output
|
|
1119
|
+
}] } });
|
|
1120
|
+
|
|
1121
|
+
class ProductFormButtonComponent {
|
|
1122
|
+
matDialog;
|
|
1123
|
+
productFormService;
|
|
1124
|
+
product;
|
|
1125
|
+
saved = new EventEmitter();
|
|
1126
|
+
constructor(matDialog, productFormService) {
|
|
1127
|
+
this.matDialog = matDialog;
|
|
1128
|
+
this.productFormService = productFormService;
|
|
1129
|
+
}
|
|
1130
|
+
showForm(templateRef) {
|
|
1131
|
+
this.matDialog.open(templateRef, { width: "600px" });
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Handle on product saved event.
|
|
1135
|
+
*
|
|
1136
|
+
* @param product
|
|
1137
|
+
*/
|
|
1138
|
+
onProductSaved(product) {
|
|
1139
|
+
this.saved.emit(product);
|
|
1140
|
+
this.matDialog?.closeAll();
|
|
1141
|
+
this.productFormService.listUpdated(true);
|
|
1142
|
+
}
|
|
1143
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1144
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: { product: "product" }, outputs: { saved: "saved" }, ngImport: i0, template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n [class.text-secondary]=\"product\"\n (click)=\"showForm(addProductForm)\"\n>\n {{ product ? \"edit\" : \"add\" }}\n</mat-icon>\n\n<ng-template #addProductForm>\n <app-product-form\n [product]=\"product\"\n mat-dialog-content\n (saved)=\"onProductSaved($event)\"\n (cancelled)=\"matDialog.closeAll()\"\n ></app-product-form>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ProductFormComponent, selector: "app-product-form", inputs: ["product", "displayedFormFields", "displayedFormSections"], outputs: ["saved", "cancelled"] }], preserveWhitespaces: true });
|
|
1145
|
+
}
|
|
1146
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormButtonComponent, decorators: [{
|
|
1147
|
+
type: Component,
|
|
1148
|
+
args: [{ selector: "app-product-form-button", template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n [class.text-secondary]=\"product\"\n (click)=\"showForm(addProductForm)\"\n>\n {{ product ? \"edit\" : \"add\" }}\n</mat-icon>\n\n<ng-template #addProductForm>\n <app-product-form\n [product]=\"product\"\n mat-dialog-content\n (saved)=\"onProductSaved($event)\"\n (cancelled)=\"matDialog.closeAll()\"\n ></app-product-form>\n</ng-template>\n" }]
|
|
1149
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductFormService }], propDecorators: { product: [{
|
|
1150
|
+
type: Input
|
|
1151
|
+
}], saved: [{
|
|
1152
|
+
type: Output
|
|
1153
|
+
}] } });
|
|
1154
|
+
|
|
1155
|
+
let ProductListComponent = class ProductListComponent {
|
|
1156
|
+
fb;
|
|
1157
|
+
dialog;
|
|
1158
|
+
activatedRoute;
|
|
1159
|
+
productService;
|
|
1160
|
+
requestHelperService;
|
|
1161
|
+
productFormService;
|
|
1162
|
+
filterForm;
|
|
1163
|
+
lastPage;
|
|
1164
|
+
page = 1;
|
|
1165
|
+
perPage = 25;
|
|
1166
|
+
totalItems = 0;
|
|
1167
|
+
currentPage = 1;
|
|
1168
|
+
num_items = 25;
|
|
1169
|
+
routeFilters;
|
|
1170
|
+
products = [];
|
|
1171
|
+
dataSource = new MatTableDataSource();
|
|
1172
|
+
isLoading = false;
|
|
1173
|
+
columnConfig = [
|
|
1174
|
+
{ label: '#', def: '#', isSelected: true, isEditable: true },
|
|
1175
|
+
{ label: 'Name', def: 'name', isSelected: true, isEditable: true },
|
|
1176
|
+
{ label: 'SKU', def: 'sku', isSelected: true, isEditable: true },
|
|
1177
|
+
{ label: 'Categories', def: 'categories', isSelected: true, isEditable: true },
|
|
1178
|
+
{ label: 'Initial Quantity', def: 'initial_quantity', isSelected: true, isEditable: true },
|
|
1179
|
+
{ label: 'Reorder Point', def: 'reorder_point', isSelected: true, isEditable: true },
|
|
1180
|
+
{ label: 'Stock Receipts', def: 'stock_receipts', isSelected: true, isEditable: true },
|
|
1181
|
+
{ label: 'Stock Issuances', def: 'stock_issuances', isSelected: true, isEditable: true },
|
|
1182
|
+
{ label: 'On Hand', def: 'on_hand', isSelected: true, isEditable: true },
|
|
1183
|
+
{ label: 'Sale Price', def: 'sale_price', isSelected: true, isEditable: true },
|
|
1184
|
+
{ label: 'Income Account', def: 'income_account', isSelected: false, isEditable: true },
|
|
1185
|
+
{ label: 'Expense Account', def: 'expense_account', isSelected: false, isEditable: true },
|
|
1186
|
+
{ label: 'Creator', def: 'creator', isSelected: false, isEditable: true },
|
|
1187
|
+
{ label: 'Actions', def: 'Actions', isSelected: true, isEditable: true },
|
|
1188
|
+
];
|
|
1189
|
+
selectedColumns = this.columnConfig.filter(col => col.isSelected);
|
|
1190
|
+
get displayedColumns() {
|
|
1191
|
+
return this.selectedColumns.map(col => col.def);
|
|
1192
|
+
}
|
|
1193
|
+
importId;
|
|
1194
|
+
constructor(fb, dialog, activatedRoute, productService, requestHelperService, productFormService) {
|
|
1195
|
+
this.fb = fb;
|
|
1196
|
+
this.dialog = dialog;
|
|
1197
|
+
this.activatedRoute = activatedRoute;
|
|
1198
|
+
this.productService = productService;
|
|
1199
|
+
this.requestHelperService = requestHelperService;
|
|
1200
|
+
this.productFormService = productFormService;
|
|
1201
|
+
this.filterForm = this.fb.group({
|
|
1202
|
+
search: [""],
|
|
1203
|
+
category_ids: [""],
|
|
1204
|
+
type_ids: [""],
|
|
1205
|
+
income_account_ids: [""],
|
|
1206
|
+
expense_account_ids: [""],
|
|
1207
|
+
sort_by: [""],
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
ngOnInit() {
|
|
1211
|
+
if (this.activatedRoute.snapshot.params?.["import_id"]) {
|
|
1212
|
+
this.importId = parseInt(this.activatedRoute.snapshot.params?.["import_id"]);
|
|
1213
|
+
}
|
|
1214
|
+
// update form with URL query params
|
|
1215
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
1216
|
+
type_ids: { multiple: true },
|
|
1217
|
+
category_ids: { multiple: true },
|
|
1218
|
+
income_account_ids: { multiple: true },
|
|
1219
|
+
expense_account_ids: { multiple: true },
|
|
1220
|
+
});
|
|
1221
|
+
// Update URL query params on filter change
|
|
1222
|
+
this.filterForm.valueChanges.pipe(debounceTime(800)).subscribe(() => {
|
|
1223
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData({
|
|
1224
|
+
...this.filterForm.value,
|
|
1225
|
+
}));
|
|
1226
|
+
});
|
|
1227
|
+
// fetch task on params change
|
|
1228
|
+
this.activatedRoute.queryParams
|
|
1229
|
+
.pipe(debounceTime(800))
|
|
1230
|
+
.subscribe(() => this.reload());
|
|
1231
|
+
// listen form product add or update event and reload.
|
|
1232
|
+
this.productFormService.isListUpdated().subscribe((val) => {
|
|
1233
|
+
if (val && !this.isLoading) {
|
|
1234
|
+
this.reload();
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
loadData() {
|
|
1239
|
+
let params = {
|
|
1240
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1241
|
+
};
|
|
1242
|
+
params.page = this.page;
|
|
1243
|
+
params.perPage = this.perPage;
|
|
1244
|
+
params.num_items = this.num_items + "|" + this.currentPage;
|
|
1245
|
+
params.with = "categories,lastStockReceipt,lastStockIssuance,creator";
|
|
1246
|
+
if (this.importId) {
|
|
1247
|
+
params.import_id = this.importId;
|
|
1248
|
+
}
|
|
1249
|
+
this.isLoading = true;
|
|
1250
|
+
this.productService.index(params).subscribe({
|
|
1251
|
+
next: (res) => {
|
|
1252
|
+
this.isLoading = false;
|
|
1253
|
+
this.dataSource = new MatTableDataSource(this.dataSource.data.concat(res?.data));
|
|
1254
|
+
this.totalItems = res.total;
|
|
1255
|
+
// stop reloading data once data loaded.
|
|
1256
|
+
this.productFormService.listUpdated(false);
|
|
1257
|
+
},
|
|
1258
|
+
error: () => (this.isLoading = false),
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
reload() {
|
|
1262
|
+
if (this.isLoading)
|
|
1263
|
+
return;
|
|
1264
|
+
this.dataSource = new MatTableDataSource();
|
|
1265
|
+
this.currentPage = 1;
|
|
1266
|
+
this.loadData();
|
|
1267
|
+
}
|
|
1268
|
+
modifyProduct(model) {
|
|
1269
|
+
const dialogRef = this.dialog.open(ProductFormComponent, {
|
|
1270
|
+
width: "600px",
|
|
1271
|
+
data: {
|
|
1272
|
+
details: model,
|
|
1273
|
+
},
|
|
1274
|
+
});
|
|
1275
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
1276
|
+
if (result) {
|
|
1277
|
+
this.reload();
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
assignFilter(column, direction) {
|
|
1282
|
+
if (column) {
|
|
1283
|
+
return this.filterForm.get("sort_by")?.setValue(column + "|" + direction);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
sortColumn(event) {
|
|
1287
|
+
var direction = event.direction.toString().toUpperCase();
|
|
1288
|
+
this.assignFilter(event.active, direction);
|
|
1289
|
+
}
|
|
1290
|
+
onScroll() {
|
|
1291
|
+
if (this.totalItems > this.dataSource.data.length) {
|
|
1292
|
+
this.currentPage += 1;
|
|
1293
|
+
this.loadData();
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductListComponent, deps: [{ token: i2$2.FormBuilder }, { token: i1$1.MatDialog }, { token: i2.ActivatedRoute }, { token: ProductService }, { token: i1.RequestHelperService }, { token: ProductFormService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1297
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductListComponent, selector: "app-product-list", ngImport: i0, template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form\n [formGroup]=\"filterForm\"\n class=\"d-flex justify-content-between align-items-center gap-2\"\n >\n <div class=\"d-flex justify-content-center align-items-center gap-2\">\n <h3 class=\"mb-0\">Products</h3>\n <app-product-form-button class=\"mt-2\"></app-product-form-button>\n <span matTooltip=\"Import\" routerLink=\"import\" class=\"cursor-pointer mt-1 material-symbols-outlined\">\n file_save\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mt-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-form-field style=\"width: 120px\">\n <input matInput placeholder=\"Product\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"income_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"expense_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n aria-describedby=\"Products List\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column gap-1\">\n <a class=\"text-decoration-none text-dark\" [routerLink]=\"[element?.id, 'view']\">{{ element.name }}</a>\n <small class=\"text-secondary\" *ngIf=\"element.type\">{{ element.type?.title }}</small>\n </div>\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.sku }}</td>\n </ng-container>\n\n <!-- Initial Quantity Column -->\n <ng-container matColumnDef=\"initial_quantity\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n Initial Quantity\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element.initial_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.initial_quantity_date\">\n on {{ element?.initial_quantity_date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Receipts Column -->\n <ng-container matColumnDef=\"stock_receipts\">\n <th mat-header-cell mat-sort-header=\"stock_receipts_sum_quantity\" *matHeaderCellDef>\n Stock Receipts\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_receipts_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n last added on {{ element?.last_stock_receipt?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Issuances Column -->\n <ng-container matColumnDef=\"stock_issuances\">\n <th mat-header-cell mat-sort-header=\"stock_issuances_sum_quantity\" *matHeaderCellDef>\n Stock Issuances\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_issuances_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_issuance\">\n last issued on {{ element?.last_stock_issuance?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"on_hand\">\n <th mat-header-cell mat-sort-header=\"stock_balance\" *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"reorder_point\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Selling Price Column -->\n <ng-container matColumnDef=\"sale_price\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Selling Price</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.sale_price | currency }}\n </td>\n </ng-container>\n\n <!-- Income Account Column -->\n <ng-container matColumnDef=\"income_account\">\n <th mat-header-cell *matHeaderCellDef>Income Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.income_account?.title }}\n </td>\n </ng-container>\n\n <!-- Expense Account Column -->\n <ng-container matColumnDef=\"expense_account\">\n <th mat-header-cell *matHeaderCellDef>Expense Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.expense_account?.title }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <app-product-form-button\n [product]=\"element\"\n ></app-product-form-button>\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"[element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "component", type: StockReceiptFormButtonComponent, selector: "app-stock-receipt-form-button", inputs: ["product", "stockReceipt", "icon"], outputs: ["saved"] }, { kind: "component", type: StockIssueFormButtonComponent, selector: "app-stock-issue-form-button", inputs: ["product", "stockIssuance", "icon", "issuableType", "issuableId"], outputs: ["saved"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i2$3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: i10.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1.ColumnSelectorComponent, selector: "app-column-selector", inputs: ["label", "mode", "columnConfigs", "selectedColumns"], outputs: ["selectedColumnsChange", "displayedColumnsChange"] }, { kind: "component", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1298
|
+
};
|
|
1299
|
+
ProductListComponent = __decorate([
|
|
1300
|
+
UntilDestroy()
|
|
1301
|
+
], ProductListComponent);
|
|
1302
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductListComponent, decorators: [{
|
|
1303
|
+
type: Component,
|
|
1304
|
+
args: [{ selector: "app-product-list", template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form\n [formGroup]=\"filterForm\"\n class=\"d-flex justify-content-between align-items-center gap-2\"\n >\n <div class=\"d-flex justify-content-center align-items-center gap-2\">\n <h3 class=\"mb-0\">Products</h3>\n <app-product-form-button class=\"mt-2\"></app-product-form-button>\n <span matTooltip=\"Import\" routerLink=\"import\" class=\"cursor-pointer mt-1 material-symbols-outlined\">\n file_save\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mt-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-form-field style=\"width: 120px\">\n <input matInput placeholder=\"Product\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field style=\"width: 120px\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-types\"\n formControlName=\"type_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Income Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"income_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n <!-- <mat-form-field style=\"width: 150px\">-->\n <!-- <mat-label>Expense Account</mat-label>-->\n <!-- <app-searchable-selector-->\n <!-- apiUrl=\"api/accounts\"-->\n <!-- formControlName=\"expense_account_ids\"-->\n <!-- titleField=\"title\"-->\n <!-- [multiple]=\"true\"-->\n <!-- >-->\n <!-- </app-searchable-selector>-->\n <!-- </mat-form-field>-->\n </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"dataSource\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n [fromRoot]=\"true\"\n matSort\n (matSortChange)=\"sortColumn($event)\"\n matSortDisableClear=\"true\"\n aria-describedby=\"Products List\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Name</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column gap-1\">\n <a class=\"text-decoration-none text-dark\" [routerLink]=\"[element?.id, 'view']\">{{ element.name }}</a>\n <small class=\"text-secondary\" *ngIf=\"element.type\">{{ element.type?.title }}</small>\n </div>\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element.sku }}</td>\n </ng-container>\n\n <!-- Initial Quantity Column -->\n <ng-container matColumnDef=\"initial_quantity\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>\n Initial Quantity\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element.initial_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.initial_quantity_date\">\n on {{ element?.initial_quantity_date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Receipts Column -->\n <ng-container matColumnDef=\"stock_receipts\">\n <th mat-header-cell mat-sort-header=\"stock_receipts_sum_quantity\" *matHeaderCellDef>\n Stock Receipts\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_receipts_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n last added on {{ element?.last_stock_receipt?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- Stock Issuances Column -->\n <ng-container matColumnDef=\"stock_issuances\">\n <th mat-header-cell mat-sort-header=\"stock_issuances_sum_quantity\" *matHeaderCellDef>\n Stock Issuances\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.stock_issuances_sum_quantity }}</p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_issuance\">\n last issued on {{ element?.last_stock_issuance?.date | date }}\n </small>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"on_hand\">\n <th mat-header-cell mat-sort-header=\"stock_balance\" *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"reorder_point\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Reorder Point</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Selling Price Column -->\n <ng-container matColumnDef=\"sale_price\">\n <th mat-header-cell mat-sort-header *matHeaderCellDef>Selling Price</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element.sale_price | currency }}\n </td>\n </ng-container>\n\n <!-- Income Account Column -->\n <ng-container matColumnDef=\"income_account\">\n <th mat-header-cell *matHeaderCellDef>Income Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.income_account?.title }}\n </td>\n </ng-container>\n\n <!-- Expense Account Column -->\n <ng-container matColumnDef=\"expense_account\">\n <th mat-header-cell *matHeaderCellDef>Expense Account</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.expense_account?.title }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <app-product-form-button\n [product]=\"element\"\n ></app-product-form-button>\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"[element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n <tr\n mat-header-row\n *matHeaderRowDef=\"displayedColumns; sticky: true\"\n ></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
|
|
1305
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1$1.MatDialog }, { type: i2.ActivatedRoute }, { type: ProductService }, { type: i1.RequestHelperService }, { type: ProductFormService }] });
|
|
1306
|
+
|
|
1307
|
+
class ProductNavBarComponent {
|
|
1308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1309
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductNavBarComponent, selector: "app-product-nav-bar", ngImport: i0, template: "<div>\n <router-outlet></router-outlet>\n</div>\n", dependencies: [{ kind: "directive", type: i2.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], preserveWhitespaces: true });
|
|
1310
|
+
}
|
|
1311
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, decorators: [{
|
|
1312
|
+
type: Component,
|
|
1313
|
+
args: [{ selector: "app-product-nav-bar", template: "<div>\n <router-outlet></router-outlet>\n</div>\n" }]
|
|
1314
|
+
}] });
|
|
1315
|
+
|
|
1316
|
+
class TechlifyFilterComponent {
|
|
1317
|
+
requestHelperService;
|
|
1318
|
+
activatedRoute;
|
|
1319
|
+
filterForm;
|
|
1320
|
+
filterConfig;
|
|
1321
|
+
filterUpdated = new EventEmitter();
|
|
1322
|
+
constructor(requestHelperService, activatedRoute) {
|
|
1323
|
+
this.requestHelperService = requestHelperService;
|
|
1324
|
+
this.activatedRoute = activatedRoute;
|
|
1325
|
+
}
|
|
1326
|
+
ngOnInit() {
|
|
1327
|
+
// listen for filter changes
|
|
1328
|
+
this.filterForm.valueChanges.subscribe({
|
|
1329
|
+
next: (value) => {
|
|
1330
|
+
const params = this.requestHelperService.convertToFormData(value);
|
|
1331
|
+
this.requestHelperService.updateQueryParams(params);
|
|
1332
|
+
},
|
|
1333
|
+
});
|
|
1334
|
+
// update form with query params
|
|
1335
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
1336
|
+
duration: { number: true },
|
|
1337
|
+
expiry_duration: { number: true },
|
|
1338
|
+
payment_method_ids: { multiple: true },
|
|
1339
|
+
payment_account_ids: { multiple: true },
|
|
1340
|
+
project_ids: { multiple: true },
|
|
1341
|
+
invoice_status_ids: { multiple: true },
|
|
1342
|
+
customer_ids: { multiple: true },
|
|
1343
|
+
cost_category_ids: { multiple: true },
|
|
1344
|
+
team_member_ids: { multiple: true },
|
|
1345
|
+
task_status_ids: { multiple: true },
|
|
1346
|
+
asset_account_ids: { multiple: true },
|
|
1347
|
+
depreciation_method_ids: { multiple: true },
|
|
1348
|
+
depreciation_expense_account_ids: { multiple: true },
|
|
1349
|
+
fixed_asset_type_ids: { multiple: true },
|
|
1350
|
+
fixed_asset_document_type_ids: { multiple: true },
|
|
1351
|
+
service_center_ids: { multiple: true },
|
|
1352
|
+
fixed_asset_maintenance_status_ids: { multiple: true },
|
|
1353
|
+
milestone_ids: { multiple: true },
|
|
1354
|
+
product_ids: { multiple: true },
|
|
1355
|
+
supplier_ids: { multiple: true },
|
|
1356
|
+
measure_ids: { multiple: true },
|
|
1357
|
+
type_ids: { multiple: true },
|
|
1358
|
+
fixed_asset_ids: { multiple: true },
|
|
1359
|
+
});
|
|
1360
|
+
// listen for route change
|
|
1361
|
+
this.activatedRoute.queryParams
|
|
1362
|
+
.pipe(debounceTime$1(800), distinctUntilChanged())
|
|
1363
|
+
.subscribe((val) => {
|
|
1364
|
+
this.filterUpdated.emit(this.filterForm.value);
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
resetField(field) {
|
|
1368
|
+
this.filterForm.get(field)?.setValue("");
|
|
1369
|
+
}
|
|
1370
|
+
onDurationChange(timelineValue) {
|
|
1371
|
+
let { date_to, date_from } = timelineValue;
|
|
1372
|
+
this.filterForm.patchValue({
|
|
1373
|
+
date_from: date_from ? moment(date_from).format("YYYY-MM-DD") : "",
|
|
1374
|
+
date_to: date_to ? moment(date_to).format("YYYY-MM-DD") : "",
|
|
1375
|
+
}, { emitEvent: false });
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Update expiry date from and date to on value change.
|
|
1379
|
+
*
|
|
1380
|
+
* @param timelineValue
|
|
1381
|
+
*/
|
|
1382
|
+
onExpiryDurationChange(timelineValue) {
|
|
1383
|
+
let { date_to, date_from } = timelineValue;
|
|
1384
|
+
this.filterForm.patchValue({
|
|
1385
|
+
expiry_date_from: date_from ? moment(date_from).format("YYYY-MM-DD") : "",
|
|
1386
|
+
expiry_date_to: date_to ? moment(date_to).format("YYYY-MM-DD") : "",
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Get the attribute value for the field.
|
|
1391
|
+
*
|
|
1392
|
+
* @param attribute
|
|
1393
|
+
* @param field
|
|
1394
|
+
*/
|
|
1395
|
+
getFilterConfig(attribute, field) {
|
|
1396
|
+
if (!this.filterConfig)
|
|
1397
|
+
return "";
|
|
1398
|
+
// Check if the field and attribute exist in the filter config, return the value or an empty string
|
|
1399
|
+
return this.filterConfig[field] &&
|
|
1400
|
+
this.filterConfig[field][attribute] !== undefined
|
|
1401
|
+
? this.filterConfig[field][attribute]
|
|
1402
|
+
: "";
|
|
1403
|
+
}
|
|
1404
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterComponent, deps: [{ token: i1.RequestHelperService }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
|
|
1405
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TechlifyFilterComponent, selector: "app-techlify-filter", inputs: { filterForm: "filterForm", filterConfig: "filterConfig" }, outputs: { filterUpdated: "filterUpdated" }, ngImport: i0, template: "<form\n [formGroup]=\"filterForm\"\n fxLayout\n fxLayoutAlign=\"start center\"\n fxLayoutGap=\"10px\"\n>\n <mat-form-field\n *ngIf=\"filterForm.get('search')\"\n [appearance]=\"getFilterConfig('appearance', 'search')\"\n >\n <mat-label>Search</mat-label>\n <input\n formControlName=\"search\"\n matInput\n [placeholder]=\"getFilterConfig('placeholder', 'search')\"\n />\n <button\n *ngIf=\"filterForm.value?.search\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('search')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <app-timeline-filter\n *ngIf=\"filterForm?.get('duration')\"\n appearance=\"fill\"\n [labelText]=\"getFilterConfig('label', 'duration')\"\n [appearance]=\"getFilterConfig('appearance', 'duration')\"\n formControlName=\"duration\"\n (selectionChange)=\"onDurationChange($event)\"\n [showClearButton]=\"true\"\n [dateFrom]=\"filterForm.value?.date_from\"\n [dateTo]=\"filterForm.value?.date_to\"\n ></app-timeline-filter>\n\n <mat-form-field *ngIf=\"filterForm.get('payment_method_ids')\">\n <mat-label>Payment Method</mat-label>\n <app-searchable-selector\n formControlName=\"payment_method_ids\"\n apiUrl=\"api/payment-methods\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.payment_method_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('payment_method_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngIf=\"filterForm.get('payment_account_ids')\">\n <mat-form-field *ngxPermissionsOnly=\"['accountingcommon_account.read']\">\n <mat-label>{{\n getFilterConfig(\"label\", \"payment_account_ids\") || \"Payment Account\"\n }}</mat-label>\n <app-searchable-selector\n formControlName=\"payment_account_ids\"\n [apiUrl]=\"\n getFilterConfig('apiUrl', 'payment_account_ids') || 'api/accounts'\n \"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.payment_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('payment_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <mat-form-field *ngIf=\"filterForm.get('invoice_status_ids')\">\n <mat-label>Invoice Status</mat-label>\n <app-searchable-selector\n formControlName=\"invoice_status_ids\"\n apiUrl=\"api/invoice-statuses\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.invoice_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('invoice_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngIf=\"filterForm.get('customer_ids')\">\n <mat-form-field *ngxPermissionsOnly=\"['customer_read']\">\n <mat-label>Customer</mat-label>\n <app-searchable-selector\n formControlName=\"customer_ids\"\n titleField=\"name\"\n apiUrl=\"api/customers\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.customer_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('customer_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <ng-container\n *ngIf=\"\n filterForm.get('project_ids') &&\n getFilterConfig('disabled', 'project_ids') === false\n \"\n >\n <mat-form-field *ngxPermissionsOnly=\"['project.read']\">\n <mat-label>Project</mat-label>\n <app-searchable-selector\n formControlName=\"project_ids\"\n apiUrl=\"api/projects\"\n titleField=\"project_name\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.project_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('project_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <mat-form-field *ngIf=\"filterForm.get('product_ids')\">\n <mat-label>Product</mat-label>\n <app-searchable-selector\n formControlName=\"product_ids\"\n apiUrl=\"api/products\"\n titleField=\"name\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.product_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('product_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('measure_ids')\">\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n formControlName=\"measure_ids\"\n apiUrl=\"api/product-measures\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.measure_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('measure_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngxPermissionsOnly=\"['supplier.read']\">\n <mat-form-field\n *ngIf=\"filterForm.get('supplier_ids')\"\n [appearance]=\"getFilterConfig('appearance', 'supplier_ids')\"\n >\n <mat-label>Supplier</mat-label>\n <app-searchable-selector\n formControlName=\"supplier_ids\"\n titleField=\"company_name\"\n apiUrl=\"api/suppliers\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.supplier_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('supplier_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <app-timeline-filter\n appearance=\"fill\"\n [labelText]=\"getFilterConfig('label', 'expiry_duration')\"\n *ngIf=\"filterForm?.get('expiry_duration')\"\n formControlName=\"expiry_duration\"\n (selectionChange)=\"onExpiryDurationChange($event)\"\n [showClearButton]=\"true\"\n [dateFrom]=\"filterForm.value?.expiry_date_from\"\n [dateTo]=\"filterForm.value?.expiry_date_to\"\n ></app-timeline-filter>\n\n <mat-form-field\n *ngIf=\"filterForm.get('cost_category_ids')\"\n style=\"width: 150px\"\n >\n <mat-label>Cost Category</mat-label>\n <app-searchable-selector\n formControlName=\"cost_category_ids\"\n apiUrl=\"api/cost-code-categories\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.cost_category_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('cost_category_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('milestone_ids')\" style=\"width: 150px\">\n <mat-label>Milestone</mat-label>\n <app-searchable-selector\n formControlName=\"milestone_ids\"\n apiUrl=\"api/milestones\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.milestone_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('milestone_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('team_member_ids')\">\n <mat-label>Assignee</mat-label>\n <app-searchable-selector\n apiUrl=\"api/persons\"\n formControlName=\"team_member_ids\"\n titleField=\"name\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.team_member_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('team_member_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_type_ids')\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n formControlName=\"fixed_asset_type_ids\"\n apiUrl=\"api/accounting-plus/fixed-asset-types\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_type_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_type_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_document_type_ids')\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n formControlName=\"fixed_asset_document_type_ids\"\n apiUrl=\"api/accounting-plus/fixed-asset-document-types\"\n [multiple]=\"true\"\n [enableSearch]=\"\n getFilterConfig('enableSearch', 'fixed_asset_document_type_ids')\n \"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_document_type_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_document_type_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <div *ngIf=\"filterForm.get('fixed_asset_document_status')\">\n <small\n class=\"mr-2 text-secondary\"\n *ngIf=\"getFilterConfig('showLabel', 'fixed_asset_document_status')\"\n >\n Status\n </small>\n <mat-button-toggle-group\n formControlName=\"fixed_asset_document_status\"\n [multiple]=\"false\"\n >\n <mat-button-toggle value=\"all\">All</mat-button-toggle>\n <mat-button-toggle value=\"active\">Active</mat-button-toggle>\n <mat-button-toggle value=\"expired\">Expired</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <mat-form-field *ngIf=\"filterForm.get('asset_account_ids')\">\n <mat-label>Asset Account</mat-label>\n <app-searchable-selector\n formControlName=\"asset_account_ids\"\n apiUrl=\"api/accounts\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.asset_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('asset_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('depreciation_expense_account_ids')\">\n <mat-label>Depreciation Expense Account</mat-label>\n <app-searchable-selector\n [multiple]=\"true\"\n apiUrl=\"api/accounts\"\n formControlName=\"depreciation_expense_account_ids\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.depreciation_expense_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('depreciation_expense_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('depreciation_method_ids')\">\n <mat-label>Depreciation Method</mat-label>\n <app-searchable-selector\n formControlName=\"depreciation_method_ids\"\n apiUrl=\"api/accounting-plus/depreciation-methods\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n (click)=\"resetField('depreciation_method_ids')\"\n *ngIf=\"filterForm.value?.depreciation_method_ids\"\n mat-icon-button\n matSuffix\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field\n *ngIf=\"filterForm.get('task_status_ids')\"\n style=\"width: 150px\"\n >\n <mat-label>Status</mat-label>\n <app-searchable-selector\n apiUrl=\"api/task-statuses\"\n formControlName=\"task_status_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.task_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('task_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('service_center_ids')\">\n <mat-label>Service Center</mat-label>\n <app-searchable-selector\n apiUrl=\"api/accounting-plus/service-centers\"\n formControlName=\"service_center_ids\"\n titleField=\"name\"\n [enableSearch]=\"false\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.service_center_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('service_center_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_maintenance_status_ids')\">\n <mat-label>Status</mat-label>\n <app-searchable-selector\n apiUrl=\"api/accounting-plus/fixed-asset-maintenance-statuses\"\n formControlName=\"fixed_asset_maintenance_status_ids\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_maintenance_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_maintenance_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('group_by')\">\n <mat-label>Group By</mat-label>\n <mat-select formControlName=\"group_by\">\n <mat-option value=\"week\">Week</mat-option>\n <mat-option value=\"month\">Month</mat-option>\n <mat-option value=\"year\">Year</mat-option>\n </mat-select>\n </mat-form-field>\n</form>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i10$1.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i10$1.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "component", type: i1.TimelineFilterComponent, selector: "app-timeline-filter", inputs: ["defaultValue", "required", "disabled", "value", "timelines", "dateFrom", "dateTo", "appearance", "showClearButton", "form", "labelText"], outputs: ["selectionChange"] }, { kind: "component", type: i7$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i11.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i12$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i12$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }], preserveWhitespaces: true });
|
|
1406
|
+
}
|
|
1407
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterComponent, decorators: [{
|
|
1408
|
+
type: Component,
|
|
1409
|
+
args: [{ selector: "app-techlify-filter", template: "<form\n [formGroup]=\"filterForm\"\n fxLayout\n fxLayoutAlign=\"start center\"\n fxLayoutGap=\"10px\"\n>\n <mat-form-field\n *ngIf=\"filterForm.get('search')\"\n [appearance]=\"getFilterConfig('appearance', 'search')\"\n >\n <mat-label>Search</mat-label>\n <input\n formControlName=\"search\"\n matInput\n [placeholder]=\"getFilterConfig('placeholder', 'search')\"\n />\n <button\n *ngIf=\"filterForm.value?.search\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('search')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <app-timeline-filter\n *ngIf=\"filterForm?.get('duration')\"\n appearance=\"fill\"\n [labelText]=\"getFilterConfig('label', 'duration')\"\n [appearance]=\"getFilterConfig('appearance', 'duration')\"\n formControlName=\"duration\"\n (selectionChange)=\"onDurationChange($event)\"\n [showClearButton]=\"true\"\n [dateFrom]=\"filterForm.value?.date_from\"\n [dateTo]=\"filterForm.value?.date_to\"\n ></app-timeline-filter>\n\n <mat-form-field *ngIf=\"filterForm.get('payment_method_ids')\">\n <mat-label>Payment Method</mat-label>\n <app-searchable-selector\n formControlName=\"payment_method_ids\"\n apiUrl=\"api/payment-methods\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.payment_method_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('payment_method_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngIf=\"filterForm.get('payment_account_ids')\">\n <mat-form-field *ngxPermissionsOnly=\"['accountingcommon_account.read']\">\n <mat-label>{{\n getFilterConfig(\"label\", \"payment_account_ids\") || \"Payment Account\"\n }}</mat-label>\n <app-searchable-selector\n formControlName=\"payment_account_ids\"\n [apiUrl]=\"\n getFilterConfig('apiUrl', 'payment_account_ids') || 'api/accounts'\n \"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.payment_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('payment_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <mat-form-field *ngIf=\"filterForm.get('invoice_status_ids')\">\n <mat-label>Invoice Status</mat-label>\n <app-searchable-selector\n formControlName=\"invoice_status_ids\"\n apiUrl=\"api/invoice-statuses\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.invoice_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('invoice_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngIf=\"filterForm.get('customer_ids')\">\n <mat-form-field *ngxPermissionsOnly=\"['customer_read']\">\n <mat-label>Customer</mat-label>\n <app-searchable-selector\n formControlName=\"customer_ids\"\n titleField=\"name\"\n apiUrl=\"api/customers\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.customer_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('customer_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <ng-container\n *ngIf=\"\n filterForm.get('project_ids') &&\n getFilterConfig('disabled', 'project_ids') === false\n \"\n >\n <mat-form-field *ngxPermissionsOnly=\"['project.read']\">\n <mat-label>Project</mat-label>\n <app-searchable-selector\n formControlName=\"project_ids\"\n apiUrl=\"api/projects\"\n titleField=\"project_name\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.project_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('project_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <mat-form-field *ngIf=\"filterForm.get('product_ids')\">\n <mat-label>Product</mat-label>\n <app-searchable-selector\n formControlName=\"product_ids\"\n apiUrl=\"api/products\"\n titleField=\"name\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.product_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('product_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('measure_ids')\">\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n formControlName=\"measure_ids\"\n apiUrl=\"api/product-measures\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.measure_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('measure_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngxPermissionsOnly=\"['supplier.read']\">\n <mat-form-field\n *ngIf=\"filterForm.get('supplier_ids')\"\n [appearance]=\"getFilterConfig('appearance', 'supplier_ids')\"\n >\n <mat-label>Supplier</mat-label>\n <app-searchable-selector\n formControlName=\"supplier_ids\"\n titleField=\"company_name\"\n apiUrl=\"api/suppliers\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.supplier_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('supplier_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <app-timeline-filter\n appearance=\"fill\"\n [labelText]=\"getFilterConfig('label', 'expiry_duration')\"\n *ngIf=\"filterForm?.get('expiry_duration')\"\n formControlName=\"expiry_duration\"\n (selectionChange)=\"onExpiryDurationChange($event)\"\n [showClearButton]=\"true\"\n [dateFrom]=\"filterForm.value?.expiry_date_from\"\n [dateTo]=\"filterForm.value?.expiry_date_to\"\n ></app-timeline-filter>\n\n <mat-form-field\n *ngIf=\"filterForm.get('cost_category_ids')\"\n style=\"width: 150px\"\n >\n <mat-label>Cost Category</mat-label>\n <app-searchable-selector\n formControlName=\"cost_category_ids\"\n apiUrl=\"api/cost-code-categories\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.cost_category_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('cost_category_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('milestone_ids')\" style=\"width: 150px\">\n <mat-label>Milestone</mat-label>\n <app-searchable-selector\n formControlName=\"milestone_ids\"\n apiUrl=\"api/milestones\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.milestone_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('milestone_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('team_member_ids')\">\n <mat-label>Assignee</mat-label>\n <app-searchable-selector\n apiUrl=\"api/persons\"\n formControlName=\"team_member_ids\"\n titleField=\"name\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.team_member_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('team_member_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_type_ids')\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n formControlName=\"fixed_asset_type_ids\"\n apiUrl=\"api/accounting-plus/fixed-asset-types\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_type_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_type_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_document_type_ids')\">\n <mat-label>Type</mat-label>\n <app-searchable-selector\n formControlName=\"fixed_asset_document_type_ids\"\n apiUrl=\"api/accounting-plus/fixed-asset-document-types\"\n [multiple]=\"true\"\n [enableSearch]=\"\n getFilterConfig('enableSearch', 'fixed_asset_document_type_ids')\n \"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_document_type_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_document_type_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <div *ngIf=\"filterForm.get('fixed_asset_document_status')\">\n <small\n class=\"mr-2 text-secondary\"\n *ngIf=\"getFilterConfig('showLabel', 'fixed_asset_document_status')\"\n >\n Status\n </small>\n <mat-button-toggle-group\n formControlName=\"fixed_asset_document_status\"\n [multiple]=\"false\"\n >\n <mat-button-toggle value=\"all\">All</mat-button-toggle>\n <mat-button-toggle value=\"active\">Active</mat-button-toggle>\n <mat-button-toggle value=\"expired\">Expired</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <mat-form-field *ngIf=\"filterForm.get('asset_account_ids')\">\n <mat-label>Asset Account</mat-label>\n <app-searchable-selector\n formControlName=\"asset_account_ids\"\n apiUrl=\"api/accounts\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.asset_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('asset_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('depreciation_expense_account_ids')\">\n <mat-label>Depreciation Expense Account</mat-label>\n <app-searchable-selector\n [multiple]=\"true\"\n apiUrl=\"api/accounts\"\n formControlName=\"depreciation_expense_account_ids\"\n ></app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.depreciation_expense_account_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('depreciation_expense_account_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('depreciation_method_ids')\">\n <mat-label>Depreciation Method</mat-label>\n <app-searchable-selector\n formControlName=\"depreciation_method_ids\"\n apiUrl=\"api/accounting-plus/depreciation-methods\"\n [multiple]=\"true\"\n ></app-searchable-selector>\n <button\n (click)=\"resetField('depreciation_method_ids')\"\n *ngIf=\"filterForm.value?.depreciation_method_ids\"\n mat-icon-button\n matSuffix\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field\n *ngIf=\"filterForm.get('task_status_ids')\"\n style=\"width: 150px\"\n >\n <mat-label>Status</mat-label>\n <app-searchable-selector\n apiUrl=\"api/task-statuses\"\n formControlName=\"task_status_ids\"\n titleField=\"title\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.task_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('task_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('service_center_ids')\">\n <mat-label>Service Center</mat-label>\n <app-searchable-selector\n apiUrl=\"api/accounting-plus/service-centers\"\n formControlName=\"service_center_ids\"\n titleField=\"name\"\n [enableSearch]=\"false\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.service_center_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('service_center_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('fixed_asset_maintenance_status_ids')\">\n <mat-label>Status</mat-label>\n <app-searchable-selector\n apiUrl=\"api/accounting-plus/fixed-asset-maintenance-statuses\"\n formControlName=\"fixed_asset_maintenance_status_ids\"\n [multiple]=\"true\"\n [enableSearch]=\"false\"\n >\n </app-searchable-selector>\n <button\n *ngIf=\"filterForm.value?.fixed_asset_maintenance_status_ids\"\n mat-icon-button\n matSuffix\n (click)=\"resetField('fixed_asset_maintenance_status_ids')\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <mat-form-field *ngIf=\"filterForm.get('group_by')\">\n <mat-label>Group By</mat-label>\n <mat-select formControlName=\"group_by\">\n <mat-option value=\"week\">Week</mat-option>\n <mat-option value=\"month\">Month</mat-option>\n <mat-option value=\"year\">Year</mat-option>\n </mat-select>\n </mat-form-field>\n</form>\n" }]
|
|
1410
|
+
}], ctorParameters: () => [{ type: i1.RequestHelperService }, { type: i2.ActivatedRoute }], propDecorators: { filterForm: [{
|
|
1411
|
+
type: Input
|
|
1412
|
+
}], filterConfig: [{
|
|
1413
|
+
type: Input
|
|
1414
|
+
}], filterUpdated: [{
|
|
1415
|
+
type: Output
|
|
1416
|
+
}] } });
|
|
1417
|
+
|
|
1418
|
+
class StockReceiptDeleteButtonComponent {
|
|
1419
|
+
matDialog;
|
|
1420
|
+
stockReceiptService;
|
|
1421
|
+
alertService;
|
|
1422
|
+
stockReceipt;
|
|
1423
|
+
deleted = new EventEmitter();
|
|
1424
|
+
isDeleting = false;
|
|
1425
|
+
constructor(matDialog, stockReceiptService, alertService) {
|
|
1426
|
+
this.matDialog = matDialog;
|
|
1427
|
+
this.stockReceiptService = stockReceiptService;
|
|
1428
|
+
this.alertService = alertService;
|
|
1429
|
+
}
|
|
1430
|
+
showDeleteConfirmModel(templateRef) {
|
|
1431
|
+
this.matDialog.open(templateRef, { width: "400px" });
|
|
1432
|
+
}
|
|
1433
|
+
delete() {
|
|
1434
|
+
this.isDeleting = true;
|
|
1435
|
+
this.stockReceiptService.delete(this.stockReceipt).subscribe({
|
|
1436
|
+
next: () => {
|
|
1437
|
+
this.matDialog.closeAll();
|
|
1438
|
+
this.isDeleting = false;
|
|
1439
|
+
this.deleted.emit();
|
|
1440
|
+
this.alertService.addAlert("Stock Receipt deleted successfully!", "success");
|
|
1441
|
+
},
|
|
1442
|
+
error: () => {
|
|
1443
|
+
this.isDeleting = false;
|
|
1444
|
+
},
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptDeleteButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: StockReceiptService }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1448
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockReceiptDeleteButtonComponent, selector: "app-stock-receipt-delete-button", inputs: { stockReceipt: "stockReceipt" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n (click)=\"showDeleteConfirmModel(deleteModelTemplate)\"\n>\n delete\n</span>\n\n<ng-template #deleteModelTemplate>\n <h3 mat-dialog-title>Delete Stock Receipt</h3>\n <div mat-dialog-content>\n <p>Are you sure you want to delete the stock receipt record?</p>\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-2\">\n <button\n [disabled]=\"isDeleting\"\n mat-raised-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n mat-flat-button\n mat-dialog-close\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }], preserveWhitespaces: true });
|
|
1449
|
+
}
|
|
1450
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptDeleteButtonComponent, decorators: [{
|
|
1451
|
+
type: Component,
|
|
1452
|
+
args: [{ selector: "app-stock-receipt-delete-button", template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n (click)=\"showDeleteConfirmModel(deleteModelTemplate)\"\n>\n delete\n</span>\n\n<ng-template #deleteModelTemplate>\n <h3 mat-dialog-title>Delete Stock Receipt</h3>\n <div mat-dialog-content>\n <p>Are you sure you want to delete the stock receipt record?</p>\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-2\">\n <button\n [disabled]=\"isDeleting\"\n mat-raised-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n mat-flat-button\n mat-dialog-close\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
|
|
1453
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: StockReceiptService }, { type: i1.AlertService }], propDecorators: { stockReceipt: [{
|
|
1454
|
+
type: Input
|
|
1455
|
+
}], deleted: [{
|
|
1456
|
+
type: Output
|
|
1457
|
+
}] } });
|
|
1458
|
+
|
|
1459
|
+
let StockReceiptsListPageComponent = class StockReceiptsListPageComponent extends TechlifyListingControllerInterface {
|
|
1460
|
+
stockReceiptService;
|
|
1461
|
+
formBuilder;
|
|
1462
|
+
requestHelperService;
|
|
1463
|
+
product;
|
|
1464
|
+
listUpdated = new EventEmitter();
|
|
1465
|
+
displayedColumns = [
|
|
1466
|
+
"no",
|
|
1467
|
+
"product",
|
|
1468
|
+
"date",
|
|
1469
|
+
"quantity",
|
|
1470
|
+
"purchase_price",
|
|
1471
|
+
"amount",
|
|
1472
|
+
"particulars",
|
|
1473
|
+
"supplier",
|
|
1474
|
+
"creator",
|
|
1475
|
+
"actions",
|
|
1476
|
+
];
|
|
1477
|
+
filterConfig = {
|
|
1478
|
+
duration: {
|
|
1479
|
+
label: "Date",
|
|
1480
|
+
},
|
|
1481
|
+
};
|
|
1482
|
+
constructor(stockReceiptService, formBuilder, requestHelperService) {
|
|
1483
|
+
super();
|
|
1484
|
+
this.stockReceiptService = stockReceiptService;
|
|
1485
|
+
this.formBuilder = formBuilder;
|
|
1486
|
+
this.requestHelperService = requestHelperService;
|
|
1487
|
+
this.lastPage = 0;
|
|
1488
|
+
this.filterForm = this.formBuilder.group({
|
|
1489
|
+
product_ids: [""],
|
|
1490
|
+
duration: [Timeline.THIS_MONTH],
|
|
1491
|
+
date_from: [""],
|
|
1492
|
+
date_to: [""],
|
|
1493
|
+
supplier_ids: [""],
|
|
1494
|
+
measure_ids: [""],
|
|
1495
|
+
sort_by: ["date|desc"],
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
ngOnInit() {
|
|
1499
|
+
this.filterForm.valueChanges
|
|
1500
|
+
.pipe(debounceTime$1(500))
|
|
1501
|
+
.subscribe({
|
|
1502
|
+
next: () => this.reload(),
|
|
1503
|
+
});
|
|
1504
|
+
if (this.product) {
|
|
1505
|
+
this.filterForm.get("product_ids")?.setValue(this.product?.id);
|
|
1506
|
+
const index = this.displayedColumns.indexOf("product");
|
|
1507
|
+
if (index !== -1) {
|
|
1508
|
+
this.displayedColumns.splice(index, 1);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
loadData() {
|
|
1513
|
+
const params = {
|
|
1514
|
+
page: this.page,
|
|
1515
|
+
perPage: this.perPage,
|
|
1516
|
+
with: "creator,supplier,product.measure",
|
|
1517
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1518
|
+
};
|
|
1519
|
+
this.isWorking = true;
|
|
1520
|
+
this.stockReceiptService.index(params).subscribe({
|
|
1521
|
+
next: (response) => {
|
|
1522
|
+
this.models = this.models.concat(response?.data);
|
|
1523
|
+
this.lastPage = response?.last_page;
|
|
1524
|
+
this.isWorking = false;
|
|
1525
|
+
},
|
|
1526
|
+
error: () => {
|
|
1527
|
+
this.isWorking = false;
|
|
1528
|
+
},
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
onSortChange(sort) {
|
|
1532
|
+
console.log(sort);
|
|
1533
|
+
let { active, direction } = sort;
|
|
1534
|
+
if (!active) {
|
|
1535
|
+
active = "date";
|
|
1536
|
+
}
|
|
1537
|
+
if (!direction) {
|
|
1538
|
+
direction = "desc";
|
|
1539
|
+
active = "date";
|
|
1540
|
+
}
|
|
1541
|
+
this.filterForm.get("sort_by").setValue(active + "|" + direction);
|
|
1542
|
+
}
|
|
1543
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsListPageComponent, deps: [{ token: StockReceiptService }, { token: i2$2.FormBuilder }, { token: i1.RequestHelperService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1544
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockReceiptsListPageComponent, selector: "app-stock-receipts-list-page", inputs: { product: "product" }, outputs: { listUpdated: "listUpdated" }, usesInheritance: true, ngImport: i0, template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Stock Receipts</h3>\n </div>\n\n <app-techlify-filter\n [filterForm]=\"filterForm\"\n (filterUpdated)=\"reload()\"\n [filterConfig]=\"filterConfig\"\n ></app-techlify-filter>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content *ngIf=\"product\" class=\"mb-0\">\n <div class=\"d-flex justify-content-start align-items-center gap-2 mb-2\">\n <span class=\"material-symbols-outlined\"> output_circle </span>\n <h3 class=\"mb-0\">Stock Receipts</h3>\n <app-stock-receipt-form-button\n [product]=\"product\"\n (saved)=\"reload(); listUpdated.emit()\"\n icon=\"add\"\n ></app-stock-receipt-form-button>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n aria-describedby=\"Stock Receipts\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"no\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.date | date }}</td>\n </ng-container>\n\n <!-- Quantity Column -->\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }} {{ element?.product?.measure?.title }}\n </td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.purchase_price | currency }}\n </td>\n </ng-container>\n\n <!-- Total Value Column -->\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Total Value</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.amount | currency }}\n </td>\n </ng-container>\n\n <!-- Particulars Column -->\n <ng-container matColumnDef=\"particulars\">\n <th mat-header-cell *matHeaderCellDef>Particulars</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.particulars }}</td>\n </ng-container>\n\n <!-- Supplier Column -->\n <ng-container matColumnDef=\"supplier\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.supplier?.company_name }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-1\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex gap-1\">\n <app-stock-receipt-form-button\n [product]=\"element.product\"\n [stockReceipt]=\"element\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-receipt-form-button>\n <app-stock-receipt-delete-button\n [stockReceipt]=\"element\"\n (deleted)=\"reload(); listUpdated.emit()\"\n ></app-stock-receipt-delete-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar *ngIf=\"isWorking\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: TechlifyFilterComponent, selector: "app-techlify-filter", inputs: ["filterForm", "filterConfig"], outputs: ["filterUpdated"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: i10.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: StockReceiptFormButtonComponent, selector: "app-stock-receipt-form-button", inputs: ["product", "stockReceipt", "icon"], outputs: ["saved"] }, { kind: "component", type: StockReceiptDeleteButtonComponent, selector: "app-stock-receipt-delete-button", inputs: ["stockReceipt"], outputs: ["deleted"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1545
|
+
};
|
|
1546
|
+
StockReceiptsListPageComponent = __decorate([
|
|
1547
|
+
UntilDestroy()
|
|
1548
|
+
], StockReceiptsListPageComponent);
|
|
1549
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsListPageComponent, decorators: [{
|
|
1550
|
+
type: Component,
|
|
1551
|
+
args: [{ selector: "app-stock-receipts-list-page", template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Stock Receipts</h3>\n </div>\n\n <app-techlify-filter\n [filterForm]=\"filterForm\"\n (filterUpdated)=\"reload()\"\n [filterConfig]=\"filterConfig\"\n ></app-techlify-filter>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content *ngIf=\"product\" class=\"mb-0\">\n <div class=\"d-flex justify-content-start align-items-center gap-2 mb-2\">\n <span class=\"material-symbols-outlined\"> output_circle </span>\n <h3 class=\"mb-0\">Stock Receipts</h3>\n <app-stock-receipt-form-button\n [product]=\"product\"\n (saved)=\"reload(); listUpdated.emit()\"\n icon=\"add\"\n ></app-stock-receipt-form-button>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n aria-describedby=\"Stock Receipts\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"no\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.date | date }}</td>\n </ng-container>\n\n <!-- Quantity Column -->\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }} {{ element?.product?.measure?.title }}\n </td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.purchase_price | currency }}\n </td>\n </ng-container>\n\n <!-- Total Value Column -->\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Total Value</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.amount | currency }}\n </td>\n </ng-container>\n\n <!-- Particulars Column -->\n <ng-container matColumnDef=\"particulars\">\n <th mat-header-cell *matHeaderCellDef>Particulars</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.particulars }}</td>\n </ng-container>\n\n <!-- Supplier Column -->\n <ng-container matColumnDef=\"supplier\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.supplier?.company_name }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-1\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex gap-1\">\n <app-stock-receipt-form-button\n [product]=\"element.product\"\n [stockReceipt]=\"element\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-receipt-form-button>\n <app-stock-receipt-delete-button\n [stockReceipt]=\"element\"\n (deleted)=\"reload(); listUpdated.emit()\"\n ></app-stock-receipt-delete-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar *ngIf=\"isWorking\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
|
|
1552
|
+
}], ctorParameters: () => [{ type: StockReceiptService }, { type: i2$2.FormBuilder }, { type: i1.RequestHelperService }], propDecorators: { product: [{
|
|
1553
|
+
type: Input
|
|
1554
|
+
}], listUpdated: [{
|
|
1555
|
+
type: Output
|
|
1556
|
+
}] } });
|
|
1557
|
+
|
|
1558
|
+
class StockIssuanceDeleteButtonComponent {
|
|
1559
|
+
matDialog;
|
|
1560
|
+
stockIssuanceService;
|
|
1561
|
+
alertService;
|
|
1562
|
+
stockIssuance;
|
|
1563
|
+
deleted = new EventEmitter();
|
|
1564
|
+
isDeleting = false;
|
|
1565
|
+
constructor(matDialog, stockIssuanceService, alertService) {
|
|
1566
|
+
this.matDialog = matDialog;
|
|
1567
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
1568
|
+
this.alertService = alertService;
|
|
1569
|
+
}
|
|
1570
|
+
showDeleteConfirmModel(templateRef) {
|
|
1571
|
+
this.matDialog.open(templateRef, { width: "400px" });
|
|
1572
|
+
}
|
|
1573
|
+
delete() {
|
|
1574
|
+
this.isDeleting = true;
|
|
1575
|
+
this.stockIssuanceService.delete(this.stockIssuance).subscribe({
|
|
1576
|
+
next: () => {
|
|
1577
|
+
this.matDialog.closeAll();
|
|
1578
|
+
this.isDeleting = false;
|
|
1579
|
+
this.deleted.emit();
|
|
1580
|
+
this.alertService.addAlert("Stock Issuance deleted successfully!", "success");
|
|
1581
|
+
},
|
|
1582
|
+
error: () => {
|
|
1583
|
+
this.isDeleting = false;
|
|
1584
|
+
},
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: StockIssuanceService }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1588
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockIssuanceDeleteButtonComponent, selector: "app-stock-issuance-delete-button", inputs: { stockIssuance: "stockIssuance" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n (click)=\"showDeleteConfirmModel(deleteModelTemplate)\"\n>\n delete\n</span>\n\n<ng-template #deleteModelTemplate>\n <h3 mat-dialog-title>Delete Stock Issuance</h3>\n <div mat-dialog-content>\n <p>Are you sure you want to delete the stock issuance record?</p>\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-2\">\n <button\n [disabled]=\"isDeleting\"\n mat-raised-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n mat-flat-button\n mat-dialog-close\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }], preserveWhitespaces: true });
|
|
1589
|
+
}
|
|
1590
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonComponent, decorators: [{
|
|
1591
|
+
type: Component,
|
|
1592
|
+
args: [{ selector: "app-stock-issuance-delete-button", template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n (click)=\"showDeleteConfirmModel(deleteModelTemplate)\"\n>\n delete\n</span>\n\n<ng-template #deleteModelTemplate>\n <h3 mat-dialog-title>Delete Stock Issuance</h3>\n <div mat-dialog-content>\n <p>Are you sure you want to delete the stock issuance record?</p>\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-2\">\n <button\n [disabled]=\"isDeleting\"\n mat-raised-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n mat-flat-button\n mat-dialog-close\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
|
|
1593
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: StockIssuanceService }, { type: i1.AlertService }], propDecorators: { stockIssuance: [{
|
|
1594
|
+
type: Input
|
|
1595
|
+
}], deleted: [{
|
|
1596
|
+
type: Output
|
|
1597
|
+
}] } });
|
|
1598
|
+
|
|
1599
|
+
class StockIssuancesListComponent extends TechlifyListingControllerInterface {
|
|
1600
|
+
formBuilder;
|
|
1601
|
+
requestHelperService;
|
|
1602
|
+
stockIssuanceService;
|
|
1603
|
+
product;
|
|
1604
|
+
issuableType;
|
|
1605
|
+
issuableId;
|
|
1606
|
+
label = "Stock Issuances";
|
|
1607
|
+
listUpdated = new EventEmitter();
|
|
1608
|
+
filterConfig = {
|
|
1609
|
+
duration: {
|
|
1610
|
+
label: "Date",
|
|
1611
|
+
},
|
|
1612
|
+
search: {
|
|
1613
|
+
placeholder: "Search Product Name, SKU, Description, etc",
|
|
1614
|
+
},
|
|
1615
|
+
};
|
|
1616
|
+
displayedColumns = [
|
|
1617
|
+
"no",
|
|
1618
|
+
"product",
|
|
1619
|
+
"date",
|
|
1620
|
+
"quantity",
|
|
1621
|
+
"related",
|
|
1622
|
+
"particulars",
|
|
1623
|
+
"creator",
|
|
1624
|
+
"actions",
|
|
1625
|
+
];
|
|
1626
|
+
constructor(formBuilder, requestHelperService, stockIssuanceService) {
|
|
1627
|
+
super();
|
|
1628
|
+
this.formBuilder = formBuilder;
|
|
1629
|
+
this.requestHelperService = requestHelperService;
|
|
1630
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
1631
|
+
this.lastPage = 0;
|
|
1632
|
+
this.filterForm = this.formBuilder.group({
|
|
1633
|
+
duration: [Timeline.THIS_MONTH],
|
|
1634
|
+
date_from: [""],
|
|
1635
|
+
date_to: [""],
|
|
1636
|
+
measure_ids: [""],
|
|
1637
|
+
product_ids: [""],
|
|
1638
|
+
search: [""],
|
|
1639
|
+
sort_by: ["date|desc"],
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
ngOnInit() {
|
|
1643
|
+
this.filterForm.valueChanges
|
|
1644
|
+
.pipe(debounceTime$1(500))
|
|
1645
|
+
.subscribe({
|
|
1646
|
+
next: () => this.reload(),
|
|
1647
|
+
});
|
|
1648
|
+
if (this.product) {
|
|
1649
|
+
this.filterForm.get("product_ids")?.setValue(this.product?.id);
|
|
1650
|
+
const index = this.displayedColumns.indexOf("product");
|
|
1651
|
+
if (index !== -1) {
|
|
1652
|
+
this.displayedColumns.splice(index, 1);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
loadData() {
|
|
1657
|
+
const params = {
|
|
1658
|
+
page: this.page,
|
|
1659
|
+
perPage: this.perPage,
|
|
1660
|
+
with: "creator,product.measure,issuable.fixedAsset",
|
|
1661
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1662
|
+
};
|
|
1663
|
+
if (this.issuableId && this.issuableType) {
|
|
1664
|
+
params.issuable_ids = this.issuableId;
|
|
1665
|
+
params.issuable_types = this.issuableType;
|
|
1666
|
+
}
|
|
1667
|
+
this.isWorking = true;
|
|
1668
|
+
this.stockIssuanceService.index(params).subscribe({
|
|
1669
|
+
next: (response) => {
|
|
1670
|
+
this.models = this.models.concat(response?.data);
|
|
1671
|
+
this.lastPage = response?.last_page;
|
|
1672
|
+
this.isWorking = false;
|
|
1673
|
+
},
|
|
1674
|
+
error: () => {
|
|
1675
|
+
this.isWorking = false;
|
|
1676
|
+
},
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
onSortChange(sort) {
|
|
1680
|
+
let { active, direction } = sort;
|
|
1681
|
+
if (!active) {
|
|
1682
|
+
active = "date";
|
|
1683
|
+
}
|
|
1684
|
+
if (!direction) {
|
|
1685
|
+
direction = "desc";
|
|
1686
|
+
active = "date";
|
|
1687
|
+
}
|
|
1688
|
+
this.filterForm.get("sort_by").setValue(active + "|" + direction);
|
|
1689
|
+
}
|
|
1690
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListComponent, deps: [{ token: i2$2.FormBuilder }, { token: i1.RequestHelperService }, { token: StockIssuanceService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1691
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockIssuancesListComponent, selector: "app-stock-issuances-list", inputs: { product: "product", issuableType: "issuableType", issuableId: "issuableId", label: "label" }, outputs: { listUpdated: "listUpdated" }, usesInheritance: true, ngImport: i0, template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">{{ label }}</h3>\n\n <app-stock-issue-form-button\n icon=\"add\"\n [issuableType]=\"issuableType\"\n [issuableId]=\"issuableId\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n\n <app-techlify-filter\n [filterForm]=\"filterForm\"\n [filterConfig]=\"filterConfig\"\n (filterUpdated)=\"reload()\"\n ></app-techlify-filter>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content *ngIf=\"product\" class=\"mb-0\">\n <div class=\"d-flex justify-content-start align-items-center gap-2 mb-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <h3 class=\"mb-0\">Stock Issuances</h3>\n\n <app-stock-issue-form-button\n [product]=\"product\"\n icon=\"add\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n aria-describedby=\"Stock Issuances\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"no\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"[\n '/inventory/products/',\n element?.product?.id,\n 'view'\n ]\"\n >\n {{ element?.product?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.date | date }}</td>\n </ng-container>\n\n <!-- Related Column -->\n <ng-container matColumnDef=\"related\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Related</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-dark\"\n *ngIf=\"element?.issuable\"\n [routerLink]=\"['/maintenances', element?.issuable_id, 'view']\"\n >\n Maintenance for {{ element?.issuable?.fixed_asset?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Quantity Column -->\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }} {{ element?.product?.measure?.title }}\n </td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.purchase_price | currency }}\n </td>\n </ng-container>\n\n <!-- Total Value Column -->\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Total Value</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.amount | currency }}\n </td>\n </ng-container>\n\n <!-- Particulars Column -->\n <ng-container matColumnDef=\"particulars\">\n <th mat-header-cell *matHeaderCellDef>Particulars</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.particulars }}</td>\n </ng-container>\n\n <!-- Supplier Column -->\n <ng-container matColumnDef=\"supplier\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.supplier?.company_name }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-1\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex gap-1\">\n <app-stock-issue-form-button\n [product]=\"element.product\"\n [stockIssuance]=\"element\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n <app-stock-issuance-delete-button\n [stockIssuance]=\"element\"\n (deleted)=\"reload(); listUpdated.emit()\"\n ></app-stock-issuance-delete-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar *ngIf=\"isWorking\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: TechlifyFilterComponent, selector: "app-techlify-filter", inputs: ["filterForm", "filterConfig"], outputs: ["filterUpdated"] }, { kind: "component", type: StockIssueFormButtonComponent, selector: "app-stock-issue-form-button", inputs: ["product", "stockIssuance", "icon", "issuableType", "issuableId"], outputs: ["saved"] }, { kind: "directive", type: i10.InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: StockIssuanceDeleteButtonComponent, selector: "app-stock-issuance-delete-button", inputs: ["stockIssuance"], outputs: ["deleted"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1692
|
+
}
|
|
1693
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListComponent, decorators: [{
|
|
1694
|
+
type: Component,
|
|
1695
|
+
args: [{ selector: "app-stock-issuances-list", template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">{{ label }}</h3>\n\n <app-stock-issue-form-button\n icon=\"add\"\n [issuableType]=\"issuableType\"\n [issuableId]=\"issuableId\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n\n <app-techlify-filter\n [filterForm]=\"filterForm\"\n [filterConfig]=\"filterConfig\"\n (filterUpdated)=\"reload()\"\n ></app-techlify-filter>\n </mat-card-content>\n</mat-card>\n\n<mat-card>\n <mat-card-content *ngIf=\"product\" class=\"mb-0\">\n <div class=\"d-flex justify-content-start align-items-center gap-2 mb-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <h3 class=\"mb-0\">Stock Issuances</h3>\n\n <app-stock-issue-form-button\n [product]=\"product\"\n icon=\"add\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n aria-describedby=\"Stock Issuances\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"no\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"[\n '/inventory/products/',\n element?.product?.id,\n 'view'\n ]\"\n >\n {{ element?.product?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.date | date }}</td>\n </ng-container>\n\n <!-- Related Column -->\n <ng-container matColumnDef=\"related\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Related</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-dark\"\n *ngIf=\"element?.issuable\"\n [routerLink]=\"['/maintenances', element?.issuable_id, 'view']\"\n >\n Maintenance for {{ element?.issuable?.fixed_asset?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Quantity Column -->\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }} {{ element?.product?.measure?.title }}\n </td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.purchase_price | currency }}\n </td>\n </ng-container>\n\n <!-- Total Value Column -->\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Total Value</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.amount | currency }}\n </td>\n </ng-container>\n\n <!-- Particulars Column -->\n <ng-container matColumnDef=\"particulars\">\n <th mat-header-cell *matHeaderCellDef>Particulars</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.particulars }}</td>\n </ng-container>\n\n <!-- Supplier Column -->\n <ng-container matColumnDef=\"supplier\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Supplier</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.supplier?.company_name }}\n </td>\n </ng-container>\n\n <!-- Creator Column -->\n <ng-container matColumnDef=\"creator\">\n <th mat-header-cell *matHeaderCellDef>Creator</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-1\">{{ element?.creator?.name }}</p>\n <small class=\"text-secondary\">{{ element?.created_at | date }}</small>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex gap-1\">\n <app-stock-issue-form-button\n [product]=\"element.product\"\n [stockIssuance]=\"element\"\n (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n <app-stock-issuance-delete-button\n [stockIssuance]=\"element\"\n (deleted)=\"reload(); listUpdated.emit()\"\n ></app-stock-issuance-delete-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar *ngIf=\"isWorking\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
|
|
1696
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1.RequestHelperService }, { type: StockIssuanceService }], propDecorators: { product: [{
|
|
1697
|
+
type: Input
|
|
1698
|
+
}], issuableType: [{
|
|
1699
|
+
type: Input
|
|
1700
|
+
}], issuableId: [{
|
|
1701
|
+
type: Input
|
|
1702
|
+
}], label: [{
|
|
1703
|
+
type: Input
|
|
1704
|
+
}], listUpdated: [{
|
|
1705
|
+
type: Output
|
|
1706
|
+
}] } });
|
|
1707
|
+
|
|
1708
|
+
class ProductTaxService extends TechlifyServiceBaseClass {
|
|
1709
|
+
constructor(httpService) {
|
|
1710
|
+
super(httpService, "product-taxes");
|
|
1711
|
+
}
|
|
1712
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1713
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, providedIn: "root" });
|
|
1714
|
+
}
|
|
1715
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, decorators: [{
|
|
1716
|
+
type: Injectable,
|
|
1717
|
+
args: [{
|
|
1718
|
+
providedIn: "root",
|
|
1719
|
+
}]
|
|
1720
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
1721
|
+
|
|
1722
|
+
class ProductTaxFormButtonComponent extends TechlifyFormComponentInterface {
|
|
1723
|
+
matDialog;
|
|
1724
|
+
productTaxService;
|
|
1725
|
+
formBuilder;
|
|
1726
|
+
alertService;
|
|
1727
|
+
product;
|
|
1728
|
+
saved = new EventEmitter();
|
|
1729
|
+
isSaving;
|
|
1730
|
+
constructor(matDialog, productTaxService, formValidatorService, formBuilder, alertService) {
|
|
1731
|
+
super(formValidatorService);
|
|
1732
|
+
this.matDialog = matDialog;
|
|
1733
|
+
this.productTaxService = productTaxService;
|
|
1734
|
+
this.formBuilder = formBuilder;
|
|
1735
|
+
this.alertService = alertService;
|
|
1736
|
+
this.errorMessages = {
|
|
1737
|
+
tax_id: {
|
|
1738
|
+
required: "The tax field is required.",
|
|
1739
|
+
},
|
|
1740
|
+
};
|
|
1741
|
+
this.form = this.formBuilder.group({
|
|
1742
|
+
product_id: [""],
|
|
1743
|
+
tax_id: ["", Validators.required],
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
ngOnInit() {
|
|
1747
|
+
if (this.product) {
|
|
1748
|
+
this.form.get("product_id")?.setValue(this.product?.id);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
showForm(templateRef) {
|
|
1752
|
+
this.matDialog.open(templateRef, { width: "400px" });
|
|
1753
|
+
}
|
|
1754
|
+
save() {
|
|
1755
|
+
this.form.markAllAsTouched();
|
|
1756
|
+
if (this.form.invalid) {
|
|
1757
|
+
this.alertService.addAlert("Please check the form for errors.", "error");
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
const data = { ...this.form.value };
|
|
1761
|
+
const params = {
|
|
1762
|
+
with: "tax.type",
|
|
1763
|
+
};
|
|
1764
|
+
this.isSaving = true;
|
|
1765
|
+
this.productTaxService.store(data, params).subscribe({
|
|
1766
|
+
next: (response) => {
|
|
1767
|
+
this.isSaving = false;
|
|
1768
|
+
this.matDialog.closeAll();
|
|
1769
|
+
this.alertService.addAlert("Product tax saved successfully!", "success");
|
|
1770
|
+
this.saved.emit(response?.item);
|
|
1771
|
+
},
|
|
1772
|
+
error: () => (this.isSaving = false),
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxFormButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: ProductTaxService }, { token: i1.FormValidatorService }, { token: i2$2.FormBuilder }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1776
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxFormButtonComponent, selector: "app-product-tax-form-button", inputs: { product: "product" }, outputs: { saved: "saved" }, usesInheritance: true, ngImport: i0, template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n (click)=\"showForm(formTemplate)\"\n>\n add\n</mat-icon>\n\n<ng-template #formTemplate>\n <form\n [formGroup]=\"form\"\n (submit)=\"save()\"\n mat-dialog-content\n class=\"d-flex flex-column gap-2\"\n >\n <h3 class=\"text-dark\">Add tax for {{ product?.name }}</h3>\n <mat-form-field>\n <mat-label>Tax</mat-label>\n <app-searchable-selector\n formControlName=\"tax_id\"\n required\n apiUrl=\"api/taxes\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('tax_id')\">\n {{ getErrorMessage(\"tax_id\") }}\n </mat-error>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n [disabled]=\"isSaving\"\n type=\"submit\"\n mat-raised-button\n color=\"primary\"\n >\n Save\n </button>\n <button\n [disabled]=\"isSaving\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n </form>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i7$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }], preserveWhitespaces: true });
|
|
1777
|
+
}
|
|
1778
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxFormButtonComponent, decorators: [{
|
|
1779
|
+
type: Component,
|
|
1780
|
+
args: [{ selector: "app-product-tax-form-button", template: "<mat-icon\n color=\"primary\"\n class=\"cursor-pointer\"\n (click)=\"showForm(formTemplate)\"\n>\n add\n</mat-icon>\n\n<ng-template #formTemplate>\n <form\n [formGroup]=\"form\"\n (submit)=\"save()\"\n mat-dialog-content\n class=\"d-flex flex-column gap-2\"\n >\n <h3 class=\"text-dark\">Add tax for {{ product?.name }}</h3>\n <mat-form-field>\n <mat-label>Tax</mat-label>\n <app-searchable-selector\n formControlName=\"tax_id\"\n required\n apiUrl=\"api/taxes\"\n [enableSearch]=\"false\"\n ></app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('tax_id')\">\n {{ getErrorMessage(\"tax_id\") }}\n </mat-error>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button\n [disabled]=\"isSaving\"\n type=\"submit\"\n mat-raised-button\n color=\"primary\"\n >\n Save\n </button>\n <button\n [disabled]=\"isSaving\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n </form>\n</ng-template>\n" }]
|
|
1781
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductTaxService }, { type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: i1.AlertService }], propDecorators: { product: [{
|
|
1782
|
+
type: Input
|
|
1783
|
+
}], saved: [{
|
|
1784
|
+
type: Output
|
|
1785
|
+
}] } });
|
|
1786
|
+
|
|
1787
|
+
class ProductTaxDeleteButtonComponent {
|
|
1788
|
+
matDialog;
|
|
1789
|
+
productTaxService;
|
|
1790
|
+
alertService;
|
|
1791
|
+
productTax;
|
|
1792
|
+
deleted = new EventEmitter();
|
|
1793
|
+
isDeleting;
|
|
1794
|
+
constructor(matDialog, productTaxService, alertService) {
|
|
1795
|
+
this.matDialog = matDialog;
|
|
1796
|
+
this.productTaxService = productTaxService;
|
|
1797
|
+
this.alertService = alertService;
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Delete the product.
|
|
1801
|
+
*/
|
|
1802
|
+
delete() {
|
|
1803
|
+
this.isDeleting = true;
|
|
1804
|
+
this.productTaxService.delete(this.productTax).subscribe({
|
|
1805
|
+
next: () => {
|
|
1806
|
+
this.matDialog?.closeAll();
|
|
1807
|
+
this.deleted.emit();
|
|
1808
|
+
this.isDeleting = false;
|
|
1809
|
+
this.alertService.addAlert("Product tax deleted successfully!", "success");
|
|
1810
|
+
},
|
|
1811
|
+
error: () => (this.isDeleting = false),
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Show delete product dialog.
|
|
1816
|
+
*
|
|
1817
|
+
* @param templateRef
|
|
1818
|
+
*/
|
|
1819
|
+
showDeleteDialog(templateRef) {
|
|
1820
|
+
this.matDialog.open(templateRef, { width: "500px" });
|
|
1821
|
+
}
|
|
1822
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxDeleteButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: ProductTaxService }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1823
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxDeleteButtonComponent, selector: "app-product-tax-delete-button", inputs: { productTax: "productTax" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteConfirmDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the product tax?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
|
|
1824
|
+
}
|
|
1825
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxDeleteButtonComponent, decorators: [{
|
|
1826
|
+
type: Component,
|
|
1827
|
+
args: [{ selector: "app-product-tax-delete-button", template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteConfirmDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the product tax?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"delete()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
|
|
1828
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductTaxService }, { type: i1.AlertService }], propDecorators: { productTax: [{
|
|
1829
|
+
type: Input
|
|
1830
|
+
}], deleted: [{
|
|
1831
|
+
type: Output
|
|
1832
|
+
}] } });
|
|
1833
|
+
|
|
1834
|
+
class ProductTaxListComponent extends TechlifyListingControllerInterface {
|
|
1835
|
+
product;
|
|
1836
|
+
displayedColumns = ["#", "Tax", "Actions"];
|
|
1837
|
+
ngOnInit() {
|
|
1838
|
+
this.loadData();
|
|
1839
|
+
}
|
|
1840
|
+
loadData() {
|
|
1841
|
+
this.models = this.product?.taxes ?? [];
|
|
1842
|
+
}
|
|
1843
|
+
onCreated(productTax) {
|
|
1844
|
+
this.models.unshift(productTax);
|
|
1845
|
+
this.models = [...this.models];
|
|
1846
|
+
}
|
|
1847
|
+
onDeleted(index) {
|
|
1848
|
+
this.models.splice(index, 1);
|
|
1849
|
+
this.models = [...this.models];
|
|
1850
|
+
}
|
|
1851
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1852
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductTaxListComponent, selector: "app-product-tax-list", inputs: { product: "product" }, usesInheritance: true, ngImport: i0, template: "<mat-card>\n <mat-card-content\n class=\"pb-3 d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> percent </span>\n <strong class=\"mb-0 text-dark\">Product Taxes</strong>\n </div>\n <app-product-tax-form-button\n [product]=\"product\"\n (saved)=\"onCreated($event)\"\n ></app-product-tax-form-button>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\">\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"Tax\">\n <th mat-header-cell *matHeaderCellDef>Tax</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">\n {{ element?.tax?.title }} ({{ element?.tax?.code }})\n </p>\n <small class=\"text-secondary\"\n >{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small\n >\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">\n <app-product-tax-delete-button\n [productTax]=\"element\"\n (deleted)=\"onDeleted(i)\"\n ></app-product-tax-delete-button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n </mat-card-content>\n</mat-card>\n", dependencies: [{ kind: "component", type: i14.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i14.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i14.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i14.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i14.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i14.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i14.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i14.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i14.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i14.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ProductTaxFormButtonComponent, selector: "app-product-tax-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "component", type: ProductTaxDeleteButtonComponent, selector: "app-product-tax-delete-button", inputs: ["productTax"], outputs: ["deleted"] }], preserveWhitespaces: true });
|
|
1853
|
+
}
|
|
1854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, decorators: [{
|
|
1855
|
+
type: Component,
|
|
1856
|
+
args: [{ selector: "app-product-tax-list", template: "<mat-card>\n <mat-card-content\n class=\"pb-3 d-flex justify-content-between align-items-center gap-3\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> percent </span>\n <strong class=\"mb-0 text-dark\">Product Taxes</strong>\n </div>\n <app-product-tax-form-button\n [product]=\"product\"\n (saved)=\"onCreated($event)\"\n ></app-product-tax-form-button>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\">\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"Tax\">\n <th mat-header-cell *matHeaderCellDef>Tax</th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\">\n {{ element?.tax?.title }} ({{ element?.tax?.code }})\n </p>\n <small class=\"text-secondary\"\n >{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small\n >\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">\n <app-product-tax-delete-button\n [productTax]=\"element\"\n (deleted)=\"onDeleted(i)\"\n ></app-product-tax-delete-button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n </mat-card-content>\n</mat-card>\n" }]
|
|
1857
|
+
}], propDecorators: { product: [{
|
|
1858
|
+
type: Input
|
|
1859
|
+
}] } });
|
|
1860
|
+
|
|
1861
|
+
class StockSummaryService {
|
|
1862
|
+
httpService;
|
|
1863
|
+
constructor(httpService) {
|
|
1864
|
+
this.httpService = httpService;
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Get the stocks summary.
|
|
1868
|
+
*
|
|
1869
|
+
* @param params
|
|
1870
|
+
*/
|
|
1871
|
+
summary(params) {
|
|
1872
|
+
return this.httpService.get("api/stocks-summary", { params });
|
|
1873
|
+
}
|
|
1874
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1875
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, providedIn: "root" });
|
|
1876
|
+
}
|
|
1877
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, decorators: [{
|
|
1878
|
+
type: Injectable,
|
|
1879
|
+
args: [{
|
|
1880
|
+
providedIn: "root",
|
|
1881
|
+
}]
|
|
1882
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
1883
|
+
|
|
1884
|
+
class ProductDeleteButtonComponent {
|
|
1885
|
+
matDialog;
|
|
1886
|
+
productService;
|
|
1887
|
+
alertService;
|
|
1888
|
+
product;
|
|
1889
|
+
deleted = new EventEmitter();
|
|
1890
|
+
isDeleting;
|
|
1891
|
+
constructor(matDialog, productService, alertService) {
|
|
1892
|
+
this.matDialog = matDialog;
|
|
1893
|
+
this.productService = productService;
|
|
1894
|
+
this.alertService = alertService;
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Delete the product.
|
|
1898
|
+
*/
|
|
1899
|
+
deleteProduct() {
|
|
1900
|
+
this.isDeleting = true;
|
|
1901
|
+
this.productService.delete(this.product).subscribe({
|
|
1902
|
+
next: () => {
|
|
1903
|
+
this.deleted.emit();
|
|
1904
|
+
this.isDeleting = false;
|
|
1905
|
+
this.matDialog.closeAll();
|
|
1906
|
+
this.alertService.addAlert("Product deleted successfully!", "success");
|
|
1907
|
+
},
|
|
1908
|
+
error: () => (this.isDeleting = false),
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Show delete product dialog.
|
|
1913
|
+
*
|
|
1914
|
+
* @param templateRef
|
|
1915
|
+
*/
|
|
1916
|
+
showDeleteDialog(templateRef) {
|
|
1917
|
+
this.matDialog.open(templateRef, { width: "500px" });
|
|
1918
|
+
}
|
|
1919
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductDeleteButtonComponent, deps: [{ token: i1$1.MatDialog }, { token: ProductService }, { token: i1.AlertService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1920
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductDeleteButtonComponent, selector: "app-product-delete-button", inputs: { product: "product" }, outputs: { deleted: "deleted" }, ngImport: i0, template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteProductDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteProductDialog>\n <h3 mat-dialog-title>Delete Product</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the\n <strong>{{ product?.name }}</strong> ?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"deleteProduct()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i7$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
|
|
1921
|
+
}
|
|
1922
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductDeleteButtonComponent, decorators: [{
|
|
1923
|
+
type: Component,
|
|
1924
|
+
args: [{ selector: "app-product-delete-button", template: "<mat-icon\n class=\"cursor-pointer text-secondary\"\n (click)=\"showDeleteDialog(deleteProductDialog)\"\n>\n delete\n</mat-icon>\n\n<ng-template #deleteProductDialog>\n <h3 mat-dialog-title>Delete Product</h3>\n <div mat-dialog-content>\n Are you sure? You want to delete the\n <strong>{{ product?.name }}</strong> ?\n </div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-raised-button\n color=\"warn\"\n (click)=\"deleteProduct()\"\n >\n Delete\n </button>\n <button\n [disabled]=\"isDeleting\"\n type=\"button\"\n mat-flat-button\n mat-dialog-close\n >\n Cancel\n </button>\n </div>\n</ng-template>\n" }]
|
|
1925
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductService }, { type: i1.AlertService }], propDecorators: { product: [{
|
|
1926
|
+
type: Input
|
|
1927
|
+
}], deleted: [{
|
|
1928
|
+
type: Output
|
|
1929
|
+
}] } });
|
|
1930
|
+
|
|
1931
|
+
class ProductBasicInfoComponent {
|
|
1932
|
+
stockSummaryService;
|
|
1933
|
+
product;
|
|
1934
|
+
saved = new EventEmitter();
|
|
1935
|
+
deleted = new EventEmitter();
|
|
1936
|
+
stockSummary;
|
|
1937
|
+
constructor(stockSummaryService) {
|
|
1938
|
+
this.stockSummaryService = stockSummaryService;
|
|
1939
|
+
}
|
|
1940
|
+
ngOnInit() {
|
|
1941
|
+
if (this.product) {
|
|
1942
|
+
this.loadProductStocksSummary();
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
onProductSaved(product) {
|
|
1946
|
+
this.product = product;
|
|
1947
|
+
this.saved.emit(this.product);
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
* Load product stocks summary.
|
|
1951
|
+
*/
|
|
1952
|
+
loadProductStocksSummary() {
|
|
1953
|
+
const params = {
|
|
1954
|
+
product_ids: this.product?.id,
|
|
1955
|
+
include: "stock_receipts_quantity_sum,stock_issuances_quantity_sum,stock_quantity_remaining",
|
|
1956
|
+
};
|
|
1957
|
+
this.stockSummaryService.summary(params).subscribe({
|
|
1958
|
+
next: (response) => {
|
|
1959
|
+
this.stockSummary = response;
|
|
1960
|
+
},
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, deps: [{ token: StockSummaryService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductBasicInfoComponent, selector: "app-product-basic-info", inputs: { product: "product" }, outputs: { saved: "saved", deleted: "deleted" }, ngImport: i0, template: "<mat-card *ngIf=\"product\" class=\"w-100\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center mb-1 mb-2\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">Product Information</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button\n [product]=\"product\"\n (saved)=\"onProductSaved($event)\"\n ></app-product-form-button>\n <app-product-delete-button\n [product]=\"product\"\n (deleted)=\"deleted.emit()\"\n ></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"mt-3\">\n <h3 class=\"mb-1 font-weight-bold\">{{ product?.name }}</h3>\n <div class=\"d-flex flex-wrap gap-1\">\n <span\n class=\"badge badge-primary\"\n *ngFor=\"let category of product?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex justify-content-between align-items-start\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-5 d-flex justify-content-between align-items-start\"\n >\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Receipts</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> arrow_downward </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_receipts_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_receipt\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_receipt?.date | date }}\n </small>\n </div>\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Issuances</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_issuances_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_issuance\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_issuance?.date | date }}\n </small>\n </div>\n </mat-card-content>\n\n <mat-card-content\n *ngIf=\"stockSummary\"\n class=\"mt-3 d-flex justify-content-center align-items-center\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">On Hand</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> inventory_2 </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_quantity_remaining }}\n </p>\n </div>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ProductFormButtonComponent, selector: "app-product-form-button", inputs: ["product"], outputs: ["saved"] }, { kind: "component", type: ProductDeleteButtonComponent, selector: "app-product-delete-button", inputs: ["product"], outputs: ["deleted"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1965
|
+
}
|
|
1966
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, decorators: [{
|
|
1967
|
+
type: Component,
|
|
1968
|
+
args: [{ selector: "app-product-basic-info", template: "<mat-card *ngIf=\"product\" class=\"w-100\">\n <mat-card-content\n class=\"d-flex justify-content-between align-items-center mb-1 mb-2\"\n >\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">Product Information</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button\n [product]=\"product\"\n (saved)=\"onProductSaved($event)\"\n ></app-product-form-button>\n <app-product-delete-button\n [product]=\"product\"\n (deleted)=\"deleted.emit()\"\n ></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n <mat-card-content class=\"mt-3\">\n <h3 class=\"mb-1 font-weight-bold\">{{ product?.name }}</h3>\n <div class=\"d-flex flex-wrap gap-1\">\n <span\n class=\"badge badge-primary\"\n *ngFor=\"let category of product?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex justify-content-between align-items-start\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content\n class=\"mt-5 d-flex justify-content-between align-items-start\"\n >\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Receipts</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> arrow_downward </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_receipts_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_receipt\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_receipt?.date | date }}\n </small>\n </div>\n <div\n *ngIf=\"stockSummary\"\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">Stock Issuances</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> ungroup </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_issuances_quantity_sum }}\n </p>\n </div>\n <small *ngIf=\"product?.last_stock_issuance\" class=\"text-secondary\">\n Last Added On {{ product?.last_stock_issuance?.date | date }}\n </small>\n </div>\n </mat-card-content>\n\n <mat-card-content\n *ngIf=\"stockSummary\"\n class=\"mt-3 d-flex justify-content-center align-items-center\"\n >\n <div\n class=\"d-flex flex-column justify-content-start align-items-start gap-1\"\n >\n <small class=\"text-secondary\">On Hand</small>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> inventory_2 </span>\n <p class=\"mb-0\" style=\"font-size: 24px\">\n {{ stockSummary?.stock_quantity_remaining }}\n </p>\n </div>\n </div>\n </mat-card-content>\n</mat-card>\n" }]
|
|
1969
|
+
}], ctorParameters: () => [{ type: StockSummaryService }], propDecorators: { product: [{
|
|
1970
|
+
type: Input
|
|
1971
|
+
}], saved: [{
|
|
1972
|
+
type: Output
|
|
1973
|
+
}], deleted: [{
|
|
1974
|
+
type: Output
|
|
1975
|
+
}] } });
|
|
1976
|
+
|
|
1977
|
+
class ProductViewPageComponent {
|
|
1978
|
+
productService;
|
|
1979
|
+
activatedRoute;
|
|
1980
|
+
location;
|
|
1981
|
+
product;
|
|
1982
|
+
id;
|
|
1983
|
+
isLoading;
|
|
1984
|
+
constructor(productService, activatedRoute, location) {
|
|
1985
|
+
this.productService = productService;
|
|
1986
|
+
this.activatedRoute = activatedRoute;
|
|
1987
|
+
this.location = location;
|
|
1988
|
+
this.id = this.activatedRoute.snapshot.params?.["id"];
|
|
1989
|
+
}
|
|
1990
|
+
ngOnInit() {
|
|
1991
|
+
if (this.id) {
|
|
1992
|
+
this.getProduct(this.id);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Get the product details.
|
|
1997
|
+
*
|
|
1998
|
+
* @param productId
|
|
1999
|
+
*/
|
|
2000
|
+
getProduct(productId) {
|
|
2001
|
+
this.isLoading = true;
|
|
2002
|
+
const params = {
|
|
2003
|
+
with: "type,measure,incomeAccount,expenseAccount,categories,lastStockReceipt,lastStockIssuance,taxes.tax.type",
|
|
2004
|
+
};
|
|
2005
|
+
this.productService.show(productId, params).subscribe({
|
|
2006
|
+
next: (result) => {
|
|
2007
|
+
this.isLoading = false;
|
|
2008
|
+
this.product = result?.item;
|
|
2009
|
+
},
|
|
2010
|
+
error: () => (this.isLoading = false),
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Handle the on product update event.
|
|
2015
|
+
*
|
|
2016
|
+
* @param product
|
|
2017
|
+
*/
|
|
2018
|
+
onProductUpdated(product) {
|
|
2019
|
+
this.getProduct(this.id);
|
|
2020
|
+
}
|
|
2021
|
+
/**
|
|
2022
|
+
* Handle on product delete event.
|
|
2023
|
+
*/
|
|
2024
|
+
onProductDeleted() {
|
|
2025
|
+
this.location.back();
|
|
2026
|
+
}
|
|
2027
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductViewPageComponent, deps: [{ token: ProductService }, { token: i2.ActivatedRoute }, { token: i4.Location }], target: i0.ɵɵFactoryTarget.Component });
|
|
2028
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductViewPageComponent, selector: "app-product-view-page", ngImport: i0, template: "<mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n\n<div\n *ngIf=\"product\"\n class=\"d-flex justify-content-start align-items-start gap-3\"\n>\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info\n [product]=\"product\"\n #productBasicInfoComponent\n (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"\n ></app-product-basic-info>\n\n <app-product-tax-list [product]=\"product\"></app-product-tax-list>\n </div>\n <div style=\"width: calc(75%)\" class=\"d-flex flex-column gap-3\">\n <app-stock-receipts-list-page\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-receipts-list-page>\n\n <app-stock-issuances-list\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-issuances-list>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: StockReceiptsListPageComponent, selector: "app-stock-receipts-list-page", inputs: ["product"], outputs: ["listUpdated"] }, { kind: "component", type: StockIssuancesListComponent, selector: "app-stock-issuances-list", inputs: ["product", "issuableType", "issuableId", "label"], outputs: ["listUpdated"] }, { kind: "component", type: ProductTaxListComponent, selector: "app-product-tax-list", inputs: ["product"] }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: ProductBasicInfoComponent, selector: "app-product-basic-info", inputs: ["product"], outputs: ["saved", "deleted"] }], preserveWhitespaces: true });
|
|
2029
|
+
}
|
|
2030
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductViewPageComponent, decorators: [{
|
|
2031
|
+
type: Component,
|
|
2032
|
+
args: [{ selector: "app-product-view-page", template: "<mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n\n<div\n *ngIf=\"product\"\n class=\"d-flex justify-content-start align-items-start gap-3\"\n>\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info\n [product]=\"product\"\n #productBasicInfoComponent\n (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"\n ></app-product-basic-info>\n\n <app-product-tax-list [product]=\"product\"></app-product-tax-list>\n </div>\n <div style=\"width: calc(75%)\" class=\"d-flex flex-column gap-3\">\n <app-stock-receipts-list-page\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-receipts-list-page>\n\n <app-stock-issuances-list\n [product]=\"product\"\n (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"\n ></app-stock-issuances-list>\n </div>\n</div>\n" }]
|
|
2033
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2.ActivatedRoute }, { type: i4.Location }] });
|
|
2034
|
+
|
|
2035
|
+
class ProductImportPageComponent {
|
|
2036
|
+
importConfig = {
|
|
2037
|
+
apiUrl: "api/products-import",
|
|
2038
|
+
title: "Products",
|
|
2039
|
+
importType: "product",
|
|
2040
|
+
properties: [
|
|
2041
|
+
{
|
|
2042
|
+
label: "Name",
|
|
2043
|
+
value: "name",
|
|
2044
|
+
type: "text",
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
label: "SKU",
|
|
2048
|
+
value: "sku",
|
|
2049
|
+
type: "text",
|
|
2050
|
+
},
|
|
2051
|
+
{
|
|
2052
|
+
label: "Initial Quantity",
|
|
2053
|
+
value: "initial_quantity",
|
|
2054
|
+
type: "number",
|
|
2055
|
+
},
|
|
2056
|
+
{
|
|
2057
|
+
label: "Initial Quantity Date",
|
|
2058
|
+
value: "initial_quantity_date",
|
|
2059
|
+
type: "date",
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
label: "Reorder Point",
|
|
2063
|
+
value: "reorder_point",
|
|
2064
|
+
type: "number",
|
|
2065
|
+
},
|
|
2066
|
+
{
|
|
2067
|
+
label: "Measure",
|
|
2068
|
+
value: "measure",
|
|
2069
|
+
type: "text",
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
label: "Categories",
|
|
2073
|
+
value: "categories",
|
|
2074
|
+
type: "text",
|
|
2075
|
+
},
|
|
2076
|
+
],
|
|
2077
|
+
sampleFile: {
|
|
2078
|
+
name: "Products Import",
|
|
2079
|
+
path: "assets/product/product-import-sample.csv",
|
|
2080
|
+
},
|
|
2081
|
+
importHistory: {
|
|
2082
|
+
isEnabled: true,
|
|
2083
|
+
type: "product",
|
|
2084
|
+
apiUrl: "api/import-histories",
|
|
2085
|
+
},
|
|
2086
|
+
viewRouterLink: "/inventory/products/",
|
|
2087
|
+
};
|
|
2088
|
+
constructor() { }
|
|
2089
|
+
ngOnInit() { }
|
|
2090
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2091
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductImportPageComponent, selector: "app-product-import-page", ngImport: i0, template: "<app-import-csv [config]=\"importConfig\"></app-import-csv>\n", styles: [""], dependencies: [{ kind: "component", type: i1.ImportCsvComponent, selector: "app-import-csv", inputs: ["config"] }], preserveWhitespaces: true });
|
|
2092
|
+
}
|
|
2093
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, decorators: [{
|
|
2094
|
+
type: Component,
|
|
2095
|
+
args: [{ selector: "app-product-import-page", template: "<app-import-csv [config]=\"importConfig\"></app-import-csv>\n" }]
|
|
2096
|
+
}], ctorParameters: () => [] });
|
|
2097
|
+
|
|
2098
|
+
const routes$2 = [
|
|
2099
|
+
{
|
|
2100
|
+
path: "",
|
|
2101
|
+
component: ProductNavBarComponent,
|
|
2102
|
+
children: [
|
|
2103
|
+
{
|
|
2104
|
+
path: "",
|
|
2105
|
+
component: ProductListComponent,
|
|
2106
|
+
canLoad: [AuthenticationGuard],
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
2109
|
+
path: "import",
|
|
2110
|
+
component: ProductImportPageComponent,
|
|
2111
|
+
canLoad: [AuthenticationGuard],
|
|
2112
|
+
},
|
|
2113
|
+
{
|
|
2114
|
+
path: "measure",
|
|
2115
|
+
component: ProductMeasuresListComponent,
|
|
2116
|
+
canLoad: [AuthenticationGuard],
|
|
2117
|
+
},
|
|
2118
|
+
{
|
|
2119
|
+
path: ":id/view",
|
|
2120
|
+
component: ProductViewPageComponent,
|
|
2121
|
+
canLoad: [AuthenticationGuard],
|
|
2122
|
+
},
|
|
2123
|
+
{
|
|
2124
|
+
path: "**",
|
|
2125
|
+
redirectTo: "",
|
|
2126
|
+
pathMatch: "full",
|
|
2127
|
+
canLoad: [AuthenticationGuard],
|
|
2128
|
+
},
|
|
2129
|
+
],
|
|
2130
|
+
},
|
|
2131
|
+
];
|
|
2132
|
+
class ProductRoutingModule {
|
|
2133
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2134
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
2135
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [RouterModule.forChild(routes$2), RouterModule] });
|
|
2136
|
+
}
|
|
2137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, decorators: [{
|
|
2138
|
+
type: NgModule,
|
|
2139
|
+
args: [{
|
|
2140
|
+
imports: [RouterModule.forChild(routes$2)],
|
|
2141
|
+
exports: [RouterModule],
|
|
2142
|
+
}]
|
|
2143
|
+
}] });
|
|
2144
|
+
|
|
2145
|
+
class PayeeSelectorModule {
|
|
2146
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2147
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, declarations: [PayeeSelectorComponent], imports: [CommonModule,
|
|
2148
|
+
MatFormFieldModule,
|
|
2149
|
+
ReactiveFormsModule,
|
|
2150
|
+
SearchableSelectorModule,
|
|
2151
|
+
FormsModule], exports: [PayeeSelectorComponent] });
|
|
2152
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, imports: [CommonModule,
|
|
2153
|
+
MatFormFieldModule,
|
|
2154
|
+
ReactiveFormsModule,
|
|
2155
|
+
SearchableSelectorModule,
|
|
2156
|
+
FormsModule] });
|
|
2157
|
+
}
|
|
2158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, decorators: [{
|
|
2159
|
+
type: NgModule,
|
|
2160
|
+
args: [{
|
|
2161
|
+
declarations: [PayeeSelectorComponent],
|
|
2162
|
+
exports: [PayeeSelectorComponent],
|
|
2163
|
+
imports: [
|
|
2164
|
+
CommonModule,
|
|
2165
|
+
MatFormFieldModule,
|
|
2166
|
+
ReactiveFormsModule,
|
|
2167
|
+
SearchableSelectorModule,
|
|
2168
|
+
FormsModule,
|
|
2169
|
+
],
|
|
2170
|
+
}]
|
|
2171
|
+
}] });
|
|
2172
|
+
|
|
2173
|
+
class StockReceiptFormModule {
|
|
2174
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2175
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, declarations: [StockReceiptFormComponent, StockReceiptFormButtonComponent], imports: [CommonModule,
|
|
2176
|
+
MatTooltipModule,
|
|
2177
|
+
MatDialogModule,
|
|
2178
|
+
PayeeSelectorModule,
|
|
2179
|
+
ReactiveFormsModule,
|
|
2180
|
+
MatFormFieldModule,
|
|
2181
|
+
MatInputModule,
|
|
2182
|
+
MatDatepickerModule,
|
|
2183
|
+
MatButtonModule], exports: [StockReceiptFormButtonComponent] });
|
|
2184
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, imports: [CommonModule,
|
|
2185
|
+
MatTooltipModule,
|
|
2186
|
+
MatDialogModule,
|
|
2187
|
+
PayeeSelectorModule,
|
|
2188
|
+
ReactiveFormsModule,
|
|
2189
|
+
MatFormFieldModule,
|
|
2190
|
+
MatInputModule,
|
|
2191
|
+
MatDatepickerModule,
|
|
2192
|
+
MatButtonModule] });
|
|
2193
|
+
}
|
|
2194
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, decorators: [{
|
|
2195
|
+
type: NgModule,
|
|
2196
|
+
args: [{
|
|
2197
|
+
declarations: [StockReceiptFormComponent, StockReceiptFormButtonComponent],
|
|
2198
|
+
exports: [StockReceiptFormButtonComponent],
|
|
2199
|
+
imports: [
|
|
2200
|
+
CommonModule,
|
|
2201
|
+
MatTooltipModule,
|
|
2202
|
+
MatDialogModule,
|
|
2203
|
+
PayeeSelectorModule,
|
|
2204
|
+
ReactiveFormsModule,
|
|
2205
|
+
MatFormFieldModule,
|
|
2206
|
+
MatInputModule,
|
|
2207
|
+
MatDatepickerModule,
|
|
2208
|
+
MatButtonModule,
|
|
2209
|
+
],
|
|
2210
|
+
}]
|
|
2211
|
+
}] });
|
|
2212
|
+
|
|
2213
|
+
class StockIssueFormModule {
|
|
2214
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2215
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, declarations: [StockIssueFormComponent, StockIssueFormButtonComponent], imports: [CommonModule,
|
|
2216
|
+
ReactiveFormsModule,
|
|
2217
|
+
MatFormFieldModule,
|
|
2218
|
+
MatInputModule,
|
|
2219
|
+
MatDatepickerModule,
|
|
2220
|
+
MatButtonModule,
|
|
2221
|
+
MatDialogModule,
|
|
2222
|
+
MatTooltipModule,
|
|
2223
|
+
SearchableSelectorModule], exports: [StockIssueFormButtonComponent] });
|
|
2224
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, imports: [CommonModule,
|
|
2225
|
+
ReactiveFormsModule,
|
|
2226
|
+
MatFormFieldModule,
|
|
2227
|
+
MatInputModule,
|
|
2228
|
+
MatDatepickerModule,
|
|
2229
|
+
MatButtonModule,
|
|
2230
|
+
MatDialogModule,
|
|
2231
|
+
MatTooltipModule,
|
|
2232
|
+
SearchableSelectorModule] });
|
|
2233
|
+
}
|
|
2234
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, decorators: [{
|
|
2235
|
+
type: NgModule,
|
|
2236
|
+
args: [{
|
|
2237
|
+
declarations: [StockIssueFormComponent, StockIssueFormButtonComponent],
|
|
2238
|
+
exports: [StockIssueFormButtonComponent],
|
|
2239
|
+
imports: [
|
|
2240
|
+
CommonModule,
|
|
2241
|
+
ReactiveFormsModule,
|
|
2242
|
+
MatFormFieldModule,
|
|
2243
|
+
MatInputModule,
|
|
2244
|
+
MatDatepickerModule,
|
|
2245
|
+
MatButtonModule,
|
|
2246
|
+
MatDialogModule,
|
|
2247
|
+
MatTooltipModule,
|
|
2248
|
+
SearchableSelectorModule,
|
|
2249
|
+
],
|
|
2250
|
+
}]
|
|
2251
|
+
}] });
|
|
2252
|
+
|
|
2253
|
+
const routes$1 = [
|
|
2254
|
+
{
|
|
2255
|
+
path: "",
|
|
2256
|
+
component: StockReceiptsListPageComponent,
|
|
2257
|
+
},
|
|
2258
|
+
];
|
|
2259
|
+
class StockReceiptsRoutingModule {
|
|
2260
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2261
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
2262
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, imports: [RouterModule.forChild(routes$1), RouterModule] });
|
|
2263
|
+
}
|
|
2264
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, decorators: [{
|
|
2265
|
+
type: NgModule,
|
|
2266
|
+
args: [{
|
|
2267
|
+
imports: [RouterModule.forChild(routes$1)],
|
|
2268
|
+
exports: [RouterModule],
|
|
2269
|
+
}]
|
|
2270
|
+
}] });
|
|
2271
|
+
|
|
2272
|
+
class TechlifyFilterModule {
|
|
2273
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2274
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, declarations: [TechlifyFilterComponent], imports: [CommonModule,
|
|
2275
|
+
ReactiveFormsModule,
|
|
2276
|
+
FlexLayoutModule,
|
|
2277
|
+
SearchableSelectorModule,
|
|
2278
|
+
TimelineFilterModule,
|
|
2279
|
+
MaterialModule], exports: [TechlifyFilterComponent] });
|
|
2280
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, imports: [CommonModule,
|
|
2281
|
+
ReactiveFormsModule,
|
|
2282
|
+
FlexLayoutModule,
|
|
2283
|
+
SearchableSelectorModule,
|
|
2284
|
+
TimelineFilterModule,
|
|
2285
|
+
MaterialModule] });
|
|
2286
|
+
}
|
|
2287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, decorators: [{
|
|
2288
|
+
type: NgModule,
|
|
2289
|
+
args: [{
|
|
2290
|
+
declarations: [TechlifyFilterComponent],
|
|
2291
|
+
imports: [
|
|
2292
|
+
CommonModule,
|
|
2293
|
+
ReactiveFormsModule,
|
|
2294
|
+
FlexLayoutModule,
|
|
2295
|
+
SearchableSelectorModule,
|
|
2296
|
+
TimelineFilterModule,
|
|
2297
|
+
MaterialModule,
|
|
2298
|
+
],
|
|
2299
|
+
exports: [TechlifyFilterComponent],
|
|
2300
|
+
}]
|
|
2301
|
+
}] });
|
|
2302
|
+
|
|
2303
|
+
class StockReceiptsModule {
|
|
2304
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2305
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, declarations: [StockReceiptsListPageComponent,
|
|
2306
|
+
StockReceiptDeleteButtonComponent], imports: [CommonModule,
|
|
2307
|
+
StockReceiptsRoutingModule,
|
|
2308
|
+
MatCardModule,
|
|
2309
|
+
TechlifyFilterModule,
|
|
2310
|
+
MatTableModule,
|
|
2311
|
+
MatFormFieldModule,
|
|
2312
|
+
SearchableSelectorModule,
|
|
2313
|
+
TimelineFilterModule,
|
|
2314
|
+
ReactiveFormsModule,
|
|
2315
|
+
PayeeSelectorModule,
|
|
2316
|
+
MatProgressBarModule,
|
|
2317
|
+
InfiniteScrollModule,
|
|
2318
|
+
MaterialModule,
|
|
2319
|
+
StockReceiptFormModule], exports: [StockReceiptDeleteButtonComponent, StockReceiptsListPageComponent] });
|
|
2320
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, imports: [CommonModule,
|
|
2321
|
+
StockReceiptsRoutingModule,
|
|
2322
|
+
MatCardModule,
|
|
2323
|
+
TechlifyFilterModule,
|
|
2324
|
+
MatTableModule,
|
|
2325
|
+
MatFormFieldModule,
|
|
2326
|
+
SearchableSelectorModule,
|
|
2327
|
+
TimelineFilterModule,
|
|
2328
|
+
ReactiveFormsModule,
|
|
2329
|
+
PayeeSelectorModule,
|
|
2330
|
+
MatProgressBarModule,
|
|
2331
|
+
InfiniteScrollModule,
|
|
2332
|
+
MaterialModule,
|
|
2333
|
+
StockReceiptFormModule] });
|
|
2334
|
+
}
|
|
2335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, decorators: [{
|
|
2336
|
+
type: NgModule,
|
|
2337
|
+
args: [{
|
|
2338
|
+
declarations: [
|
|
2339
|
+
StockReceiptsListPageComponent,
|
|
2340
|
+
StockReceiptDeleteButtonComponent,
|
|
2341
|
+
],
|
|
2342
|
+
exports: [StockReceiptDeleteButtonComponent, StockReceiptsListPageComponent],
|
|
2343
|
+
imports: [
|
|
2344
|
+
CommonModule,
|
|
2345
|
+
StockReceiptsRoutingModule,
|
|
2346
|
+
MatCardModule,
|
|
2347
|
+
TechlifyFilterModule,
|
|
2348
|
+
MatTableModule,
|
|
2349
|
+
MatFormFieldModule,
|
|
2350
|
+
SearchableSelectorModule,
|
|
2351
|
+
TimelineFilterModule,
|
|
2352
|
+
ReactiveFormsModule,
|
|
2353
|
+
PayeeSelectorModule,
|
|
2354
|
+
MatProgressBarModule,
|
|
2355
|
+
InfiniteScrollModule,
|
|
2356
|
+
MaterialModule,
|
|
2357
|
+
StockReceiptFormModule,
|
|
2358
|
+
],
|
|
2359
|
+
}]
|
|
2360
|
+
}] });
|
|
2361
|
+
|
|
2362
|
+
var stockReceipts_module = /*#__PURE__*/Object.freeze({
|
|
2363
|
+
__proto__: null,
|
|
2364
|
+
StockReceiptsModule: StockReceiptsModule
|
|
2365
|
+
});
|
|
2366
|
+
|
|
2367
|
+
class StockIssuanceDeleteButtonModule {
|
|
2368
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2369
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, declarations: [StockIssuanceDeleteButtonComponent], imports: [CommonModule, MaterialModule], exports: [StockIssuanceDeleteButtonComponent] });
|
|
2370
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, imports: [CommonModule, MaterialModule] });
|
|
2371
|
+
}
|
|
2372
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, decorators: [{
|
|
2373
|
+
type: NgModule,
|
|
2374
|
+
args: [{
|
|
2375
|
+
declarations: [StockIssuanceDeleteButtonComponent],
|
|
2376
|
+
imports: [CommonModule, MaterialModule],
|
|
2377
|
+
exports: [StockIssuanceDeleteButtonComponent],
|
|
2378
|
+
}]
|
|
2379
|
+
}] });
|
|
2380
|
+
|
|
2381
|
+
class StockIssuancesListModule {
|
|
2382
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2383
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, declarations: [StockIssuancesListComponent], imports: [CommonModule,
|
|
2384
|
+
MaterialModule,
|
|
2385
|
+
TechlifyFilterModule,
|
|
2386
|
+
StockIssueFormModule,
|
|
2387
|
+
InfiniteScrollModule,
|
|
2388
|
+
StockIssuanceDeleteButtonModule,
|
|
2389
|
+
MatProgressBarModule,
|
|
2390
|
+
RouterModule], exports: [StockIssuancesListComponent] });
|
|
2391
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, imports: [CommonModule,
|
|
2392
|
+
MaterialModule,
|
|
2393
|
+
TechlifyFilterModule,
|
|
2394
|
+
StockIssueFormModule,
|
|
2395
|
+
InfiniteScrollModule,
|
|
2396
|
+
StockIssuanceDeleteButtonModule,
|
|
2397
|
+
MatProgressBarModule,
|
|
2398
|
+
RouterModule] });
|
|
2399
|
+
}
|
|
2400
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, decorators: [{
|
|
2401
|
+
type: NgModule,
|
|
2402
|
+
args: [{
|
|
2403
|
+
declarations: [StockIssuancesListComponent],
|
|
2404
|
+
imports: [
|
|
2405
|
+
CommonModule,
|
|
2406
|
+
MaterialModule,
|
|
2407
|
+
TechlifyFilterModule,
|
|
2408
|
+
StockIssueFormModule,
|
|
2409
|
+
InfiniteScrollModule,
|
|
2410
|
+
StockIssuanceDeleteButtonModule,
|
|
2411
|
+
MatProgressBarModule,
|
|
2412
|
+
RouterModule,
|
|
2413
|
+
],
|
|
2414
|
+
exports: [StockIssuancesListComponent],
|
|
2415
|
+
}]
|
|
2416
|
+
}] });
|
|
2417
|
+
|
|
2418
|
+
class ProductTaxModule {
|
|
2419
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2420
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, declarations: [ProductTaxListComponent,
|
|
2421
|
+
ProductTaxFormButtonComponent,
|
|
2422
|
+
ProductTaxDeleteButtonComponent], imports: [CommonModule,
|
|
2423
|
+
MaterialModule,
|
|
2424
|
+
ReactiveFormsModule,
|
|
2425
|
+
SearchableSelectorModule], exports: [ProductTaxListComponent] });
|
|
2426
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, imports: [CommonModule,
|
|
2427
|
+
MaterialModule,
|
|
2428
|
+
ReactiveFormsModule,
|
|
2429
|
+
SearchableSelectorModule] });
|
|
2430
|
+
}
|
|
2431
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, decorators: [{
|
|
2432
|
+
type: NgModule,
|
|
2433
|
+
args: [{
|
|
2434
|
+
declarations: [
|
|
2435
|
+
ProductTaxListComponent,
|
|
2436
|
+
ProductTaxFormButtonComponent,
|
|
2437
|
+
ProductTaxDeleteButtonComponent,
|
|
2438
|
+
],
|
|
2439
|
+
imports: [
|
|
2440
|
+
CommonModule,
|
|
2441
|
+
MaterialModule,
|
|
2442
|
+
ReactiveFormsModule,
|
|
2443
|
+
SearchableSelectorModule,
|
|
2444
|
+
],
|
|
2445
|
+
exports: [ProductTaxListComponent],
|
|
2446
|
+
}]
|
|
2447
|
+
}] });
|
|
2448
|
+
|
|
2449
|
+
class ProductModule {
|
|
2450
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2451
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, declarations: [ProductListComponent,
|
|
2452
|
+
ProductFormComponent,
|
|
2453
|
+
ProductNavBarComponent,
|
|
2454
|
+
ProductMeasuresListComponent,
|
|
2455
|
+
ProductMeasureFormComponent,
|
|
2456
|
+
ProductViewPageComponent,
|
|
2457
|
+
ProductFormButtonComponent,
|
|
2458
|
+
ProductDeleteButtonComponent,
|
|
2459
|
+
ProductBasicInfoComponent,
|
|
2460
|
+
ProductImportPageComponent], imports: [CommonModule,
|
|
2461
|
+
ProductRoutingModule,
|
|
2462
|
+
SearchableSelectorModule,
|
|
2463
|
+
TimelineFilterModule,
|
|
2464
|
+
StockReceiptFormModule,
|
|
2465
|
+
StockIssueFormModule,
|
|
2466
|
+
ImportCsvModule,
|
|
2467
|
+
StockReceiptsModule,
|
|
2468
|
+
StockIssuancesListModule,
|
|
2469
|
+
ProductTaxModule,
|
|
2470
|
+
MaterialModule,
|
|
2471
|
+
MatProgressBarModule,
|
|
2472
|
+
InfiniteScrollModule,
|
|
2473
|
+
FlexModule,
|
|
2474
|
+
ReactiveFormsModule,
|
|
2475
|
+
FormsModule,
|
|
2476
|
+
ColumnSelectorModule], exports: [ProductFormComponent,
|
|
2477
|
+
ProductBasicInfoComponent,
|
|
2478
|
+
ProductFormButtonComponent] });
|
|
2479
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, imports: [CommonModule,
|
|
2480
|
+
ProductRoutingModule,
|
|
2481
|
+
SearchableSelectorModule,
|
|
2482
|
+
TimelineFilterModule,
|
|
2483
|
+
StockReceiptFormModule,
|
|
2484
|
+
StockIssueFormModule,
|
|
2485
|
+
ImportCsvModule,
|
|
2486
|
+
StockReceiptsModule,
|
|
2487
|
+
StockIssuancesListModule,
|
|
2488
|
+
ProductTaxModule,
|
|
2489
|
+
MaterialModule,
|
|
2490
|
+
MatProgressBarModule,
|
|
2491
|
+
InfiniteScrollModule,
|
|
2492
|
+
FlexModule,
|
|
2493
|
+
ReactiveFormsModule,
|
|
2494
|
+
FormsModule,
|
|
2495
|
+
ColumnSelectorModule] });
|
|
2496
|
+
}
|
|
2497
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, decorators: [{
|
|
2498
|
+
type: NgModule,
|
|
2499
|
+
args: [{
|
|
2500
|
+
declarations: [
|
|
2501
|
+
ProductListComponent,
|
|
2502
|
+
ProductFormComponent,
|
|
2503
|
+
ProductNavBarComponent,
|
|
2504
|
+
ProductMeasuresListComponent,
|
|
2505
|
+
ProductMeasureFormComponent,
|
|
2506
|
+
ProductViewPageComponent,
|
|
2507
|
+
ProductFormButtonComponent,
|
|
2508
|
+
ProductDeleteButtonComponent,
|
|
2509
|
+
ProductBasicInfoComponent,
|
|
2510
|
+
ProductImportPageComponent,
|
|
2511
|
+
],
|
|
2512
|
+
imports: [
|
|
2513
|
+
CommonModule,
|
|
2514
|
+
ProductRoutingModule,
|
|
2515
|
+
SearchableSelectorModule,
|
|
2516
|
+
TimelineFilterModule,
|
|
2517
|
+
StockReceiptFormModule,
|
|
2518
|
+
StockIssueFormModule,
|
|
2519
|
+
ImportCsvModule,
|
|
2520
|
+
StockReceiptsModule,
|
|
2521
|
+
StockIssuancesListModule,
|
|
2522
|
+
ProductTaxModule,
|
|
2523
|
+
MaterialModule,
|
|
2524
|
+
MatProgressBarModule,
|
|
2525
|
+
InfiniteScrollModule,
|
|
2526
|
+
FlexModule,
|
|
2527
|
+
ReactiveFormsModule,
|
|
2528
|
+
FormsModule,
|
|
2529
|
+
ColumnSelectorModule,
|
|
2530
|
+
],
|
|
2531
|
+
exports: [
|
|
2532
|
+
ProductFormComponent,
|
|
2533
|
+
ProductBasicInfoComponent,
|
|
2534
|
+
ProductFormButtonComponent,
|
|
2535
|
+
],
|
|
2536
|
+
}]
|
|
2537
|
+
}] });
|
|
2538
|
+
|
|
2539
|
+
var product_module = /*#__PURE__*/Object.freeze({
|
|
2540
|
+
__proto__: null,
|
|
2541
|
+
ProductModule: ProductModule
|
|
2542
|
+
});
|
|
2543
|
+
|
|
2544
|
+
class ProductQuickSearchComponent extends TechlifyListingControllerInterface {
|
|
2545
|
+
productService;
|
|
2546
|
+
displayedColumns = ['#', 'Product', 'SKU', 'Type', 'Categories', 'On Hand', 'Actions'];
|
|
2547
|
+
searchControl = new FormControl('');
|
|
2548
|
+
constructor(productService) {
|
|
2549
|
+
super();
|
|
2550
|
+
this.productService = productService;
|
|
2551
|
+
this.lastPage = 0;
|
|
2552
|
+
this.perPage = 1000;
|
|
2553
|
+
}
|
|
2554
|
+
ngOnInit() {
|
|
2555
|
+
this.loadData();
|
|
2556
|
+
this.searchControl.valueChanges.pipe(debounceTime$1(500)).subscribe(() => this.reload());
|
|
2557
|
+
}
|
|
2558
|
+
loadData() {
|
|
2559
|
+
const params = {
|
|
2560
|
+
page: this.page,
|
|
2561
|
+
perPage: this.perPage,
|
|
2562
|
+
search: this.searchControl.value,
|
|
2563
|
+
sort_by: 'created_at|desc',
|
|
2564
|
+
with: 'type,categories',
|
|
2565
|
+
};
|
|
2566
|
+
this.isWorking = true;
|
|
2567
|
+
this.productService.index(params).subscribe({
|
|
2568
|
+
next: (response) => {
|
|
2569
|
+
this.models = this.models?.concat(response?.data);
|
|
2570
|
+
this.lastPage = response?.last_page;
|
|
2571
|
+
this.isWorking = false;
|
|
2572
|
+
},
|
|
2573
|
+
error: () => (this.isWorking = false),
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductQuickSearchComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2577
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductQuickSearchComponent, isStandalone: true, selector: "app-product-quick-search", usesInheritance: true, ngImport: i0, template: "<mat-card style=\"max-height: 460px; overflow: auto\">\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-3\">\n <h3>Products Quick Search</h3>\n\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input type=\"text\" matInput placeholder=\"Search products\" [formControl]=\"searchControl\">\n </mat-form-field>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"SKU\">\n <th mat-header-cell *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.sku }}</td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef>Type</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.type?.title }}</td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"On Hand\">\n <th mat-header-cell *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"['/inventory/products', element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n", styles: [""], dependencies: [{ kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: ProductModule }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: StockReceiptFormModule }, { kind: "component", type: StockReceiptFormButtonComponent, selector: "app-stock-receipt-form-button", inputs: ["product", "stockReceipt", "icon"], outputs: ["saved"] }, { kind: "ngmodule", type: StockIssueFormModule }, { kind: "component", type: StockIssueFormButtonComponent, selector: "app-stock-issue-form-button", inputs: ["product", "stockIssuance", "icon", "issuableType", "issuableId"], outputs: ["saved"] }], preserveWhitespaces: true });
|
|
2578
|
+
}
|
|
2579
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductQuickSearchComponent, decorators: [{
|
|
2580
|
+
type: Component,
|
|
2581
|
+
args: [{ selector: 'app-product-quick-search', standalone: true, imports: [
|
|
2582
|
+
InfiniteScrollDirective,
|
|
2583
|
+
MatCard,
|
|
2584
|
+
MatCardContent,
|
|
2585
|
+
MatCell,
|
|
2586
|
+
MatCellDef,
|
|
2587
|
+
MatColumnDef,
|
|
2588
|
+
MatHeaderCell,
|
|
2589
|
+
MatHeaderRow,
|
|
2590
|
+
MatTable,
|
|
2591
|
+
MatHeaderCellDef,
|
|
2592
|
+
RouterLink,
|
|
2593
|
+
MatHeaderRowDef,
|
|
2594
|
+
MatRowDef,
|
|
2595
|
+
MatRow,
|
|
2596
|
+
MatProgressBar,
|
|
2597
|
+
NgIf,
|
|
2598
|
+
MatFormField,
|
|
2599
|
+
MatLabel,
|
|
2600
|
+
MatInput,
|
|
2601
|
+
ReactiveFormsModule,
|
|
2602
|
+
NgForOf,
|
|
2603
|
+
MatSortHeader,
|
|
2604
|
+
MatIcon,
|
|
2605
|
+
MatTooltip,
|
|
2606
|
+
ProductModule,
|
|
2607
|
+
RouterLinkActive,
|
|
2608
|
+
StockReceiptFormModule,
|
|
2609
|
+
StockIssueFormModule,
|
|
2610
|
+
], template: "<mat-card style=\"max-height: 460px; overflow: auto\">\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-3\">\n <h3>Products Quick Search</h3>\n\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input type=\"text\" matInput placeholder=\"Search products\" [formControl]=\"searchControl\">\n </mat-form-field>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table\n mat-table\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n >\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef>#</th>\n <td mat-cell *matCellDef=\"let element; let i = index\">{{ i + 1 }}</td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef>Product</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"SKU\">\n <th mat-header-cell *matHeaderCellDef>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.sku }}</td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef>Type</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.type?.title }}</td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef>Categories</th>\n <td mat-cell *matCellDef=\"let element\" style=\"max-width: 200px\">\n <div\n *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\"\n >\n <span\n class=\"badge bg-secondary\"\n *ngFor=\"let category of element?.categories\"\n >\n {{ category?.title }}\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- On Hand Column -->\n <ng-container matColumnDef=\"On Hand\">\n <th mat-header-cell *matHeaderCellDef>On Hand</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock_balance }}\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"Actions\">\n <th mat-header-cell *matHeaderCellDef>Actions</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"text-secondary d-flex gap-1\">\n <mat-icon\n class=\"cursor-pointer\"\n matTooltip=\"View\"\n [routerLink]=\"['/inventory/products', element.id, 'view']\"\n routerLinkActive=\"route-link-active\"\n >\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button\n [product]=\"element\"\n (saved)=\"reload()\"\n ></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n</mat-card>\n" }]
|
|
2611
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
2612
|
+
|
|
2613
|
+
class InventoryDashboardPageComponent {
|
|
2614
|
+
productService;
|
|
2615
|
+
lowStockProductsCount;
|
|
2616
|
+
stockReceiptsQtySum;
|
|
2617
|
+
stockIssuanceQtySum;
|
|
2618
|
+
constructor(productService) {
|
|
2619
|
+
this.productService = productService;
|
|
2620
|
+
}
|
|
2621
|
+
ngOnInit() {
|
|
2622
|
+
this.loadProductSummary();
|
|
2623
|
+
}
|
|
2624
|
+
loadProductSummary() {
|
|
2625
|
+
const params = {
|
|
2626
|
+
include: 'low_stock_products_count,stock_receipts_quantity_sum,stock_issuances_quantity_sum',
|
|
2627
|
+
date_from: moment().startOf('month').format('YYYY-MM-DD'),
|
|
2628
|
+
date_to: moment().endOf('month').format('YYYY-MM-DD'),
|
|
2629
|
+
};
|
|
2630
|
+
this.productService.summary(params).subscribe({
|
|
2631
|
+
next: (response) => {
|
|
2632
|
+
this.lowStockProductsCount = response?.low_stock_products_count;
|
|
2633
|
+
this.stockReceiptsQtySum = response?.stock_receipts_quantity_sum;
|
|
2634
|
+
this.stockIssuanceQtySum = response?.stock_issuances_quantity_sum;
|
|
2635
|
+
}
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryDashboardPageComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2639
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: InventoryDashboardPageComponent, selector: "app-inventory-dashboard-page", ngImport: i0, template: "<div class=\"d-flex justify-content-start align-items-start gap-3 vh-100\">\n <div class=\"row\" style=\"width: calc(100% - 300px)\">\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\" style=\"color: #F5222D !important;\">\n inventory_2\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Low Stock Products</small>\n <h1 class=\"mb-0 fw-bold\">{{ lowStockProductsCount | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\">\n arrow_circle_down\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Products Received This Month</small>\n <h1 class=\"mb-0 fw-bold\">{{ stockReceiptsQtySum | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\">\n arrow_circle_up\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Products Issued This Month</small>\n <h1 class=\"mb-0 fw-bold\">{{ stockIssuanceQtySum | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-product-quick-search></app-product-quick-search>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-low-stock-products-widget></app-low-stock-products-widget>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-product-summary-chart title=\"Product By Category\"></app-product-summary-chart>\n </div>\n </div>\n <div style=\"width: 300px\" class=\"d-flex flex-column gap-3 h-100\">\n <mat-card class=\"h-100\">\n <mat-card-content>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-icon>flag</mat-icon>\n <h3 class=\"mb-0 fw-bold\">Reports</h3>\n </div>\n </mat-card-content>\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start gap-3\">\n <a\n class=\"d-flex justify-content-start align-items-center gap-2 text-decoration-none text-dark\"\n routerLink=\"/inventory/reports/low-stock-report\"\n >\n <span class=\"material-symbols-outlined fs-3\">\n description\n </span>\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <span class=\"material-symbols-outlined\">\n chevron_forward\n </span>\n </a>\n <a\n class=\"d-flex justify-content-start align-items-center gap-2 text-decoration-none text-dark cursor-pointer\"\n routerLink=\"/inventory/reports/inventory-value-report\"\n >\n <span class=\"material-symbols-outlined fs-3\">\n description\n </span>\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <span class=\"material-symbols-outlined\">\n chevron_forward\n </span>\n </a>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: LowStockProductsWidgetComponent, selector: "app-low-stock-products-widget" }, { kind: "component", type: ProductSummaryChartComponent, selector: "app-product-summary-chart", inputs: ["height", "title"] }, { kind: "component", type: ProductQuickSearchComponent, selector: "app-product-quick-search" }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }], preserveWhitespaces: true });
|
|
2640
|
+
}
|
|
2641
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryDashboardPageComponent, decorators: [{
|
|
2642
|
+
type: Component,
|
|
2643
|
+
args: [{ selector: 'app-inventory-dashboard-page', template: "<div class=\"d-flex justify-content-start align-items-start gap-3 vh-100\">\n <div class=\"row\" style=\"width: calc(100% - 300px)\">\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\" style=\"color: #F5222D !important;\">\n inventory_2\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Low Stock Products</small>\n <h1 class=\"mb-0 fw-bold\">{{ lowStockProductsCount | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\">\n arrow_circle_down\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Products Received This Month</small>\n <h1 class=\"mb-0 fw-bold\">{{ stockReceiptsQtySum | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-4 mb-3\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-center align-items-center gap-3\">\n <span class=\"material-symbols-outlined fs-1 fw-bold\">\n arrow_circle_up\n </span>\n <div class=\"d-flex flex-column gap-0\">\n <small class=\"text-secondary\">Products Issued This Month</small>\n <h1 class=\"mb-0 fw-bold\">{{ stockIssuanceQtySum | number }}</h1>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-product-quick-search></app-product-quick-search>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-low-stock-products-widget></app-low-stock-products-widget>\n </div>\n <div class=\"col-lg-6 mb-3\">\n <app-product-summary-chart title=\"Product By Category\"></app-product-summary-chart>\n </div>\n </div>\n <div style=\"width: 300px\" class=\"d-flex flex-column gap-3 h-100\">\n <mat-card class=\"h-100\">\n <mat-card-content>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <mat-icon>flag</mat-icon>\n <h3 class=\"mb-0 fw-bold\">Reports</h3>\n </div>\n </mat-card-content>\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start gap-3\">\n <a\n class=\"d-flex justify-content-start align-items-center gap-2 text-decoration-none text-dark\"\n routerLink=\"/inventory/reports/low-stock-report\"\n >\n <span class=\"material-symbols-outlined fs-3\">\n description\n </span>\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <span class=\"material-symbols-outlined\">\n chevron_forward\n </span>\n </a>\n <a\n class=\"d-flex justify-content-start align-items-center gap-2 text-decoration-none text-dark cursor-pointer\"\n routerLink=\"/inventory/reports/inventory-value-report\"\n >\n <span class=\"material-symbols-outlined fs-3\">\n description\n </span>\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <span class=\"material-symbols-outlined\">\n chevron_forward\n </span>\n </a>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n" }]
|
|
2644
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
2645
|
+
|
|
2646
|
+
class ProductCategoryBadgesComponent {
|
|
2647
|
+
product;
|
|
2648
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductCategoryBadgesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2649
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductCategoryBadgesComponent, isStandalone: true, selector: "app-product-category-badges", inputs: { product: "product" }, ngImport: i0, template: "<ng-container\n *ngIf=\"product?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1\"\n>\n <span class=\"badge bg-primary-lighter\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n</ng-container>\n", styles: [""], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], preserveWhitespaces: true });
|
|
2650
|
+
}
|
|
2651
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductCategoryBadgesComponent, decorators: [{
|
|
2652
|
+
type: Component,
|
|
2653
|
+
args: [{ selector: 'app-product-category-badges', standalone: true, imports: [
|
|
2654
|
+
NgIf,
|
|
2655
|
+
NgForOf
|
|
2656
|
+
], template: "<ng-container\n *ngIf=\"product?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1\"\n>\n <span class=\"badge bg-primary-lighter\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n</ng-container>\n" }]
|
|
2657
|
+
}], propDecorators: { product: [{
|
|
2658
|
+
type: Input
|
|
2659
|
+
}] } });
|
|
2660
|
+
|
|
2661
|
+
class LowStockReportService extends TechlifyServiceBaseClass {
|
|
2662
|
+
httpService;
|
|
2663
|
+
constructor(httpService) {
|
|
2664
|
+
super(httpService, 'reports/low-stock-report');
|
|
2665
|
+
this.httpService = httpService;
|
|
2666
|
+
}
|
|
2667
|
+
export(params) {
|
|
2668
|
+
return this.http.get('api/reports/low-stock-report/export', { params });
|
|
2669
|
+
}
|
|
2670
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2671
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, providedIn: 'root' });
|
|
2672
|
+
}
|
|
2673
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, decorators: [{
|
|
2674
|
+
type: Injectable,
|
|
2675
|
+
args: [{
|
|
2676
|
+
providedIn: 'root'
|
|
2677
|
+
}]
|
|
2678
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
2679
|
+
|
|
2680
|
+
class LowStockReportComponent extends TechlifyListingControllerInterface {
|
|
2681
|
+
service;
|
|
2682
|
+
activatedRoute;
|
|
2683
|
+
requestHelperService;
|
|
2684
|
+
formBuilder;
|
|
2685
|
+
displayedColumns = [
|
|
2686
|
+
'#',
|
|
2687
|
+
'Product',
|
|
2688
|
+
'Type',
|
|
2689
|
+
'Categories',
|
|
2690
|
+
'Reorder Point',
|
|
2691
|
+
'Stock',
|
|
2692
|
+
'Last Purchase',
|
|
2693
|
+
'30d Issues',
|
|
2694
|
+
'30d Receipts',
|
|
2695
|
+
'60d Issues',
|
|
2696
|
+
'60d Receipts',
|
|
2697
|
+
'90d Issues',
|
|
2698
|
+
'90d Receipts',
|
|
2699
|
+
'1y Issues',
|
|
2700
|
+
'1y Receipts',
|
|
2701
|
+
];
|
|
2702
|
+
totalInventoryValue = 0;
|
|
2703
|
+
isExporting = false;
|
|
2704
|
+
constructor(service, activatedRoute, requestHelperService, formBuilder) {
|
|
2705
|
+
super();
|
|
2706
|
+
this.service = service;
|
|
2707
|
+
this.activatedRoute = activatedRoute;
|
|
2708
|
+
this.requestHelperService = requestHelperService;
|
|
2709
|
+
this.formBuilder = formBuilder;
|
|
2710
|
+
this.filterForm = this.formBuilder.group({
|
|
2711
|
+
category_ids: [''],
|
|
2712
|
+
search: [''],
|
|
2713
|
+
sort_by: ['id|desc']
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2716
|
+
ngOnInit() {
|
|
2717
|
+
this.updateFormWithQueryParams();
|
|
2718
|
+
this.subscribeToFormChanges();
|
|
2719
|
+
this.subscribeToRouteChanges();
|
|
2720
|
+
}
|
|
2721
|
+
loadData() {
|
|
2722
|
+
const params = {
|
|
2723
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
2724
|
+
page: this.page,
|
|
2725
|
+
perPage: this.perPage,
|
|
2726
|
+
with: 'categories,lastStockReceipt,type,measure',
|
|
2727
|
+
};
|
|
2728
|
+
this.isWorking = true;
|
|
2729
|
+
this.service.index(params).subscribe({
|
|
2730
|
+
next: (response) => {
|
|
2731
|
+
this.models = this.models?.concat(response?.data);
|
|
2732
|
+
this.isWorking = false;
|
|
2733
|
+
this.models.forEach((model) => {
|
|
2734
|
+
this.totalInventoryValue += model?.inventory_value;
|
|
2735
|
+
});
|
|
2736
|
+
},
|
|
2737
|
+
error: () => (this.isWorking = false),
|
|
2738
|
+
});
|
|
2739
|
+
}
|
|
2740
|
+
onSortChange(sort) {
|
|
2741
|
+
let { active, direction } = sort;
|
|
2742
|
+
if (!active)
|
|
2743
|
+
active = 'id';
|
|
2744
|
+
if (!direction)
|
|
2745
|
+
direction = 'desc';
|
|
2746
|
+
this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
|
|
2747
|
+
}
|
|
2748
|
+
export() {
|
|
2749
|
+
const params = {
|
|
2750
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
2751
|
+
page: this.page,
|
|
2752
|
+
perPage: 50000,
|
|
2753
|
+
with: 'categories,lastStockReceipt',
|
|
2754
|
+
};
|
|
2755
|
+
this.isExporting = true;
|
|
2756
|
+
this.service.export(params).subscribe({
|
|
2757
|
+
next: (response) => {
|
|
2758
|
+
this.isExporting = false;
|
|
2759
|
+
window.open(response?.item?.file_link, '_blank');
|
|
2760
|
+
},
|
|
2761
|
+
error: () => (this.isExporting = false)
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
updateFormWithQueryParams() {
|
|
2765
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
2766
|
+
category_ids: { multiple: true }
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
subscribeToFormChanges() {
|
|
2770
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
2771
|
+
next: () => {
|
|
2772
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
2773
|
+
}
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
subscribeToRouteChanges() {
|
|
2777
|
+
this.activatedRoute.queryParams
|
|
2778
|
+
.pipe(debounceTime$1(500), distinctUntilChanged())
|
|
2779
|
+
.subscribe(() => {
|
|
2780
|
+
this.reload();
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportComponent, deps: [{ token: LowStockReportService }, { token: i2.ActivatedRoute }, { token: i1.RequestHelperService }, { token: i2$2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
2784
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LowStockReportComponent, isStandalone: true, selector: "app-low-stock-report", usesInheritance: true, ngImport: i0, template: "<div>\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export()\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef> Type </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.type?.title }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef> Reorder Point </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"stock\"> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock }}\n </td>\n </ng-container>\n\n <!-- Last Purchase Column -->\n <ng-container matColumnDef=\"Last Purchase\">\n <th mat-header-cell *matHeaderCellDef>\n Last Purchase\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.date | date }} -\n {{ element?.last_stock_receipt?.quantity }} {{ element?.measure?.title }}\n </p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }} per {{ element?.measure?.title }}\n </small>\n </td>\n </ng-container>\n\n <!-- 30d Issues -->\n <ng-container matColumnDef=\"30d Issues\">\n <th mat-header-cell *matHeaderCellDef> 30d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_30d }}</td>\n </ng-container>\n\n <!-- 30d Receipts -->\n <ng-container matColumnDef=\"30d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 30d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_30d }}</td>\n </ng-container>\n\n <!-- 60d Issues -->\n <ng-container matColumnDef=\"60d Issues\">\n <th mat-header-cell *matHeaderCellDef> 60d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_60d }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"60d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 60d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_60d }}</td>\n </ng-container>\n\n <!-- 90d Issues -->\n <ng-container matColumnDef=\"90d Issues\">\n <th mat-header-cell *matHeaderCellDef> 90d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_90d }}</td>\n </ng-container>\n\n <!-- 90d Receipts -->\n <ng-container matColumnDef=\"90d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 90d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_90d }}</td>\n </ng-container>\n\n <!-- 1y Issues -->\n <ng-container matColumnDef=\"1y Issues\">\n <th mat-header-cell *matHeaderCellDef> 1y Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_1y }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"1y Receipts\">\n <th mat-header-cell *matHeaderCellDef> 1y Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_1y }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n", styles: [""], dependencies: [{ kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: SearchableSelectorModule }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "pipe", type: DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
2785
|
+
}
|
|
2786
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportComponent, decorators: [{
|
|
2787
|
+
type: Component,
|
|
2788
|
+
args: [{ selector: 'app-low-stock-report', standalone: true, imports: [
|
|
2789
|
+
CurrencyPipe,
|
|
2790
|
+
FormsModule,
|
|
2791
|
+
InfiniteScrollDirective,
|
|
2792
|
+
MatCard,
|
|
2793
|
+
MatCardContent,
|
|
2794
|
+
MatCell,
|
|
2795
|
+
MatCellDef,
|
|
2796
|
+
MatColumnDef,
|
|
2797
|
+
MatFooterCell,
|
|
2798
|
+
MatFooterRow,
|
|
2799
|
+
MatFooterRowDef,
|
|
2800
|
+
MatFormField,
|
|
2801
|
+
MatHeaderCell,
|
|
2802
|
+
MatHeaderRow,
|
|
2803
|
+
MatHeaderRowDef,
|
|
2804
|
+
MatInput,
|
|
2805
|
+
MatLabel,
|
|
2806
|
+
MatProgressBar,
|
|
2807
|
+
MatRow,
|
|
2808
|
+
MatRowDef,
|
|
2809
|
+
MatSort,
|
|
2810
|
+
MatSortHeader,
|
|
2811
|
+
MatTable,
|
|
2812
|
+
NgIf,
|
|
2813
|
+
ProductCategoryBadgesComponent,
|
|
2814
|
+
ReactiveFormsModule,
|
|
2815
|
+
SearchableSelectorModule,
|
|
2816
|
+
RouterLink,
|
|
2817
|
+
MatFooterCellDef,
|
|
2818
|
+
MatHeaderCellDef,
|
|
2819
|
+
MatFooterCellDef,
|
|
2820
|
+
MatHeaderCellDef,
|
|
2821
|
+
MatHeaderCellDef,
|
|
2822
|
+
DatePipe
|
|
2823
|
+
], template: "<div>\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export()\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef> Type </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.type?.title }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef> Reorder Point </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"stock\"> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock }}\n </td>\n </ng-container>\n\n <!-- Last Purchase Column -->\n <ng-container matColumnDef=\"Last Purchase\">\n <th mat-header-cell *matHeaderCellDef>\n Last Purchase\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.date | date }} -\n {{ element?.last_stock_receipt?.quantity }} {{ element?.measure?.title }}\n </p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }} per {{ element?.measure?.title }}\n </small>\n </td>\n </ng-container>\n\n <!-- 30d Issues -->\n <ng-container matColumnDef=\"30d Issues\">\n <th mat-header-cell *matHeaderCellDef> 30d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_30d }}</td>\n </ng-container>\n\n <!-- 30d Receipts -->\n <ng-container matColumnDef=\"30d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 30d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_30d }}</td>\n </ng-container>\n\n <!-- 60d Issues -->\n <ng-container matColumnDef=\"60d Issues\">\n <th mat-header-cell *matHeaderCellDef> 60d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_60d }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"60d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 60d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_60d }}</td>\n </ng-container>\n\n <!-- 90d Issues -->\n <ng-container matColumnDef=\"90d Issues\">\n <th mat-header-cell *matHeaderCellDef> 90d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_90d }}</td>\n </ng-container>\n\n <!-- 90d Receipts -->\n <ng-container matColumnDef=\"90d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 90d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_90d }}</td>\n </ng-container>\n\n <!-- 1y Issues -->\n <ng-container matColumnDef=\"1y Issues\">\n <th mat-header-cell *matHeaderCellDef> 1y Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_1y }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"1y Receipts\">\n <th mat-header-cell *matHeaderCellDef> 1y Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_1y }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n" }]
|
|
2824
|
+
}], ctorParameters: () => [{ type: LowStockReportService }, { type: i2.ActivatedRoute }, { type: i1.RequestHelperService }, { type: i2$2.FormBuilder }] });
|
|
2825
|
+
|
|
2826
|
+
class InventoryValueReportService extends TechlifyServiceBaseClass {
|
|
2827
|
+
constructor(httpService) {
|
|
2828
|
+
super(httpService, 'reports/inventory-value-report');
|
|
2829
|
+
}
|
|
2830
|
+
export(params) {
|
|
2831
|
+
return this.http.get('api/reports/inventory-value-report/export', { params });
|
|
2832
|
+
}
|
|
2833
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2834
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, providedIn: 'root' });
|
|
2835
|
+
}
|
|
2836
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, decorators: [{
|
|
2837
|
+
type: Injectable,
|
|
2838
|
+
args: [{
|
|
2839
|
+
providedIn: 'root'
|
|
2840
|
+
}]
|
|
2841
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
2842
|
+
|
|
2843
|
+
class InventoryValueReportComponent extends TechlifyListingControllerInterface {
|
|
2844
|
+
service;
|
|
2845
|
+
activatedRoute;
|
|
2846
|
+
requestHelperService;
|
|
2847
|
+
formBuilder;
|
|
2848
|
+
displayedColumns = [
|
|
2849
|
+
'#',
|
|
2850
|
+
'Product',
|
|
2851
|
+
'Description',
|
|
2852
|
+
'Categories',
|
|
2853
|
+
'Available Stock',
|
|
2854
|
+
'Average Price',
|
|
2855
|
+
'Inventory Value',
|
|
2856
|
+
'Last Purchase Price',
|
|
2857
|
+
'Inventory Value Based On Last Purchase Price',
|
|
2858
|
+
];
|
|
2859
|
+
totalInventoryValue = 0;
|
|
2860
|
+
isExporting = false;
|
|
2861
|
+
constructor(service, activatedRoute, requestHelperService, formBuilder) {
|
|
2862
|
+
super();
|
|
2863
|
+
this.service = service;
|
|
2864
|
+
this.activatedRoute = activatedRoute;
|
|
2865
|
+
this.requestHelperService = requestHelperService;
|
|
2866
|
+
this.formBuilder = formBuilder;
|
|
2867
|
+
this.filterForm = this.formBuilder.group({
|
|
2868
|
+
category_ids: [''],
|
|
2869
|
+
search: [''],
|
|
2870
|
+
sort_by: ['id|desc']
|
|
2871
|
+
});
|
|
2872
|
+
}
|
|
2873
|
+
ngOnInit() {
|
|
2874
|
+
this.updateFormWithQueryParams();
|
|
2875
|
+
this.subscribeToFormChanges();
|
|
2876
|
+
this.subscribeToRouteChanges();
|
|
2877
|
+
}
|
|
2878
|
+
loadData() {
|
|
2879
|
+
const params = {
|
|
2880
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
2881
|
+
page: this.page,
|
|
2882
|
+
perPage: this.perPage,
|
|
2883
|
+
with: 'categories,lastStockReceipt',
|
|
2884
|
+
};
|
|
2885
|
+
this.isWorking = true;
|
|
2886
|
+
this.service.index(params).subscribe({
|
|
2887
|
+
next: (response) => {
|
|
2888
|
+
this.models = this.models?.concat(response?.data);
|
|
2889
|
+
this.isWorking = false;
|
|
2890
|
+
this.models.forEach((model) => {
|
|
2891
|
+
this.totalInventoryValue += model?.inventory_value;
|
|
2892
|
+
});
|
|
2893
|
+
},
|
|
2894
|
+
error: () => (this.isWorking = false),
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
updateFormWithQueryParams() {
|
|
2898
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
2899
|
+
category_ids: { multiple: true }
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2902
|
+
subscribeToFormChanges() {
|
|
2903
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
2904
|
+
next: () => {
|
|
2905
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
2906
|
+
}
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2909
|
+
subscribeToRouteChanges() {
|
|
2910
|
+
this.activatedRoute.queryParams
|
|
2911
|
+
.pipe(debounceTime$1(500), distinctUntilChanged())
|
|
2912
|
+
.subscribe(() => {
|
|
2913
|
+
this.reload();
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
onSortChange(sort) {
|
|
2917
|
+
let { active, direction } = sort;
|
|
2918
|
+
if (!active)
|
|
2919
|
+
active = 'id';
|
|
2920
|
+
if (!direction)
|
|
2921
|
+
direction = 'desc';
|
|
2922
|
+
this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
|
|
2923
|
+
}
|
|
2924
|
+
export(type = 'excel') {
|
|
2925
|
+
const params = {
|
|
2926
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
2927
|
+
page: this.page,
|
|
2928
|
+
perPage: 50000,
|
|
2929
|
+
with: 'categories,lastStockReceipt',
|
|
2930
|
+
export_type: type,
|
|
2931
|
+
};
|
|
2932
|
+
this.isExporting = true;
|
|
2933
|
+
this.service.export(params).subscribe({
|
|
2934
|
+
next: (response) => {
|
|
2935
|
+
this.isExporting = false;
|
|
2936
|
+
window.open(response?.item?.file_link, '_blank');
|
|
2937
|
+
},
|
|
2938
|
+
error: () => (this.isExporting = false)
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportComponent, deps: [{ token: InventoryValueReportService }, { token: i2.ActivatedRoute }, { token: i1.RequestHelperService }, { token: i2$2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
2942
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: InventoryValueReportComponent, isStandalone: true, selector: "app-inventory-value-report", usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export('excel')\"></i>\n <i class=\"fa-solid fa-file-pdf cursor-pointer d-print-none\" (click)=\"export('pdf')\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell *matHeaderCellDef> Description </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.description }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>Total</strong>\n </td>\n </ng-container>\n\n <!-- Available Stock Column -->\n <ng-container matColumnDef=\"Available Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"current_stock\"> Available Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Average Price Column -->\n <ng-container matColumnDef=\"Average Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"average_purchase_price\"> Average Price </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.average_purchase_price | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Column -->\n <ng-container matColumnDef=\"Inventory Value\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"inventory_value\"> Inventory Value </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.inventory_value | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>{{ totalInventoryValue | currency }}</strong>\n </td>\n </ng-container>\n\n <!-- Last Purchase Price Column -->\n <ng-container matColumnDef=\"Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.purchase_price\">\n Last Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Based On Last Purchase Price Column -->\n <ng-container matColumnDef=\"Inventory Value Based On Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.amount\">\n <div>\n <p class=\"mb-0\">Inventory Value</p>\n <small class=\"text-secondary\">Based on last purchase price</small>\n </div>\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.amount ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "component", type: MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: SearchableSelectorModule }, { kind: "component", type: i1.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }], preserveWhitespaces: true });
|
|
2943
|
+
}
|
|
2944
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportComponent, decorators: [{
|
|
2945
|
+
type: Component,
|
|
2946
|
+
args: [{ selector: 'app-inventory-value-report', standalone: true, imports: [
|
|
2947
|
+
MatCard,
|
|
2948
|
+
MatCardContent,
|
|
2949
|
+
MatTable,
|
|
2950
|
+
MatColumnDef,
|
|
2951
|
+
MatColumnDef,
|
|
2952
|
+
MatCellDef,
|
|
2953
|
+
MatRow,
|
|
2954
|
+
MatCellDef,
|
|
2955
|
+
MatHeaderCell,
|
|
2956
|
+
MatCell,
|
|
2957
|
+
MatRowDef,
|
|
2958
|
+
MatCellDef,
|
|
2959
|
+
MatHeaderCell,
|
|
2960
|
+
MatColumnDef,
|
|
2961
|
+
MatCell,
|
|
2962
|
+
MatColumnDef,
|
|
2963
|
+
MatHeaderCell,
|
|
2964
|
+
MatHeaderRowDef,
|
|
2965
|
+
MatHeaderCell,
|
|
2966
|
+
MatCell,
|
|
2967
|
+
MatHeaderRow,
|
|
2968
|
+
MatCell,
|
|
2969
|
+
MatCellDef,
|
|
2970
|
+
MatHeaderCellDef,
|
|
2971
|
+
MatHeaderCellDef,
|
|
2972
|
+
MatHeaderCellDef,
|
|
2973
|
+
MatHeaderCellDef,
|
|
2974
|
+
RouterLink,
|
|
2975
|
+
ProductCategoryBadgesComponent,
|
|
2976
|
+
CurrencyPipe,
|
|
2977
|
+
MatProgressBar,
|
|
2978
|
+
NgIf,
|
|
2979
|
+
MatFooterRowDef,
|
|
2980
|
+
MatFooterRow,
|
|
2981
|
+
MatFooterCellDef,
|
|
2982
|
+
MatFooterCell,
|
|
2983
|
+
MatFormField,
|
|
2984
|
+
MatLabel,
|
|
2985
|
+
ReactiveFormsModule,
|
|
2986
|
+
SearchableSelectorModule,
|
|
2987
|
+
MatInput,
|
|
2988
|
+
InfiniteScrollDirective,
|
|
2989
|
+
MatSort,
|
|
2990
|
+
MatSortHeader
|
|
2991
|
+
], template: "<div class=\"container\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export('excel')\"></i>\n <i class=\"fa-solid fa-file-pdf cursor-pointer d-print-none\" (click)=\"export('pdf')\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell *matHeaderCellDef> Description </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.description }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>Total</strong>\n </td>\n </ng-container>\n\n <!-- Available Stock Column -->\n <ng-container matColumnDef=\"Available Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"current_stock\"> Available Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Average Price Column -->\n <ng-container matColumnDef=\"Average Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"average_purchase_price\"> Average Price </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.average_purchase_price | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Column -->\n <ng-container matColumnDef=\"Inventory Value\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"inventory_value\"> Inventory Value </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.inventory_value | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>{{ totalInventoryValue | currency }}</strong>\n </td>\n </ng-container>\n\n <!-- Last Purchase Price Column -->\n <ng-container matColumnDef=\"Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.purchase_price\">\n Last Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Based On Last Purchase Price Column -->\n <ng-container matColumnDef=\"Inventory Value Based On Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.amount\">\n <div>\n <p class=\"mb-0\">Inventory Value</p>\n <small class=\"text-secondary\">Based on last purchase price</small>\n </div>\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.amount ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n" }]
|
|
2992
|
+
}], ctorParameters: () => [{ type: InventoryValueReportService }, { type: i2.ActivatedRoute }, { type: i1.RequestHelperService }, { type: i2$2.FormBuilder }] });
|
|
2993
|
+
|
|
2994
|
+
const routes = [
|
|
2995
|
+
{
|
|
2996
|
+
path: 'reports/low-stock-report',
|
|
2997
|
+
component: LowStockReportComponent,
|
|
2998
|
+
},
|
|
2999
|
+
{
|
|
3000
|
+
path: 'reports/inventory-value-report',
|
|
3001
|
+
component: InventoryValueReportComponent,
|
|
3002
|
+
},
|
|
3003
|
+
{
|
|
3004
|
+
path: "suppliers",
|
|
3005
|
+
loadChildren: () => import('./techlify-inventory-common-supplier.module-CFDwJ-TS.mjs').then((m) => m.SupplierModule),
|
|
3006
|
+
},
|
|
3007
|
+
{
|
|
3008
|
+
path: "measures",
|
|
3009
|
+
loadChildren: () => import('./techlify-inventory-common-measure.module-CZHhYoQd.mjs').then((mod) => mod.MeasureModule),
|
|
3010
|
+
},
|
|
3011
|
+
{
|
|
3012
|
+
path: "stock-issuances",
|
|
3013
|
+
loadChildren: () => import('./techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs').then((mod) => mod.StockIssuancesModule),
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
path: "stock-receipts",
|
|
3017
|
+
loadChildren: () => Promise.resolve().then(function () { return stockReceipts_module; }).then((mod) => mod.StockReceiptsModule),
|
|
3018
|
+
},
|
|
3019
|
+
{
|
|
3020
|
+
path: "categories",
|
|
3021
|
+
loadChildren: () => import('./techlify-inventory-common-category.module-BKEBFEeZ.mjs').then((mod) => mod.CategoryModule),
|
|
3022
|
+
},
|
|
3023
|
+
{
|
|
3024
|
+
path: "products",
|
|
3025
|
+
loadChildren: () => Promise.resolve().then(function () { return product_module; }).then((mod) => mod.ProductModule),
|
|
3026
|
+
},
|
|
3027
|
+
{
|
|
3028
|
+
path: "dashboard",
|
|
3029
|
+
component: InventoryDashboardPageComponent,
|
|
3030
|
+
},
|
|
3031
|
+
{
|
|
3032
|
+
path: "**",
|
|
3033
|
+
redirectTo: "dashboard",
|
|
3034
|
+
pathMatch: "full",
|
|
3035
|
+
},
|
|
3036
|
+
];
|
|
3037
|
+
class InventoryCommonRoutingModule {
|
|
3038
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3039
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
3040
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
|
|
3041
|
+
}
|
|
3042
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, decorators: [{
|
|
3043
|
+
type: NgModule,
|
|
3044
|
+
args: [{
|
|
3045
|
+
imports: [RouterModule.forChild(routes)],
|
|
3046
|
+
exports: [RouterModule],
|
|
3047
|
+
}]
|
|
3048
|
+
}] });
|
|
3049
|
+
|
|
3050
|
+
class LowStockProductsWidgetModule {
|
|
3051
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3052
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, declarations: [LowStockProductsWidgetComponent], imports: [CommonModule,
|
|
3053
|
+
MaterialModule,
|
|
3054
|
+
InfiniteScrollModule,
|
|
3055
|
+
MatProgressBarModule,
|
|
3056
|
+
RouterModule], exports: [LowStockProductsWidgetComponent] });
|
|
3057
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, imports: [CommonModule,
|
|
3058
|
+
MaterialModule,
|
|
3059
|
+
InfiniteScrollModule,
|
|
3060
|
+
MatProgressBarModule,
|
|
3061
|
+
RouterModule] });
|
|
3062
|
+
}
|
|
3063
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, decorators: [{
|
|
3064
|
+
type: NgModule,
|
|
3065
|
+
args: [{
|
|
3066
|
+
declarations: [LowStockProductsWidgetComponent],
|
|
3067
|
+
imports: [
|
|
3068
|
+
CommonModule,
|
|
3069
|
+
MaterialModule,
|
|
3070
|
+
InfiniteScrollModule,
|
|
3071
|
+
MatProgressBarModule,
|
|
3072
|
+
RouterModule,
|
|
3073
|
+
],
|
|
3074
|
+
exports: [LowStockProductsWidgetComponent],
|
|
3075
|
+
}]
|
|
3076
|
+
}] });
|
|
3077
|
+
|
|
3078
|
+
class ProductSummaryChartModule {
|
|
3079
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3080
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, imports: [CommonModule,
|
|
3081
|
+
MaterialModule,
|
|
3082
|
+
MatProgressBarModule,
|
|
3083
|
+
GoogleChartsModule] });
|
|
3084
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, imports: [CommonModule,
|
|
3085
|
+
MaterialModule,
|
|
3086
|
+
MatProgressBarModule,
|
|
3087
|
+
GoogleChartsModule] });
|
|
3088
|
+
}
|
|
3089
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, decorators: [{
|
|
3090
|
+
type: NgModule,
|
|
3091
|
+
args: [{
|
|
3092
|
+
imports: [
|
|
3093
|
+
CommonModule,
|
|
3094
|
+
MaterialModule,
|
|
3095
|
+
MatProgressBarModule,
|
|
3096
|
+
GoogleChartsModule,
|
|
3097
|
+
],
|
|
3098
|
+
}]
|
|
3099
|
+
}] });
|
|
3100
|
+
|
|
3101
|
+
class InventoryCommonModule {
|
|
3102
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3103
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, declarations: [InventoryDashboardPageComponent], imports: [CommonModule,
|
|
3104
|
+
InventoryCommonRoutingModule,
|
|
3105
|
+
MaterialModule,
|
|
3106
|
+
LowStockProductsWidgetModule,
|
|
3107
|
+
ProductSummaryChartModule,
|
|
3108
|
+
ProductSummaryChartComponent,
|
|
3109
|
+
ProductQuickSearchComponent] });
|
|
3110
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, imports: [CommonModule,
|
|
3111
|
+
InventoryCommonRoutingModule,
|
|
3112
|
+
MaterialModule,
|
|
3113
|
+
LowStockProductsWidgetModule,
|
|
3114
|
+
ProductSummaryChartModule,
|
|
3115
|
+
ProductSummaryChartComponent,
|
|
3116
|
+
ProductQuickSearchComponent] });
|
|
3117
|
+
}
|
|
3118
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, decorators: [{
|
|
3119
|
+
type: NgModule,
|
|
3120
|
+
args: [{
|
|
3121
|
+
declarations: [InventoryDashboardPageComponent],
|
|
3122
|
+
imports: [
|
|
3123
|
+
CommonModule,
|
|
3124
|
+
InventoryCommonRoutingModule,
|
|
3125
|
+
MaterialModule,
|
|
3126
|
+
LowStockProductsWidgetModule,
|
|
3127
|
+
ProductSummaryChartModule,
|
|
3128
|
+
ProductSummaryChartComponent,
|
|
3129
|
+
ProductQuickSearchComponent,
|
|
3130
|
+
],
|
|
3131
|
+
}]
|
|
3132
|
+
}] });
|
|
3133
|
+
|
|
3134
|
+
/*
|
|
3135
|
+
* Public API Surface of inventory-common
|
|
3136
|
+
*/
|
|
3137
|
+
|
|
3138
|
+
/**
|
|
3139
|
+
* Generated bundle index. Do not edit.
|
|
3140
|
+
*/
|
|
3141
|
+
|
|
3142
|
+
export { InventoryCommonRoutingModule as I, SupplierFormComponent as S, TechlifyFormService as T, SupplierService as a, TechlifyFilterComponent as b, TechlifyFilterModule as c, StockIssuancesListComponent as d, StockReceiptFormModule as e, StockIssueFormModule as f, StockIssuancesListModule as g, InventoryCommonModule as h, StockSummaryService as i };
|
|
3143
|
+
//# sourceMappingURL=techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs.map
|