techlify-inventory-common 18.1.0 → 18.3.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/category/category-form/category-form.component.mjs +12 -12
- package/esm2022/lib/inventory-common/category/category-form-button/category-form-button.component.mjs +5 -5
- package/esm2022/lib/inventory-common/category/category-list-page/category-list-page.component.mjs +22 -26
- package/esm2022/lib/inventory-common/category/category-routing.module.mjs +10 -5
- package/esm2022/lib/inventory-common/category/category-view/category-view.component.mjs +46 -0
- package/esm2022/lib/inventory-common/category/category.module.mjs +23 -24
- package/esm2022/lib/inventory-common/category/category.service.mjs +6 -6
- package/esm2022/lib/inventory-common/inventory-common-routing.module.mjs +32 -18
- package/esm2022/lib/inventory-common/inventory-common.module.mjs +13 -9
- package/esm2022/lib/inventory-common/inventory-dashboard-page/inventory-dashboard-page.component.mjs +12 -10
- package/esm2022/lib/inventory-common/inventory-value-report.service.mjs +21 -0
- package/esm2022/lib/inventory-common/location/location-delete-button/location-delete-button.component.mjs +68 -0
- package/esm2022/lib/inventory-common/location/location-form/location-form.component.mjs +86 -0
- package/esm2022/lib/inventory-common/location/location-form-button/location-form-button.component.mjs +35 -0
- package/esm2022/lib/inventory-common/location/location-information/location-information.component.mjs +34 -0
- package/esm2022/lib/inventory-common/location/location-list/location-list.component.mjs +121 -0
- package/esm2022/lib/inventory-common/location/location-product-statistics/location-product-statistics.component.mjs +127 -0
- package/esm2022/lib/inventory-common/location/location-routing.module.mjs +29 -0
- package/esm2022/lib/inventory-common/location/location-view/location-view.component.mjs +53 -0
- package/esm2022/lib/inventory-common/location/location.module.mjs +22 -0
- package/esm2022/lib/inventory-common/location/location.service.mjs +23 -0
- package/esm2022/lib/inventory-common/low-stock-report.service.mjs +23 -0
- package/esm2022/lib/inventory-common/material.module.mjs +37 -37
- package/esm2022/lib/inventory-common/measure/measure-delete/measure-delete-button/measure-delete-button.component.mjs +4 -4
- package/esm2022/lib/inventory-common/measure/measure-delete/measure-delete.module.mjs +4 -4
- package/esm2022/lib/inventory-common/measure/measure-form/measure-form/measure-form.component.mjs +14 -14
- package/esm2022/lib/inventory-common/measure/measure-form/measure-form-button/measure-form-button.component.mjs +5 -5
- package/esm2022/lib/inventory-common/measure/measure-form/measure-form.module.mjs +6 -6
- package/esm2022/lib/inventory-common/measure/measure-routing.module.mjs +5 -5
- package/esm2022/lib/inventory-common/measure/measure.module.mjs +10 -10
- package/esm2022/lib/inventory-common/measure/measure.service.mjs +6 -6
- package/esm2022/lib/inventory-common/measure/measures-list/measures-list.component.mjs +12 -18
- package/esm2022/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.component.mjs +13 -11
- package/esm2022/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.module.mjs +10 -24
- package/esm2022/lib/inventory-common/product/product-basic-info/product-basic-info.component.mjs +5 -5
- package/esm2022/lib/inventory-common/product/product-batch-update-form/product-batch-update-form.component.mjs +56 -0
- package/esm2022/lib/inventory-common/product/product-delete-button/product-delete-button.component.mjs +6 -6
- package/esm2022/lib/inventory-common/product/product-form/product-form.component.mjs +43 -45
- package/esm2022/lib/inventory-common/product/product-form-button/product-form-button.component.mjs +5 -5
- package/esm2022/lib/inventory-common/product/product-form.service.mjs +4 -4
- package/esm2022/lib/inventory-common/product/product-import-page/product-import-page.component.mjs +32 -32
- package/esm2022/lib/inventory-common/product/product-list/product-list.component.mjs +65 -87
- package/esm2022/lib/inventory-common/product/product-location/product-location-list/product-location-list.component.mjs +56 -0
- package/esm2022/lib/inventory-common/product/product-measure-form/product-measure-form.component.mjs +12 -12
- package/esm2022/lib/inventory-common/product/product-measures-list/product-measures-list.component.mjs +22 -28
- package/esm2022/lib/inventory-common/product/product-nav-bar/product-nav-bar.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/product-routing.module.mjs +17 -17
- package/esm2022/lib/inventory-common/product/product-statistics.service.mjs +23 -0
- package/esm2022/lib/inventory-common/product/product-summary-chart/product-summary-chart.component.mjs +10 -16
- package/esm2022/lib/inventory-common/product/product-summary-chart/product-summary-chart.module.mjs +9 -20
- package/esm2022/lib/inventory-common/product/product-tax/product-tax-delete-button/product-tax-delete-button.component.mjs +6 -6
- package/esm2022/lib/inventory-common/product/product-tax/product-tax-form-button/product-tax-form-button.component.mjs +14 -14
- package/esm2022/lib/inventory-common/product/product-tax/product-tax-list/product-tax-list.component.mjs +6 -6
- package/esm2022/lib/inventory-common/product/product-tax/product-tax.module.mjs +9 -26
- package/esm2022/lib/inventory-common/product/product-tax/product-tax.service.mjs +6 -6
- package/esm2022/lib/inventory-common/product/product-view-page/product-view-page.component.mjs +9 -7
- package/esm2022/lib/inventory-common/product/product.module.mjs +37 -26
- package/esm2022/lib/inventory-common/product/product.service.mjs +7 -7
- package/esm2022/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.mjs +15 -0
- package/esm2022/lib/inventory-common/product-batch.service.mjs +20 -0
- package/esm2022/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.mjs +168 -0
- package/esm2022/lib/inventory-common/reports/low-stock-report/low-stock-report.component.mjs +163 -0
- package/esm2022/lib/inventory-common/services/techlify-form-service.mjs +2 -2
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuance-delete-button/stock-issuance-delete-button.component.mjs +6 -6
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuance-delete-button/stock-issuance-delete-button.module.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuance.service.mjs +6 -6
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuances-list/stock-issuances-list.component.mjs +84 -56
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuances-list/stock-issuances-list.module.mjs +28 -12
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuances-routing.module.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-issuances/stock-issuances.module.mjs +14 -14
- package/esm2022/lib/inventory-common/stock-issuances/stock-issue-form/stock-issue-form/stock-issue-form.component.mjs +14 -14
- package/esm2022/lib/inventory-common/stock-issuances/stock-issue-form/stock-issue-form-button/stock-issue-form-button.component.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-issuances/stock-issue-form/stock-issue-form.module.mjs +13 -13
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipt-delete-button/stock-receipt-delete-button.component.mjs +6 -6
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipt-form/stock-receipt-form/stock-receipt-form.component.mjs +18 -18
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipt-form/stock-receipt-form-button/stock-receipt-form-button.component.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipt-form/stock-receipt-form.module.mjs +12 -12
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipt.service.mjs +6 -6
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipts-list-page/stock-receipts-list-page.component.mjs +82 -44
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipts-routing.module.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-receipts/stock-receipts.module.mjs +24 -22
- package/esm2022/lib/inventory-common/stock-summary.service.mjs +5 -5
- package/esm2022/lib/inventory-common/stock-transfer/stock-transfer-form/stock-transfer-form.component.mjs +105 -0
- package/esm2022/lib/inventory-common/stock-transfer/stock-transfer-form-button/stock-transfer-form-button.component.mjs +38 -0
- package/esm2022/lib/inventory-common/stock-transfer/stock-transfer-list/stock-transfer-list.component.mjs +77 -0
- package/esm2022/lib/inventory-common/stock-transfer/stock-transfer.service.mjs +18 -0
- package/esm2022/lib/inventory-common/supplier/payee-selector/payee-selector/payee-selector.component.mjs +9 -9
- package/esm2022/lib/inventory-common/supplier/payee-selector/payee-selector.module.mjs +10 -24
- 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-form/supplier-form.component.mjs +24 -24
- package/esm2022/lib/inventory-common/supplier/supplier-form/supplier-form.service.mjs +4 -4
- package/esm2022/lib/inventory-common/supplier/supplier-information/supplier-information.component.mjs +16 -15
- package/esm2022/lib/inventory-common/supplier/supplier-routing.module.mjs +9 -16
- package/esm2022/lib/inventory-common/supplier/supplier-view/supplier-view.component.mjs +13 -14
- package/esm2022/lib/inventory-common/supplier/supplier.component.mjs +3 -3
- package/esm2022/lib/inventory-common/supplier/supplier.module.mjs +23 -15
- package/esm2022/lib/inventory-common/supplier/supplier.service.mjs +5 -5
- package/esm2022/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.mjs +6 -65
- package/esm2022/lib/inventory-common/techlify-filter/techlify-filter.component.mjs +16 -18
- package/esm2022/lib/inventory-common/techlify-filter/techlify-filter.module.mjs +13 -9
- package/fesm2022/techlify-inventory-common-category.module-BsvJ6rVx.mjs +290 -0
- package/fesm2022/techlify-inventory-common-category.module-BsvJ6rVx.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common-location.module-Cwx9mHKE.mjs +529 -0
- package/fesm2022/techlify-inventory-common-location.module-Cwx9mHKE.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common-measure.module-C2v0-n_m.mjs +307 -0
- package/fesm2022/techlify-inventory-common-measure.module-C2v0-n_m.mjs.map +1 -0
- package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs → techlify-inventory-common-stock-issuances.module-CPccetrp.mjs} +3 -5
- package/fesm2022/techlify-inventory-common-stock-issuances.module-CPccetrp.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common-supplier.module-CYq-2pV1.mjs +464 -0
- package/fesm2022/techlify-inventory-common-supplier.module-CYq-2pV1.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-BMNkSTd6.mjs +3620 -0
- package/fesm2022/techlify-inventory-common-techlify-inventory-common-BMNkSTd6.mjs.map +1 -0
- package/fesm2022/techlify-inventory-common.mjs +1 -1
- package/lib/inventory-common/category/category-form/category-form.component.d.ts +4 -4
- package/lib/inventory-common/category/category-form-button/category-form-button.component.d.ts +2 -2
- package/lib/inventory-common/category/category-list-page/category-list-page.component.d.ts +4 -4
- package/lib/inventory-common/category/category-view/category-view.component.d.ts +16 -0
- package/lib/inventory-common/category/category.module.d.ts +12 -11
- package/lib/inventory-common/category/category.service.d.ts +1 -1
- package/lib/inventory-common/inventory-common.module.d.ts +2 -1
- package/lib/inventory-common/inventory-dashboard-page/inventory-dashboard-page.component.d.ts +1 -1
- package/lib/inventory-common/inventory-value-report.service.d.ts +9 -0
- package/lib/inventory-common/location/location-delete-button/location-delete-button.component.d.ts +28 -0
- package/lib/inventory-common/location/location-form/location-form.component.d.ts +19 -0
- package/lib/inventory-common/location/location-form-button/location-form-button.component.d.ts +13 -0
- package/lib/inventory-common/location/location-information/location-information.component.d.ts +10 -0
- package/lib/inventory-common/location/location-list/location-list.component.d.ts +20 -0
- package/lib/inventory-common/location/location-product-statistics/location-product-statistics.component.d.ts +21 -0
- package/lib/inventory-common/location/location-routing.module.d.ts +7 -0
- package/lib/inventory-common/location/location-view/location-view.component.d.ts +16 -0
- package/lib/inventory-common/location/location.module.d.ts +8 -0
- package/lib/inventory-common/location/location.service.d.ts +10 -0
- package/lib/inventory-common/low-stock-report.service.d.ts +10 -0
- package/lib/inventory-common/measure/measure-delete/measure-delete-button/measure-delete-button.component.d.ts +3 -3
- package/lib/inventory-common/measure/measure-form/measure-form/measure-form.component.d.ts +4 -4
- package/lib/inventory-common/measure/measure-form/measure-form-button/measure-form-button.component.d.ts +2 -2
- package/lib/inventory-common/measure/measure.service.d.ts +1 -1
- package/lib/inventory-common/measure/measures-list/measures-list.component.d.ts +5 -5
- package/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.component.d.ts +3 -3
- package/lib/inventory-common/product/product-basic-info/product-basic-info.component.d.ts +2 -2
- package/lib/inventory-common/product/product-batch-update-form/product-batch-update-form.component.d.ts +18 -0
- package/lib/inventory-common/product/product-delete-button/product-delete-button.component.d.ts +4 -4
- package/lib/inventory-common/product/product-form/product-form.component.d.ts +6 -6
- package/lib/inventory-common/product/product-form-button/product-form-button.component.d.ts +3 -3
- package/lib/inventory-common/product/product-import-page/product-import-page.component.d.ts +2 -2
- package/lib/inventory-common/product/product-list/product-list.component.d.ts +15 -24
- package/lib/inventory-common/product/product-location/product-location-list/product-location-list.component.d.ts +15 -0
- package/lib/inventory-common/product/product-measure-form/product-measure-form.component.d.ts +6 -6
- package/lib/inventory-common/product/product-measures-list/product-measures-list.component.d.ts +7 -7
- package/lib/inventory-common/product/product-quick-search/product-quick-search.component.d.ts +15 -0
- package/lib/inventory-common/product/product-statistics.service.d.ts +9 -0
- package/lib/inventory-common/product/product-summary-chart/product-summary-chart.component.d.ts +1 -1
- package/lib/inventory-common/product/product-tax/product-tax-delete-button/product-tax-delete-button.component.d.ts +4 -4
- package/lib/inventory-common/product/product-tax/product-tax-form-button/product-tax-form-button.component.d.ts +5 -5
- package/lib/inventory-common/product/product-tax/product-tax-list/product-tax-list.component.d.ts +2 -2
- package/lib/inventory-common/product/product-tax/product-tax.service.d.ts +1 -1
- package/lib/inventory-common/product/product-view-page/product-view-page.component.d.ts +4 -4
- package/lib/inventory-common/product/product.module.d.ts +16 -13
- package/lib/inventory-common/product/product.service.d.ts +2 -2
- package/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.d.ts +6 -0
- package/lib/inventory-common/product-batch.service.d.ts +8 -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/stock-issuances/stock-issuance-delete-button/stock-issuance-delete-button.component.d.ts +4 -4
- package/lib/inventory-common/stock-issuances/stock-issuance.service.d.ts +1 -1
- package/lib/inventory-common/stock-issuances/stock-issuances-list/stock-issuances-list.component.d.ts +16 -8
- package/lib/inventory-common/stock-issuances/stock-issuances-list/stock-issuances-list.module.d.ts +3 -1
- package/lib/inventory-common/stock-issuances/stock-issue-form/stock-issue-form/stock-issue-form.component.d.ts +4 -4
- package/lib/inventory-common/stock-issuances/stock-issue-form/stock-issue-form-button/stock-issue-form-button.component.d.ts +2 -2
- package/lib/inventory-common/stock-receipts/stock-receipt-delete-button/stock-receipt-delete-button.component.d.ts +4 -4
- package/lib/inventory-common/stock-receipts/stock-receipt-form/stock-receipt-form/stock-receipt-form.component.d.ts +4 -4
- package/lib/inventory-common/stock-receipts/stock-receipt-form/stock-receipt-form-button/stock-receipt-form-button.component.d.ts +2 -2
- package/lib/inventory-common/stock-receipts/stock-receipt.service.d.ts +1 -1
- package/lib/inventory-common/stock-receipts/stock-receipts-list-page/stock-receipts-list-page.component.d.ts +12 -4
- package/lib/inventory-common/stock-receipts/stock-receipts.module.d.ts +2 -1
- package/lib/inventory-common/stock-summary.service.d.ts +1 -1
- package/lib/inventory-common/stock-transfer/stock-transfer-form/stock-transfer-form.component.d.ts +19 -0
- package/lib/inventory-common/stock-transfer/stock-transfer-form-button/stock-transfer-form-button.component.d.ts +14 -0
- package/lib/inventory-common/stock-transfer/stock-transfer-list/stock-transfer-list.component.d.ts +17 -0
- package/lib/inventory-common/stock-transfer/stock-transfer.service.d.ts +7 -0
- package/lib/inventory-common/supplier/payee-selector/payee-selector/payee-selector.component.d.ts +3 -3
- 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-form/supplier-form.component.d.ts +6 -6
- package/lib/inventory-common/supplier/supplier-information/supplier-information.component.d.ts +4 -4
- package/lib/inventory-common/supplier/supplier-view/supplier-view.component.d.ts +4 -4
- package/lib/inventory-common/supplier/supplier.component.d.ts +2 -2
- package/lib/inventory-common/supplier/supplier.module.d.ts +3 -1
- package/lib/inventory-common/supplier/supplier.service.d.ts +1 -1
- package/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.d.ts +0 -8
- package/lib/inventory-common/techlify-filter/techlify-filter.component.d.ts +4 -4
- package/lib/inventory-common/techlify-filter/techlify-filter.module.d.ts +2 -1
- package/package.json +1 -1
- package/fesm2022/techlify-inventory-common-category.module-CNm2bEsx.mjs +0 -257
- package/fesm2022/techlify-inventory-common-category.module-CNm2bEsx.mjs.map +0 -1
- package/fesm2022/techlify-inventory-common-measure.module-BEaRHh5Z.mjs +0 -313
- package/fesm2022/techlify-inventory-common-measure.module-BEaRHh5Z.mjs.map +0 -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-issuances.module-BQRRP-hW.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 +0 -608
- 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,3620 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, Component, Input, Inject, forwardRef, EventEmitter, Output, 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, SearchableSelectorModule, AuthenticationGuard, TimelineFilterModule, MaterialModule as MaterialModule$1, ColumnSelectorModule, ImportCsvModule } from 'ngx-techlify-core';
|
|
8
|
+
import * as i8 from '@angular/material/icon';
|
|
9
|
+
import { MatIconModule, 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, NgForOf, CommonModule, CurrencyPipe, DatePipe } from '@angular/common';
|
|
14
|
+
import * as i15 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 i5 from '@angular/material/progress-bar';
|
|
17
|
+
import { MatProgressBar, MatProgressBarModule } from '@angular/material/progress-bar';
|
|
18
|
+
import * as i10 from 'ngx-infinite-scroll';
|
|
19
|
+
import { InfiniteScrollDirective, InfiniteScrollModule } from 'ngx-infinite-scroll';
|
|
20
|
+
import * as i2$1 from 'angular-google-charts';
|
|
21
|
+
import { ChartType, GoogleChartsModule } from 'angular-google-charts';
|
|
22
|
+
import * as i6 from '@angular/material/form-field';
|
|
23
|
+
import { MatFormField, MatLabel, MatSuffix, MatError, MatHint, MatFormFieldModule } from '@angular/material/form-field';
|
|
24
|
+
import * as i7 from '@angular/material/input';
|
|
25
|
+
import { MatInput, MatInputModule } 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 i14 from '@angular/material/sort';
|
|
30
|
+
import { MatSortModule, MatSortHeader, MatSort } from '@angular/material/sort';
|
|
31
|
+
import * as i2$3 from '@angular/material/tooltip';
|
|
32
|
+
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
|
|
33
|
+
import { __decorate } from 'tslib';
|
|
34
|
+
import * as i1$1 from '@angular/material/dialog';
|
|
35
|
+
import { MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogModule } from '@angular/material/dialog';
|
|
36
|
+
import * as i4$2 from 'ngx-spinner';
|
|
37
|
+
import * as i4$3 from '@angular/material/button';
|
|
38
|
+
import { MatButton, 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 { MatCommonModule, MatLineModule, MatNativeDateModule, MatOptionModule, MatPseudoCheckboxModule, MatRippleModule } from '@angular/material/core';
|
|
45
|
+
import * as i12 from '@angular/material/select';
|
|
46
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
47
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
48
|
+
import { HttpParams } from '@angular/common/http';
|
|
49
|
+
import * as i9 from '@angular/material/datepicker';
|
|
50
|
+
import { MatDatepickerInput, MatDatepickerToggle, MatDatepicker, MatDatepickerModule } from '@angular/material/datepicker';
|
|
51
|
+
import * as i10$2 from '@angular/material/checkbox';
|
|
52
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
53
|
+
import moment$1 from 'moment/moment';
|
|
54
|
+
import * as i5$1 from '@angular/material/divider';
|
|
55
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
56
|
+
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
57
|
+
import { MatBadgeModule } from '@angular/material/badge';
|
|
58
|
+
import * as i12$1 from '@angular/material/button-toggle';
|
|
59
|
+
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
60
|
+
import { MatChipsModule } from '@angular/material/chips';
|
|
61
|
+
import { MatExpansionModule } from '@angular/material/expansion';
|
|
62
|
+
import { MatGridListModule } from '@angular/material/grid-list';
|
|
63
|
+
import { MatListModule } from '@angular/material/list';
|
|
64
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
65
|
+
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
66
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
67
|
+
import { MatRadioModule } from '@angular/material/radio';
|
|
68
|
+
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
69
|
+
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
70
|
+
import { MatSliderModule } from '@angular/material/slider';
|
|
71
|
+
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
72
|
+
import { MatStepperModule } from '@angular/material/stepper';
|
|
73
|
+
import { MatTabsModule } from '@angular/material/tabs';
|
|
74
|
+
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
75
|
+
import { MatTreeModule } from '@angular/material/tree';
|
|
76
|
+
import * as i13 from 'ngx-permissions';
|
|
77
|
+
import { NgxPermissionsModule } from 'ngx-permissions';
|
|
78
|
+
|
|
79
|
+
class ProductService extends TechlifyServiceBaseClass {
|
|
80
|
+
dataManager;
|
|
81
|
+
httpService;
|
|
82
|
+
constructor(dataManager, httpService) {
|
|
83
|
+
super(httpService, 'products');
|
|
84
|
+
this.dataManager = dataManager;
|
|
85
|
+
this.httpService = httpService;
|
|
86
|
+
}
|
|
87
|
+
getProducts(filters) {
|
|
88
|
+
return this.dataManager.GET(`api/products`, filters);
|
|
89
|
+
}
|
|
90
|
+
getProduct(id) {
|
|
91
|
+
return this.dataManager.GET(`api/products/${id}`);
|
|
92
|
+
}
|
|
93
|
+
createProduct(model) {
|
|
94
|
+
return this.dataManager.POST(`api/products`, model);
|
|
95
|
+
}
|
|
96
|
+
updateProducts(model) {
|
|
97
|
+
return this.dataManager.PUT(`api/products/${model.id}`, model);
|
|
98
|
+
}
|
|
99
|
+
deleteProduct(id) {
|
|
100
|
+
return this.dataManager.DELETE(`api/products/${id}`);
|
|
101
|
+
}
|
|
102
|
+
getProductMeasures(filters) {
|
|
103
|
+
return this.dataManager.GET(`api/product-measures`, filters);
|
|
104
|
+
}
|
|
105
|
+
createProductMeasure(model) {
|
|
106
|
+
return this.dataManager.POST(`api/product-measures`, model);
|
|
107
|
+
}
|
|
108
|
+
updateProductMeasure(model) {
|
|
109
|
+
return this.dataManager.PUT(`api/product-measures/${model.id}`, model);
|
|
110
|
+
}
|
|
111
|
+
summary(params) {
|
|
112
|
+
return this.httpService.get('api/products-summary', { params });
|
|
113
|
+
}
|
|
114
|
+
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 });
|
|
115
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductService, providedIn: 'root' });
|
|
116
|
+
}
|
|
117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductService, decorators: [{
|
|
118
|
+
type: Injectable,
|
|
119
|
+
args: [{
|
|
120
|
+
providedIn: 'root',
|
|
121
|
+
}]
|
|
122
|
+
}], ctorParameters: () => [{ type: i1.DataManager }, { type: i1.HttpService }] });
|
|
123
|
+
|
|
124
|
+
class LowStockProductsWidgetComponent extends TechlifyListingControllerInterface {
|
|
125
|
+
productService;
|
|
126
|
+
displayedColumns = ['#', 'Product', 'Stock', 'Reorder Point'];
|
|
127
|
+
constructor(productService) {
|
|
128
|
+
super();
|
|
129
|
+
this.productService = productService;
|
|
130
|
+
this.lastPage = 0;
|
|
131
|
+
this.perPage = 1000;
|
|
132
|
+
}
|
|
133
|
+
ngOnInit() {
|
|
134
|
+
this.loadData();
|
|
135
|
+
}
|
|
136
|
+
loadData() {
|
|
137
|
+
const params = {
|
|
138
|
+
page: this.page,
|
|
139
|
+
perPage: this.perPage,
|
|
140
|
+
is_low_stock: true,
|
|
141
|
+
num_items: this.perPage + '|' + this.page,
|
|
142
|
+
};
|
|
143
|
+
this.isWorking = true;
|
|
144
|
+
this.productService.index(params).subscribe({
|
|
145
|
+
next: (response) => {
|
|
146
|
+
this.models = this.models?.concat(response?.data);
|
|
147
|
+
this.lastPage = response?.last_page;
|
|
148
|
+
this.isWorking = false;
|
|
149
|
+
},
|
|
150
|
+
error: () => (this.isWorking = false),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
154
|
+
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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.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: i5.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 });
|
|
155
|
+
}
|
|
156
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetComponent, decorators: [{
|
|
157
|
+
type: Component,
|
|
158
|
+
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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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" }]
|
|
159
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
160
|
+
|
|
161
|
+
class ProductSummaryChartComponent {
|
|
162
|
+
productService;
|
|
163
|
+
height = 400;
|
|
164
|
+
title = 'Product Summary';
|
|
165
|
+
constructor(productService) {
|
|
166
|
+
this.productService = productService;
|
|
167
|
+
}
|
|
168
|
+
chart = {
|
|
169
|
+
title: 'Pie Chart',
|
|
170
|
+
type: ChartType.PieChart,
|
|
171
|
+
data: [],
|
|
172
|
+
options: {
|
|
173
|
+
pieSliceText: 'value',
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
isLoading = false;
|
|
177
|
+
ngOnInit() {
|
|
178
|
+
this.loadData();
|
|
179
|
+
}
|
|
180
|
+
loadData() {
|
|
181
|
+
const params = {
|
|
182
|
+
include: 'products_aggregated',
|
|
183
|
+
group_by: 'category_id',
|
|
184
|
+
};
|
|
185
|
+
this.isLoading = true;
|
|
186
|
+
this.productService.summary(params).subscribe({
|
|
187
|
+
next: (response) => {
|
|
188
|
+
let data = [];
|
|
189
|
+
response?.products_aggregated?.forEach((item) => {
|
|
190
|
+
data.push([item?.title, item?.product_count]);
|
|
191
|
+
});
|
|
192
|
+
this.chart.data = data;
|
|
193
|
+
this.isLoading = false;
|
|
194
|
+
},
|
|
195
|
+
error: () => (this.isLoading = false),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
199
|
+
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\n class=\"w-100\"\n [height]=\"height\"\n [type]=\"chart.type\"\n [data]=\"chart.data\"\n [columns]=\"chart.columns\"\n [options]=\"chart.options\"\n >\n </google-chart>\n </mat-card-content>\n</mat-card>\n", 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 });
|
|
200
|
+
}
|
|
201
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartComponent, decorators: [{
|
|
202
|
+
type: Component,
|
|
203
|
+
args: [{ selector: 'app-product-summary-chart', standalone: true, imports: [MatCard, MatCardContent, GoogleChartsModule, MatProgressBar, NgIf], 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\n class=\"w-100\"\n [height]=\"height\"\n [type]=\"chart.type\"\n [data]=\"chart.data\"\n [columns]=\"chart.columns\"\n [options]=\"chart.options\"\n >\n </google-chart>\n </mat-card-content>\n</mat-card>\n" }]
|
|
204
|
+
}], ctorParameters: () => [{ type: ProductService }], propDecorators: { height: [{
|
|
205
|
+
type: Input
|
|
206
|
+
}], title: [{
|
|
207
|
+
type: Input
|
|
208
|
+
}] } });
|
|
209
|
+
|
|
210
|
+
const errorMessages$1 = {
|
|
211
|
+
title: {
|
|
212
|
+
required: 'Please Enter Title',
|
|
213
|
+
},
|
|
214
|
+
description: {
|
|
215
|
+
required: 'Please Enter Description',
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
class ProductMeasureFormComponent {
|
|
219
|
+
productService;
|
|
220
|
+
fb;
|
|
221
|
+
dialogRef;
|
|
222
|
+
data;
|
|
223
|
+
spinnerService;
|
|
224
|
+
formValidatorService;
|
|
225
|
+
errorService;
|
|
226
|
+
alertService;
|
|
227
|
+
productMeasureForm;
|
|
228
|
+
isWorking = false;
|
|
229
|
+
isUpdate = false;
|
|
230
|
+
constructor(productService, fb, dialogRef, data, spinnerService, formValidatorService, errorService, alertService) {
|
|
231
|
+
this.productService = productService;
|
|
232
|
+
this.fb = fb;
|
|
233
|
+
this.dialogRef = dialogRef;
|
|
234
|
+
this.data = data;
|
|
235
|
+
this.spinnerService = spinnerService;
|
|
236
|
+
this.formValidatorService = formValidatorService;
|
|
237
|
+
this.errorService = errorService;
|
|
238
|
+
this.alertService = alertService;
|
|
239
|
+
this.productMeasureForm = this.fb.group({
|
|
240
|
+
id: [''],
|
|
241
|
+
title: ['', Validators.compose([Validators.required])],
|
|
242
|
+
description: ['', Validators.compose([Validators.required])],
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
ngOnInit() {
|
|
246
|
+
if (this.data.details) {
|
|
247
|
+
this.isUpdate = true;
|
|
248
|
+
this.productMeasureForm.patchValue(this.data.details);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async save() {
|
|
252
|
+
if (!this.productMeasureForm.valid) {
|
|
253
|
+
this.alertService.addAlert('Please Fill All Required Fields', 'warn');
|
|
254
|
+
this.productMeasureForm.markAllAsTouched();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
let productMeasure = this.productMeasureForm.value;
|
|
258
|
+
try {
|
|
259
|
+
this.spinnerService.show();
|
|
260
|
+
this.isWorking = true;
|
|
261
|
+
let result = this.isUpdate
|
|
262
|
+
? await this.productService.updateProductMeasure(productMeasure)
|
|
263
|
+
: await this.productService.createProductMeasure(productMeasure);
|
|
264
|
+
this.dialogRef.close(result);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
this.errorService.handleError(error);
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
this.isWorking = false;
|
|
271
|
+
this.spinnerService.hide();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Method to evaluate form fields
|
|
276
|
+
*/
|
|
277
|
+
isFieldValid(field) {
|
|
278
|
+
return this.formValidatorService.isFieldValid(field, this.productMeasureForm);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Method to find error in form fields
|
|
282
|
+
*/
|
|
283
|
+
getErrorMessage(field) {
|
|
284
|
+
return this.formValidatorService.getErrorMessage(field, this.productMeasureForm, errorMessages$1);
|
|
285
|
+
}
|
|
286
|
+
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 });
|
|
287
|
+
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 matInput placeholder=\"Title\" formControlName=\"title\" required />\n <mat-error *ngIf=\"isFieldValid('title')\">{{ getErrorMessage('title') }} </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input matInput placeholder=\"Description\" formControlName=\"description\" required />\n <mat-error *ngIf=\"isFieldValid('description')\">{{ getErrorMessage('description') }} </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button mat-button class=\"mt-2\" type=\"button\" (click)=\"dialogRef.close()\">Cancel</button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">Save</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: i4$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.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 });
|
|
288
|
+
}
|
|
289
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasureFormComponent, decorators: [{
|
|
290
|
+
type: Component,
|
|
291
|
+
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 matInput placeholder=\"Title\" formControlName=\"title\" required />\n <mat-error *ngIf=\"isFieldValid('title')\">{{ getErrorMessage('title') }} </mat-error>\n </mat-form-field>\n <mat-form-field>\n <input matInput placeholder=\"Description\" formControlName=\"description\" required />\n <mat-error *ngIf=\"isFieldValid('description')\">{{ getErrorMessage('description') }} </mat-error>\n </mat-form-field>\n <div fxFlex=\"100%\" fxLayout fxLayoutGap=\"1rem\">\n <button mat-button class=\"mt-2\" type=\"button\" (click)=\"dialogRef.close()\">Cancel</button>\n <button mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">Save</button>\n </div>\n </div>\n </div>\n </form>\n</div>\n" }]
|
|
292
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2$2.FormBuilder }, { type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
|
|
293
|
+
type: Inject,
|
|
294
|
+
args: [MAT_DIALOG_DATA]
|
|
295
|
+
}] }, { type: i4$2.NgxSpinnerService }, { type: i1.FormValidatorService }, { type: i1.ErrorHandlerService }, { type: i1.AlertService }] });
|
|
296
|
+
|
|
297
|
+
let ProductMeasuresListComponent = class ProductMeasuresListComponent {
|
|
298
|
+
fb;
|
|
299
|
+
dialog;
|
|
300
|
+
filterService;
|
|
301
|
+
activatedRoute;
|
|
302
|
+
productService;
|
|
303
|
+
filterFormGroup;
|
|
304
|
+
lastPage;
|
|
305
|
+
page = 1;
|
|
306
|
+
perPage = 25;
|
|
307
|
+
totalItems = 0;
|
|
308
|
+
currentPage = 1;
|
|
309
|
+
num_items = 25;
|
|
310
|
+
routeFilters;
|
|
311
|
+
productMeasures = [];
|
|
312
|
+
columnDefinitions = [
|
|
313
|
+
{ def: '#', isShow: true },
|
|
314
|
+
{ def: 'Title', isShow: true },
|
|
315
|
+
{ def: 'Description', isShow: true },
|
|
316
|
+
{ def: 'Actions', isShow: true },
|
|
317
|
+
];
|
|
318
|
+
displayedColumns = ['#', 'Title', 'Description', 'Actions'];
|
|
319
|
+
dataSource = new MatTableDataSource();
|
|
320
|
+
constructor(fb, dialog, filterService, activatedRoute, productService) {
|
|
321
|
+
this.fb = fb;
|
|
322
|
+
this.dialog = dialog;
|
|
323
|
+
this.filterService = filterService;
|
|
324
|
+
this.activatedRoute = activatedRoute;
|
|
325
|
+
this.productService = productService;
|
|
326
|
+
this.filterFormGroup = this.fb.group({
|
|
327
|
+
num_items: [this.num_items + '|' + this.currentPage],
|
|
328
|
+
search: [''],
|
|
329
|
+
type_ids: [''],
|
|
330
|
+
sort_by: [''],
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
ngOnInit() {
|
|
334
|
+
this.patchFiltersFromRoute();
|
|
335
|
+
this.listenForChanges();
|
|
336
|
+
this.loadData();
|
|
337
|
+
}
|
|
338
|
+
listenForChanges() {
|
|
339
|
+
this.filterFormGroup.valueChanges.pipe(debounceTime(500), untilDestroyed(this)).subscribe((changes) => {
|
|
340
|
+
this.filterService.applyFilterToRoute(this.activatedRoute, this.filterFormGroup.value);
|
|
341
|
+
this.reload();
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
patchFiltersFromRoute() {
|
|
345
|
+
this.routeFilters = this.filterService.getFiltersFromRoute(this.activatedRoute, this.filterFormGroup.value);
|
|
346
|
+
this.filterFormGroup.setValue(this.routeFilters);
|
|
347
|
+
if (this.routeFilters.type_ids) {
|
|
348
|
+
this.filterFormGroup.get('type_ids').setValue(this.routeFilters.type_ids.split(',').map(Number));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
async loadData() {
|
|
352
|
+
let filters = this.filterFormGroup.value;
|
|
353
|
+
filters.page = this.page;
|
|
354
|
+
filters.per_page = this.perPage;
|
|
355
|
+
filters.type_ids = filters.type_ids.toString();
|
|
356
|
+
filters.num_items = this.num_items + '|' + this.currentPage;
|
|
357
|
+
let res = await this.productService.getProductMeasures(filters);
|
|
358
|
+
if (this.productMeasures.length < 1) {
|
|
359
|
+
this.productMeasures = res.data;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
res.data.forEach((item) => this.productMeasures.push(item));
|
|
363
|
+
}
|
|
364
|
+
this.dataSource = new MatTableDataSource(this.productMeasures);
|
|
365
|
+
this.totalItems = res.total;
|
|
366
|
+
this.lastPage = res.last_page || this.page;
|
|
367
|
+
}
|
|
368
|
+
reload() {
|
|
369
|
+
this.productMeasures = [];
|
|
370
|
+
this.currentPage = 1;
|
|
371
|
+
this.loadData();
|
|
372
|
+
}
|
|
373
|
+
modifyProductMeasure(model) {
|
|
374
|
+
const dialogRef = this.dialog.open(ProductMeasureFormComponent, {
|
|
375
|
+
width: '600px',
|
|
376
|
+
data: {
|
|
377
|
+
details: model,
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
381
|
+
if (result) {
|
|
382
|
+
this.reload();
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
onScroll() {
|
|
387
|
+
if (this.totalItems > this.productMeasures.length) {
|
|
388
|
+
this.currentPage += 1;
|
|
389
|
+
this.loadData();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
assignFilter(column, direction) {
|
|
393
|
+
if (column) {
|
|
394
|
+
return this.filterFormGroup.get('sort_by')?.setValue(column + '|' + direction);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
sortColumn(event) {
|
|
398
|
+
var direction = event.direction.toString().toUpperCase();
|
|
399
|
+
this.assignFilter(event.active, direction);
|
|
400
|
+
}
|
|
401
|
+
// eslint-disable-next-line @angular-eslint/use-lifecycle-interface
|
|
402
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
403
|
+
ngOnDestroy() {
|
|
404
|
+
//Called once, before the instance is destroyed.
|
|
405
|
+
//Add 'implements OnDestroy' to the class.
|
|
406
|
+
}
|
|
407
|
+
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 });
|
|
408
|
+
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 mat-raised-button class=\"ml-2\" color=\"primary\" (click)=\"modifyProductMeasure()\">\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 matInput placeholder=\"Item Name, Description, etc.\" formControlName=\"search\" />\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 *ngFor=\"let column of columnDefinitions\" [value]=\"column.def\" [disabled]=\"!column.isShow\">\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: i4$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4$3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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: i14.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i14.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.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 });
|
|
409
|
+
};
|
|
410
|
+
ProductMeasuresListComponent = __decorate([
|
|
411
|
+
UntilDestroy()
|
|
412
|
+
], ProductMeasuresListComponent);
|
|
413
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductMeasuresListComponent, decorators: [{
|
|
414
|
+
type: Component,
|
|
415
|
+
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 mat-raised-button class=\"ml-2\" color=\"primary\" (click)=\"modifyProductMeasure()\">\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 matInput placeholder=\"Item Name, Description, etc.\" formControlName=\"search\" />\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 *ngFor=\"let column of columnDefinitions\" [value]=\"column.def\" [disabled]=\"!column.isShow\">\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" }]
|
|
416
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1$1.MatDialog }, { type: i1.FilterService }, { type: i2.ActivatedRoute }, { type: ProductService }] });
|
|
417
|
+
|
|
418
|
+
class TechlifyFormService {
|
|
419
|
+
_isListUpdated = new BehaviorSubject(false);
|
|
420
|
+
isListUpdated() {
|
|
421
|
+
return this._isListUpdated.asObservable();
|
|
422
|
+
}
|
|
423
|
+
listUpdated(val) {
|
|
424
|
+
this._isListUpdated.next(val);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
class ProductFormService extends TechlifyFormService {
|
|
429
|
+
constructor() {
|
|
430
|
+
super();
|
|
431
|
+
}
|
|
432
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
433
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, providedIn: 'root' });
|
|
434
|
+
}
|
|
435
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormService, decorators: [{
|
|
436
|
+
type: Injectable,
|
|
437
|
+
args: [{
|
|
438
|
+
providedIn: 'root',
|
|
439
|
+
}]
|
|
440
|
+
}], ctorParameters: () => [] });
|
|
441
|
+
|
|
442
|
+
class StockReceiptService extends TechlifyServiceBaseClass {
|
|
443
|
+
constructor(httpService) {
|
|
444
|
+
super(httpService, 'stock-receipts');
|
|
445
|
+
}
|
|
446
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
447
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, providedIn: 'root' });
|
|
448
|
+
}
|
|
449
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptService, decorators: [{
|
|
450
|
+
type: Injectable,
|
|
451
|
+
args: [{
|
|
452
|
+
providedIn: 'root',
|
|
453
|
+
}]
|
|
454
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
455
|
+
|
|
456
|
+
class SupplierService {
|
|
457
|
+
httpService;
|
|
458
|
+
constructor(httpService) {
|
|
459
|
+
this.httpService = httpService;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* get all suppliers from API
|
|
463
|
+
*
|
|
464
|
+
* @param filters Any attributes to filter suppliers by
|
|
465
|
+
*/
|
|
466
|
+
index(filters) {
|
|
467
|
+
let queries = new HttpParams({ fromObject: filters });
|
|
468
|
+
return this.httpService.get(`api/suppliers`, { params: queries });
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* get individual supplier from API (for view page)
|
|
472
|
+
*
|
|
473
|
+
* @param id ID of the supplier being requested
|
|
474
|
+
*/
|
|
475
|
+
show(id) {
|
|
476
|
+
return this.httpService.get(`api/suppliers/${id}`);
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* store a new supplier in the DB
|
|
480
|
+
*
|
|
481
|
+
* @param model data from the supplier form that will be stored in the DB
|
|
482
|
+
*/
|
|
483
|
+
store(model) {
|
|
484
|
+
return this.httpService.post(`api/suppliers`, model);
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* update a supplier in the DB
|
|
488
|
+
*
|
|
489
|
+
* @param model.id ID of the supplier being updated
|
|
490
|
+
* @param model data from the supplier form that will be updated in the DB
|
|
491
|
+
*/
|
|
492
|
+
update(model) {
|
|
493
|
+
return this.httpService.put(`api/suppliers/${model?.id}`, model);
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* delete a supplier from the DB
|
|
497
|
+
*
|
|
498
|
+
* @param id ID of the supplier being deleted
|
|
499
|
+
*/
|
|
500
|
+
destroy(id) {
|
|
501
|
+
return this.httpService.delete(`api/suppliers/${id}`);
|
|
502
|
+
}
|
|
503
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
504
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, providedIn: 'root' });
|
|
505
|
+
}
|
|
506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierService, decorators: [{
|
|
507
|
+
type: Injectable,
|
|
508
|
+
args: [{
|
|
509
|
+
providedIn: 'root',
|
|
510
|
+
}]
|
|
511
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
512
|
+
|
|
513
|
+
class SupplierFormComponent extends TechlifyFormComponentInterface {
|
|
514
|
+
fb;
|
|
515
|
+
alertService;
|
|
516
|
+
spinnerService;
|
|
517
|
+
dialogRef;
|
|
518
|
+
errorService;
|
|
519
|
+
data;
|
|
520
|
+
supplierService;
|
|
521
|
+
errorMessages = {
|
|
522
|
+
contact_name: {
|
|
523
|
+
required: 'Contact Name is required',
|
|
524
|
+
},
|
|
525
|
+
company_name: {
|
|
526
|
+
required: 'Company Name is required',
|
|
527
|
+
},
|
|
528
|
+
address: {
|
|
529
|
+
required: 'Address is required',
|
|
530
|
+
},
|
|
531
|
+
phone: {
|
|
532
|
+
required: 'Phone is required',
|
|
533
|
+
},
|
|
534
|
+
details: {
|
|
535
|
+
required: 'Details is required',
|
|
536
|
+
},
|
|
537
|
+
email: {
|
|
538
|
+
required: 'Email is required',
|
|
539
|
+
},
|
|
540
|
+
supplier_type_id: {
|
|
541
|
+
required: 'Supplier Type is required',
|
|
542
|
+
},
|
|
543
|
+
};
|
|
544
|
+
isWorking = false;
|
|
545
|
+
isUpdateMode = false;
|
|
546
|
+
supplierForm;
|
|
547
|
+
constructor(fb, formValidatorService, alertService, spinnerService, dialogRef, errorService, data, supplierService) {
|
|
548
|
+
super(formValidatorService);
|
|
549
|
+
this.fb = fb;
|
|
550
|
+
this.alertService = alertService;
|
|
551
|
+
this.spinnerService = spinnerService;
|
|
552
|
+
this.dialogRef = dialogRef;
|
|
553
|
+
this.errorService = errorService;
|
|
554
|
+
this.data = data;
|
|
555
|
+
this.supplierService = supplierService;
|
|
556
|
+
this.supplierForm = this.fb.group({
|
|
557
|
+
id: [''],
|
|
558
|
+
contact_name: [''],
|
|
559
|
+
company_name: ['', Validators.compose([Validators.required])],
|
|
560
|
+
details: [''],
|
|
561
|
+
address: [''],
|
|
562
|
+
phone: [''],
|
|
563
|
+
email: [''],
|
|
564
|
+
supplier_type_id: [''],
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
ngOnInit() {
|
|
568
|
+
if (this.data.details) {
|
|
569
|
+
this.isUpdateMode = true;
|
|
570
|
+
this.supplierForm.patchValue(this.data.details);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
async submit() {
|
|
574
|
+
if (!this.supplierForm.valid) {
|
|
575
|
+
this.alertService.addAlert('Please Fill All Required Fields', 'warn');
|
|
576
|
+
this.supplierForm.markAllAsTouched();
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
var supplier = this.supplierForm.value;
|
|
580
|
+
try {
|
|
581
|
+
this.spinnerService.show();
|
|
582
|
+
this.isWorking = true;
|
|
583
|
+
let result = this.isUpdateMode
|
|
584
|
+
? await lastValueFrom(this.supplierService.update(supplier))
|
|
585
|
+
: await lastValueFrom(this.supplierService.store(supplier));
|
|
586
|
+
this.dialogRef.close(result);
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
this.errorService.handleError(error);
|
|
590
|
+
}
|
|
591
|
+
finally {
|
|
592
|
+
this.isWorking = false;
|
|
593
|
+
this.spinnerService.hide();
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
/**Method to evaluate form fields*/
|
|
597
|
+
isFieldValid(field) {
|
|
598
|
+
return this.formValidatorService.isFieldValid(field, this.supplierForm);
|
|
599
|
+
}
|
|
600
|
+
/**Method to find error in form fields*/
|
|
601
|
+
getErrorMessage(field) {
|
|
602
|
+
return this.formValidatorService.getErrorMessage(field, this.supplierForm, this.errorMessages);
|
|
603
|
+
}
|
|
604
|
+
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 });
|
|
605
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SupplierFormComponent, selector: "app-supplier-form", usesInheritance: true, ngImport: i0, template: "<form (ngSubmit)=\"submit()\" [formGroup]=\"supplierForm\" class=\"mat-typography\">\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 autocomplete=\"off\" formControlName=\"company_name\" matInput placeholder=\"Company Name\" required />\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 autocomplete=\"off\" formControlName=\"contact_name\" matInput placeholder=\"Contact Name\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Types</mat-label>\n <app-searchable-selector apiUrl=\"api/supplier-types\" formControlName=\"supplier_type_id\" titleField=\"title\">\n </app-searchable-selector>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Phone</mat-label>\n <input autocomplete=\"off\" formControlName=\"phone\" matInput placeholder=\"Phone\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Email</mat-label>\n <input autocomplete=\"off\" formControlName=\"email\" matInput placeholder=\"Email\" type=\"email\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Address</mat-label>\n <input autocomplete=\"off\" formControlName=\"address\" matInput placeholder=\"Address\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Details</mat-label>\n <input autocomplete=\"off\" formControlName=\"details\" matInput placeholder=\"Details\" />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button (click)=\"dialogRef.close()\" [disabled]=\"isWorking\" mat-flat-button type=\"button\">Cancel</button>\n <button [disabled]=\"isWorking\" color=\"primary\" mat-raised-button type=\"submit\">Save</button>\n </div>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$3.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: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.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 });
|
|
606
|
+
}
|
|
607
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierFormComponent, decorators: [{
|
|
608
|
+
type: Component,
|
|
609
|
+
args: [{ selector: 'app-supplier-form', template: "<form (ngSubmit)=\"submit()\" [formGroup]=\"supplierForm\" class=\"mat-typography\">\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 autocomplete=\"off\" formControlName=\"company_name\" matInput placeholder=\"Company Name\" required />\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 autocomplete=\"off\" formControlName=\"contact_name\" matInput placeholder=\"Contact Name\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Types</mat-label>\n <app-searchable-selector apiUrl=\"api/supplier-types\" formControlName=\"supplier_type_id\" titleField=\"title\">\n </app-searchable-selector>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Phone</mat-label>\n <input autocomplete=\"off\" formControlName=\"phone\" matInput placeholder=\"Phone\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Email</mat-label>\n <input autocomplete=\"off\" formControlName=\"email\" matInput placeholder=\"Email\" type=\"email\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Address</mat-label>\n <input autocomplete=\"off\" formControlName=\"address\" matInput placeholder=\"Address\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Details</mat-label>\n <input autocomplete=\"off\" formControlName=\"details\" matInput placeholder=\"Details\" />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-3\">\n <button (click)=\"dialogRef.close()\" [disabled]=\"isWorking\" mat-flat-button type=\"button\">Cancel</button>\n <button [disabled]=\"isWorking\" color=\"primary\" mat-raised-button type=\"submit\">Save</button>\n </div>\n </div>\n</form>\n" }]
|
|
610
|
+
}], 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: [{
|
|
611
|
+
type: Inject,
|
|
612
|
+
args: [MAT_DIALOG_DATA]
|
|
613
|
+
}] }, { type: SupplierService }] });
|
|
614
|
+
|
|
615
|
+
class PayeeSelectorComponent {
|
|
616
|
+
label = 'Payee';
|
|
617
|
+
appearance = 'fill';
|
|
618
|
+
required = false;
|
|
619
|
+
showAddButton = false;
|
|
620
|
+
multiple = false;
|
|
621
|
+
value;
|
|
622
|
+
onChange = () => { };
|
|
623
|
+
onTouch = () => { };
|
|
624
|
+
writeValue(value) {
|
|
625
|
+
this.value = value;
|
|
626
|
+
this.onChange(value);
|
|
627
|
+
this.onTouch(value);
|
|
628
|
+
}
|
|
629
|
+
registerOnChange(fn) {
|
|
630
|
+
this.onChange = fn;
|
|
631
|
+
}
|
|
632
|
+
registerOnTouched(fn) {
|
|
633
|
+
this.onTouch = fn;
|
|
634
|
+
}
|
|
635
|
+
SupplierFormComponent = SupplierFormComponent;
|
|
636
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
637
|
+
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: [
|
|
638
|
+
{
|
|
639
|
+
provide: NG_VALUE_ACCESSOR,
|
|
640
|
+
useExisting: forwardRef(() => PayeeSelectorComponent),
|
|
641
|
+
multi: true,
|
|
642
|
+
},
|
|
643
|
+
], 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\"> The payee field is required. </mat-error>\n</mat-form-field>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.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 });
|
|
644
|
+
}
|
|
645
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorComponent, decorators: [{
|
|
646
|
+
type: Component,
|
|
647
|
+
args: [{ selector: 'app-payee-selector', providers: [
|
|
648
|
+
{
|
|
649
|
+
provide: NG_VALUE_ACCESSOR,
|
|
650
|
+
useExisting: forwardRef(() => PayeeSelectorComponent),
|
|
651
|
+
multi: true,
|
|
652
|
+
},
|
|
653
|
+
], 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\"> The payee field is required. </mat-error>\n</mat-form-field>\n" }]
|
|
654
|
+
}], propDecorators: { label: [{
|
|
655
|
+
type: Input
|
|
656
|
+
}], appearance: [{
|
|
657
|
+
type: Input
|
|
658
|
+
}], required: [{
|
|
659
|
+
type: Input
|
|
660
|
+
}], showAddButton: [{
|
|
661
|
+
type: Input
|
|
662
|
+
}], multiple: [{
|
|
663
|
+
type: Input
|
|
664
|
+
}] } });
|
|
665
|
+
|
|
666
|
+
class StockReceiptFormComponent extends TechlifyFormComponentInterface {
|
|
667
|
+
formBuilder;
|
|
668
|
+
stockReceiptService;
|
|
669
|
+
alertService;
|
|
670
|
+
dateUtils;
|
|
671
|
+
product;
|
|
672
|
+
stockReceipt;
|
|
673
|
+
saved = new EventEmitter();
|
|
674
|
+
cancelled = new EventEmitter();
|
|
675
|
+
isWorking;
|
|
676
|
+
constructor(formValidatorService, formBuilder, stockReceiptService, alertService, dateUtils) {
|
|
677
|
+
super(formValidatorService);
|
|
678
|
+
this.formBuilder = formBuilder;
|
|
679
|
+
this.stockReceiptService = stockReceiptService;
|
|
680
|
+
this.alertService = alertService;
|
|
681
|
+
this.dateUtils = dateUtils;
|
|
682
|
+
this.errorMessages = {
|
|
683
|
+
date: {
|
|
684
|
+
required: 'The date field is required.',
|
|
685
|
+
},
|
|
686
|
+
quantity: {
|
|
687
|
+
required: 'The quantity field is required.',
|
|
688
|
+
},
|
|
689
|
+
purchase_price: {
|
|
690
|
+
required: 'The purchase price field is required.',
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
this.form = this.formBuilder.group({
|
|
694
|
+
id: [''],
|
|
695
|
+
supplier_id: [''],
|
|
696
|
+
date: [new Date(), Validators.required],
|
|
697
|
+
quantity: [1, Validators.required],
|
|
698
|
+
purchase_price: [0, Validators.required],
|
|
699
|
+
amount: [0],
|
|
700
|
+
particulars: [''],
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
ngOnInit() {
|
|
704
|
+
this.form
|
|
705
|
+
.get('quantity')
|
|
706
|
+
?.valueChanges.pipe(debounceTime$1(500))
|
|
707
|
+
.subscribe(() => this.updateTotalAmount());
|
|
708
|
+
this.form
|
|
709
|
+
.get('purchase_price')
|
|
710
|
+
?.valueChanges.pipe(debounceTime$1(500))
|
|
711
|
+
.subscribe(() => this.updateTotalAmount());
|
|
712
|
+
if (this.stockReceipt) {
|
|
713
|
+
let data = { ...this.stockReceipt };
|
|
714
|
+
if (data.date) {
|
|
715
|
+
data.date = new Date(data.date);
|
|
716
|
+
}
|
|
717
|
+
this.form.patchValue(data);
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
// on create for set default quantity and purchase price from last record
|
|
721
|
+
if (this.product?.last_stock_receipt) {
|
|
722
|
+
const { quantity, purchase_price } = this.product.last_stock_receipt;
|
|
723
|
+
this.form.patchValue({
|
|
724
|
+
quantity,
|
|
725
|
+
purchase_price,
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
save() {
|
|
731
|
+
if (this.form.invalid) {
|
|
732
|
+
this.alertService.addAlert('Please check the form for errors', 'error');
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const data = {
|
|
736
|
+
product_id: this.product?.id,
|
|
737
|
+
...this.form.value,
|
|
738
|
+
};
|
|
739
|
+
if (data.date) {
|
|
740
|
+
data.date = this.dateUtils.getYYYYMMDDString(data.date);
|
|
741
|
+
}
|
|
742
|
+
this.isWorking = true;
|
|
743
|
+
let request = this.stockReceiptService.store(data);
|
|
744
|
+
if (this.stockReceipt?.id) {
|
|
745
|
+
request = this.stockReceiptService.update(data);
|
|
746
|
+
}
|
|
747
|
+
request.subscribe({
|
|
748
|
+
next: (response) => {
|
|
749
|
+
this.isWorking = false;
|
|
750
|
+
this.saved.emit(response?.item);
|
|
751
|
+
this.alertService.addAlert('Stock Receipt Saved Successfully!', 'success');
|
|
752
|
+
},
|
|
753
|
+
error: () => (this.isWorking = false),
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
updateTotalAmount() {
|
|
757
|
+
const { purchase_price, quantity } = this.form.value;
|
|
758
|
+
const amount = parseFloat(purchase_price) * parseFloat(quantity) || 0;
|
|
759
|
+
this.form.get('amount')?.setValue(amount);
|
|
760
|
+
}
|
|
761
|
+
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 });
|
|
762
|
+
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\">{{ stockReceipt?.id ? 'Edit' : 'Receive' }} Stock for {{ product?.name }}</h3>\n<form [formGroup]=\"form\" class=\"d-flex flex-column gap-1 justify-content-start\" (submit)=\"save()\">\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 matInput [matDatepicker]=\"datePicker\" formControlName=\"date\" (focus)=\"datePicker.open()\" />\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 [disabled]=\"isWorking\" mat-raised-button color=\"primary\" type=\"submit\">Save</button>\n <button [disabled]=\"isWorking\" (click)=\"cancelled.emit()\" mat-flat-button type=\"button\">Cancel</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: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.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.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], preserveWhitespaces: true });
|
|
763
|
+
}
|
|
764
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormComponent, decorators: [{
|
|
765
|
+
type: Component,
|
|
766
|
+
args: [{ selector: 'app-stock-receipt-form', template: "<h3 class=\"text-center\">{{ stockReceipt?.id ? 'Edit' : 'Receive' }} Stock for {{ product?.name }}</h3>\n<form [formGroup]=\"form\" class=\"d-flex flex-column gap-1 justify-content-start\" (submit)=\"save()\">\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 matInput [matDatepicker]=\"datePicker\" formControlName=\"date\" (focus)=\"datePicker.open()\" />\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 [disabled]=\"isWorking\" mat-raised-button color=\"primary\" type=\"submit\">Save</button>\n <button [disabled]=\"isWorking\" (click)=\"cancelled.emit()\" mat-flat-button type=\"button\">Cancel</button>\n </div>\n</form>\n" }]
|
|
767
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: StockReceiptService }, { type: i1.AlertService }, { type: i1.DateUtils }], propDecorators: { product: [{
|
|
768
|
+
type: Input
|
|
769
|
+
}], stockReceipt: [{
|
|
770
|
+
type: Input
|
|
771
|
+
}], saved: [{
|
|
772
|
+
type: Output
|
|
773
|
+
}], cancelled: [{
|
|
774
|
+
type: Output
|
|
775
|
+
}] } });
|
|
776
|
+
|
|
777
|
+
class StockReceiptFormButtonComponent {
|
|
778
|
+
matDialog;
|
|
779
|
+
product;
|
|
780
|
+
stockReceipt;
|
|
781
|
+
icon;
|
|
782
|
+
saved = new EventEmitter();
|
|
783
|
+
matDialogRef;
|
|
784
|
+
constructor(matDialog) {
|
|
785
|
+
this.matDialog = matDialog;
|
|
786
|
+
}
|
|
787
|
+
showStockReceiptForm(templateRef) {
|
|
788
|
+
this.matDialogRef = this.matDialog.open(templateRef, { width: '500px' });
|
|
789
|
+
}
|
|
790
|
+
onStockReceiptSaved(item) {
|
|
791
|
+
this.matDialogRef.close();
|
|
792
|
+
this.saved.emit(item);
|
|
793
|
+
}
|
|
794
|
+
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 });
|
|
795
|
+
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 });
|
|
796
|
+
}
|
|
797
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormButtonComponent, decorators: [{
|
|
798
|
+
type: Component,
|
|
799
|
+
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" }]
|
|
800
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }], propDecorators: { product: [{
|
|
801
|
+
type: Input
|
|
802
|
+
}], stockReceipt: [{
|
|
803
|
+
type: Input
|
|
804
|
+
}], icon: [{
|
|
805
|
+
type: Input
|
|
806
|
+
}], saved: [{
|
|
807
|
+
type: Output
|
|
808
|
+
}] } });
|
|
809
|
+
|
|
810
|
+
class StockIssuanceService extends TechlifyServiceBaseClass {
|
|
811
|
+
constructor(httpService) {
|
|
812
|
+
super(httpService, 'stock-issuances');
|
|
813
|
+
}
|
|
814
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
815
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, providedIn: 'root' });
|
|
816
|
+
}
|
|
817
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceService, decorators: [{
|
|
818
|
+
type: Injectable,
|
|
819
|
+
args: [{
|
|
820
|
+
providedIn: 'root',
|
|
821
|
+
}]
|
|
822
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
823
|
+
|
|
824
|
+
class StockIssueFormComponent extends TechlifyFormComponentInterface {
|
|
825
|
+
formBuilder;
|
|
826
|
+
stockIssuanceService;
|
|
827
|
+
alertService;
|
|
828
|
+
dateUtils;
|
|
829
|
+
product;
|
|
830
|
+
stockIssuance;
|
|
831
|
+
issuableType;
|
|
832
|
+
issuableId;
|
|
833
|
+
saved = new EventEmitter();
|
|
834
|
+
cancelled = new EventEmitter();
|
|
835
|
+
isWorking;
|
|
836
|
+
constructor(formValidatorService, formBuilder, stockIssuanceService, alertService, dateUtils) {
|
|
837
|
+
super(formValidatorService);
|
|
838
|
+
this.formBuilder = formBuilder;
|
|
839
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
840
|
+
this.alertService = alertService;
|
|
841
|
+
this.dateUtils = dateUtils;
|
|
842
|
+
this.errorMessages = {
|
|
843
|
+
date: {
|
|
844
|
+
required: 'The date field is required.',
|
|
845
|
+
},
|
|
846
|
+
quantity: {
|
|
847
|
+
required: 'The quantity field is required.',
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
this.form = this.formBuilder.group({
|
|
851
|
+
id: [''],
|
|
852
|
+
product_id: [''],
|
|
853
|
+
date: [new Date(), Validators.required],
|
|
854
|
+
quantity: [1, Validators.required],
|
|
855
|
+
particulars: [''],
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
ngOnInit() {
|
|
859
|
+
if (this.product) {
|
|
860
|
+
this.form.get('product_id')?.setValue(this.product?.id);
|
|
861
|
+
}
|
|
862
|
+
if (this.stockIssuance) {
|
|
863
|
+
let data = { ...this.stockIssuance };
|
|
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 from last record
|
|
871
|
+
if (this.product?.last_stock_issuance) {
|
|
872
|
+
const { quantity } = this.product.last_stock_issuance;
|
|
873
|
+
this.form.patchValue({
|
|
874
|
+
quantity,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
save() {
|
|
880
|
+
if (this.form.invalid) {
|
|
881
|
+
this.alertService.addAlert('Please check the form for errors', 'error');
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
const data = {
|
|
885
|
+
product_id: this.product?.id,
|
|
886
|
+
...this.form.value,
|
|
887
|
+
};
|
|
888
|
+
if (data.date) {
|
|
889
|
+
data.date = this.dateUtils.getYYYYMMDDString(data.date);
|
|
890
|
+
}
|
|
891
|
+
if (this.issuableId && this.issuableType) {
|
|
892
|
+
data.issuable_type = this.issuableType;
|
|
893
|
+
data.issuable_id = this.issuableId;
|
|
894
|
+
}
|
|
895
|
+
this.isWorking = true;
|
|
896
|
+
let request = this.stockIssuanceService.store(data);
|
|
897
|
+
if (this.stockIssuance?.id) {
|
|
898
|
+
request = this.stockIssuanceService.update(data);
|
|
899
|
+
}
|
|
900
|
+
request.subscribe({
|
|
901
|
+
next: (response) => {
|
|
902
|
+
this.isWorking = false;
|
|
903
|
+
this.saved.emit(response?.item);
|
|
904
|
+
this.alertService.addAlert('Stock Issuance Saved Successfully!', 'success');
|
|
905
|
+
},
|
|
906
|
+
error: () => (this.isWorking = false),
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
onProductChange(product) {
|
|
910
|
+
this.product = product;
|
|
911
|
+
}
|
|
912
|
+
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 });
|
|
913
|
+
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\">{{ stockIssuance?.id ? 'Edit' : 'Issue' }} Stock for {{ product?.name }}</h3>\n<form [formGroup]=\"form\" class=\"d-flex flex-column gap-1 justify-content-start\" (submit)=\"save()\">\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 matInput [matDatepicker]=\"datePicker\" formControlName=\"date\" (focus)=\"datePicker.open()\" />\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 [disabled]=\"isWorking\" mat-raised-button color=\"primary\" type=\"submit\">Save</button>\n <button [disabled]=\"isWorking\" (click)=\"cancelled.emit()\" mat-flat-button type=\"button\">Cancel</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: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.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.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4$3.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 });
|
|
914
|
+
}
|
|
915
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormComponent, decorators: [{
|
|
916
|
+
type: Component,
|
|
917
|
+
args: [{ selector: 'app-stock-issue-form', template: "<h3 class=\"text-center\">{{ stockIssuance?.id ? 'Edit' : 'Issue' }} Stock for {{ product?.name }}</h3>\n<form [formGroup]=\"form\" class=\"d-flex flex-column gap-1 justify-content-start\" (submit)=\"save()\">\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 matInput [matDatepicker]=\"datePicker\" formControlName=\"date\" (focus)=\"datePicker.open()\" />\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 [disabled]=\"isWorking\" mat-raised-button color=\"primary\" type=\"submit\">Save</button>\n <button [disabled]=\"isWorking\" (click)=\"cancelled.emit()\" mat-flat-button type=\"button\">Cancel</button>\n </div>\n</form>\n" }]
|
|
918
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: StockIssuanceService }, { type: i1.AlertService }, { type: i1.DateUtils }], propDecorators: { product: [{
|
|
919
|
+
type: Input
|
|
920
|
+
}], stockIssuance: [{
|
|
921
|
+
type: Input
|
|
922
|
+
}], issuableType: [{
|
|
923
|
+
type: Input
|
|
924
|
+
}], issuableId: [{
|
|
925
|
+
type: Input
|
|
926
|
+
}], saved: [{
|
|
927
|
+
type: Output
|
|
928
|
+
}], cancelled: [{
|
|
929
|
+
type: Output
|
|
930
|
+
}] } });
|
|
931
|
+
|
|
932
|
+
class StockIssueFormButtonComponent {
|
|
933
|
+
matDialog;
|
|
934
|
+
product;
|
|
935
|
+
stockIssuance;
|
|
936
|
+
icon;
|
|
937
|
+
issuableType;
|
|
938
|
+
issuableId;
|
|
939
|
+
saved = new EventEmitter();
|
|
940
|
+
matDialogRef;
|
|
941
|
+
constructor(matDialog) {
|
|
942
|
+
this.matDialog = matDialog;
|
|
943
|
+
}
|
|
944
|
+
showStockIssuanceForm(templateRef) {
|
|
945
|
+
this.matDialogRef = this.matDialog.open(templateRef, { width: '500px' });
|
|
946
|
+
}
|
|
947
|
+
onStockIssuanceSaved(item) {
|
|
948
|
+
this.matDialogRef.close();
|
|
949
|
+
this.saved.emit(item);
|
|
950
|
+
}
|
|
951
|
+
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 });
|
|
952
|
+
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 Issue\"\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 });
|
|
953
|
+
}
|
|
954
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormButtonComponent, decorators: [{
|
|
955
|
+
type: Component,
|
|
956
|
+
args: [{ selector: 'app-stock-issue-form-button', template: "<span\n class=\"material-symbols-outlined cursor-pointer\"\n [class.text-primary]=\"icon\"\n matTooltip=\"Stock Issue\"\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" }]
|
|
957
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }], propDecorators: { product: [{
|
|
958
|
+
type: Input
|
|
959
|
+
}], stockIssuance: [{
|
|
960
|
+
type: Input
|
|
961
|
+
}], icon: [{
|
|
962
|
+
type: Input
|
|
963
|
+
}], issuableType: [{
|
|
964
|
+
type: Input
|
|
965
|
+
}], issuableId: [{
|
|
966
|
+
type: Input
|
|
967
|
+
}], saved: [{
|
|
968
|
+
type: Output
|
|
969
|
+
}] } });
|
|
970
|
+
|
|
971
|
+
const initial_quantity = 0;
|
|
972
|
+
const reorder_point = 10;
|
|
973
|
+
const errorMessages = {
|
|
974
|
+
type_id: {
|
|
975
|
+
required: 'Please Enter Type',
|
|
976
|
+
},
|
|
977
|
+
name: {
|
|
978
|
+
required: 'Please Enter Name',
|
|
979
|
+
},
|
|
980
|
+
sale_price: {
|
|
981
|
+
required: 'Please Enter Sales Price',
|
|
982
|
+
},
|
|
983
|
+
minimum_price: {
|
|
984
|
+
required: 'Please Enter Minimum Price',
|
|
985
|
+
},
|
|
986
|
+
reorder_point: {
|
|
987
|
+
required: 'Please Enter Reorder Point',
|
|
988
|
+
},
|
|
989
|
+
};
|
|
990
|
+
class ProductFormComponent {
|
|
991
|
+
productService;
|
|
992
|
+
fb;
|
|
993
|
+
formValidatorService;
|
|
994
|
+
alertService;
|
|
995
|
+
datePipe;
|
|
996
|
+
productFormService;
|
|
997
|
+
productForm;
|
|
998
|
+
isWorking = false;
|
|
999
|
+
isUpdate = false;
|
|
1000
|
+
saved = new EventEmitter();
|
|
1001
|
+
cancelled = new EventEmitter();
|
|
1002
|
+
product;
|
|
1003
|
+
displayedFormFields = [
|
|
1004
|
+
'name',
|
|
1005
|
+
'product type',
|
|
1006
|
+
'sku',
|
|
1007
|
+
'description',
|
|
1008
|
+
'product measure',
|
|
1009
|
+
'reorder point',
|
|
1010
|
+
'initial quantity',
|
|
1011
|
+
'initial quantity date',
|
|
1012
|
+
'sales price',
|
|
1013
|
+
'minimum price',
|
|
1014
|
+
'maximum price',
|
|
1015
|
+
'income account',
|
|
1016
|
+
'expense account',
|
|
1017
|
+
];
|
|
1018
|
+
displayedFormSections = [
|
|
1019
|
+
'basic information',
|
|
1020
|
+
'inventory information',
|
|
1021
|
+
'sales information',
|
|
1022
|
+
'accounts information',
|
|
1023
|
+
];
|
|
1024
|
+
constructor(productService, fb, formValidatorService, alertService, datePipe, productFormService) {
|
|
1025
|
+
this.productService = productService;
|
|
1026
|
+
this.fb = fb;
|
|
1027
|
+
this.formValidatorService = formValidatorService;
|
|
1028
|
+
this.alertService = alertService;
|
|
1029
|
+
this.datePipe = datePipe;
|
|
1030
|
+
this.productFormService = productFormService;
|
|
1031
|
+
this.productForm = this.fb.group({
|
|
1032
|
+
id: [''],
|
|
1033
|
+
type_id: [1, Validators.compose([Validators.required])],
|
|
1034
|
+
sku: [''],
|
|
1035
|
+
name: ['', Validators.compose([Validators.required])],
|
|
1036
|
+
initial_quantity: [initial_quantity],
|
|
1037
|
+
initial_quantity_date: [moment().format()],
|
|
1038
|
+
reorder_point: [reorder_point, Validators.compose([Validators.required])],
|
|
1039
|
+
description: [''],
|
|
1040
|
+
sale_price: [0, Validators.compose([Validators.required])],
|
|
1041
|
+
income_account_id: [''],
|
|
1042
|
+
expense_account_id: [''],
|
|
1043
|
+
measure_id: [1],
|
|
1044
|
+
minimum_price: ['', Validators.compose([Validators.required])],
|
|
1045
|
+
maximum_price: [''],
|
|
1046
|
+
condition_type_id: [1],
|
|
1047
|
+
current_quantity: [],
|
|
1048
|
+
category_ids: [''],
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
ngOnInit() {
|
|
1052
|
+
if (this.product?.id) {
|
|
1053
|
+
this.isUpdate = true;
|
|
1054
|
+
let data = { ...this.product };
|
|
1055
|
+
if (this.product?.categories?.length > 0) {
|
|
1056
|
+
data.category_ids = this.product.categories.map((category) => category?.id);
|
|
1057
|
+
}
|
|
1058
|
+
if (data?.initial_quantity_date) {
|
|
1059
|
+
data.initial_quantity_date = moment(data.initial_quantity_date).toISOString();
|
|
1060
|
+
}
|
|
1061
|
+
this.productForm.patchValue(data);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
async save() {
|
|
1065
|
+
this.productForm.markAllAsTouched();
|
|
1066
|
+
if (this.productForm.invalid) {
|
|
1067
|
+
this.alertService.addAlert('Please Fill All Required Fields', 'warn');
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
let product = this.productForm.value;
|
|
1071
|
+
if (product.maximum_price <= 0 || !product.maximum_price) {
|
|
1072
|
+
product.maximum_price = product.minimum_price;
|
|
1073
|
+
}
|
|
1074
|
+
if (product?.initial_quantity_date) {
|
|
1075
|
+
product.initial_quantity_date = moment(product.initial_quantity_date).format('YYYY-MM-DD');
|
|
1076
|
+
}
|
|
1077
|
+
this.isWorking = true;
|
|
1078
|
+
product.with = 'type,measure,incomeAccount,expenseAccount';
|
|
1079
|
+
let request = this.productService.store(product);
|
|
1080
|
+
if (this.isUpdate) {
|
|
1081
|
+
request = this.productService.update(product);
|
|
1082
|
+
}
|
|
1083
|
+
request.subscribe({
|
|
1084
|
+
next: (response) => {
|
|
1085
|
+
this.saved.emit(response?.item);
|
|
1086
|
+
this.isWorking = false;
|
|
1087
|
+
this.productFormService.listUpdated(true);
|
|
1088
|
+
this.alertService.addAlert('Product saved successfully!', 'success');
|
|
1089
|
+
},
|
|
1090
|
+
error: () => (this.isWorking = false),
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Method to evaluate form fields
|
|
1095
|
+
*/
|
|
1096
|
+
isFieldValid(field) {
|
|
1097
|
+
return this.formValidatorService.isFieldValid(field, this.productForm);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Method to find error in form fields
|
|
1101
|
+
*/
|
|
1102
|
+
getErrorMessage(field) {
|
|
1103
|
+
return this.formValidatorService.getErrorMessage(field, this.productForm, errorMessages);
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Checks displayed Form Fields array for form field and returns boolean result
|
|
1107
|
+
*/
|
|
1108
|
+
isFormFieldShown(fieldName) {
|
|
1109
|
+
return this.displayedFormFields.length > 0 && this.displayedFormFields.includes(fieldName);
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Checks displayed Form Section array for form section and returns boolean result
|
|
1113
|
+
*/
|
|
1114
|
+
isFormSectionShown(sectionName) {
|
|
1115
|
+
return this.displayedFormSections.length > 0 && this.displayedFormSections.includes(sectionName);
|
|
1116
|
+
}
|
|
1117
|
+
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 });
|
|
1118
|
+
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')\">{{ getErrorMessage('name') }} </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 apiUrl=\"api/product-types\" formControlName=\"type_id\"> </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\">{{ getErrorMessage('type_id') }} </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')\">{{ getErrorMessage('sku') }} </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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 matInput placeholder=\"Description\" formControlName=\"description\"></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 fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product measure')\">\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_id\">\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\">{{ getErrorMessage('measure_id') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input matInput placeholder=\"Reorder Point\" formControlName=\"reorder_point\" type=\"number\" />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\">{{ getErrorMessage('reorder_point') }} </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('initial quantity')\">\n <input matInput placeholder=\"Initial Quantity\" formControlName=\"initial_quantity\" />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\">{{ getErrorMessage('initial_quantity') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('initial quantity date')\">\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle matSuffix [for]=\"pickerInitialQuantityDate\"></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 matInput placeholder=\"Selling Price\" formControlName=\"sale_price\" required type=\"number\" step=\"any\" />\n <mat-error *ngIf=\"isFieldValid('sale_price')\">{{ getErrorMessage('sale_price') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('condition types')\">\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')\">{{ getErrorMessage('minimum_price') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input matInput placeholder=\"Maximum Price\" formControlName=\"maximum_price\" type=\"number\" step=\"any\" />\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 [disabled]=\"isWorking\" mat-button class=\"mt-2\" type=\"button\" (click)=\"cancelled.emit(true)\">\n Cancel\n </button>\n <button [disabled]=\"isWorking\" mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">Save</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: i4$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i7.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.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9.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 });
|
|
1119
|
+
}
|
|
1120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormComponent, decorators: [{
|
|
1121
|
+
type: Component,
|
|
1122
|
+
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')\">{{ getErrorMessage('name') }} </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 apiUrl=\"api/product-types\" formControlName=\"type_id\"> </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('type_id')\">{{ getErrorMessage('type_id') }} </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')\">{{ getErrorMessage('sku') }} </mat-error>\n </mat-form-field>\n\n <mat-form-field fxFlex=\"50%\">\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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 matInput placeholder=\"Description\" formControlName=\"description\"></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 fxFlex=\"50%\" *ngIf=\"isFormFieldShown('product measure')\">\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_id\">\n </app-searchable-selector>\n <mat-error *ngIf=\"isFieldValid('measure_id')\">{{ getErrorMessage('measure_id') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('reorder point')\">\n <input matInput placeholder=\"Reorder Point\" formControlName=\"reorder_point\" type=\"number\" />\n <mat-error *ngIf=\"isFieldValid('reorder_point')\">{{ getErrorMessage('reorder_point') }} </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout fxLayoutGap=\"0.5rem\">\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('initial quantity')\">\n <input matInput placeholder=\"Initial Quantity\" formControlName=\"initial_quantity\" />\n <mat-error *ngIf=\"isFieldValid('initial_quantity')\">{{ getErrorMessage('initial_quantity') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('initial quantity date')\">\n <input\n matInput\n [matDatepicker]=\"pickerInitialQuantityDate\"\n placeholder=\"Initial Quantity Date\"\n formControlName=\"initial_quantity_date\"\n />\n <mat-datepicker-toggle matSuffix [for]=\"pickerInitialQuantityDate\"></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 matInput placeholder=\"Selling Price\" formControlName=\"sale_price\" required type=\"number\" step=\"any\" />\n <mat-error *ngIf=\"isFieldValid('sale_price')\">{{ getErrorMessage('sale_price') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('condition types')\">\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')\">{{ getErrorMessage('minimum_price') }} </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex=\"50%\" *ngIf=\"isFormFieldShown('maximum price')\">\n <input matInput placeholder=\"Maximum Price\" formControlName=\"maximum_price\" type=\"number\" step=\"any\" />\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 [disabled]=\"isWorking\" mat-button class=\"mt-2\" type=\"button\" (click)=\"cancelled.emit(true)\">\n Cancel\n </button>\n <button [disabled]=\"isWorking\" mat-raised-button color=\"primary\" class=\"mt-2\" type=\"submit\">Save</button>\n </div>\n </div>\n</form>\n" }]
|
|
1123
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2$2.FormBuilder }, { type: i1.FormValidatorService }, { type: i1.AlertService }, { type: i4.DatePipe }, { type: ProductFormService }], propDecorators: { saved: [{
|
|
1124
|
+
type: Output
|
|
1125
|
+
}], cancelled: [{
|
|
1126
|
+
type: Output
|
|
1127
|
+
}], product: [{
|
|
1128
|
+
type: Input
|
|
1129
|
+
}], displayedFormFields: [{
|
|
1130
|
+
type: Input
|
|
1131
|
+
}], displayedFormSections: [{
|
|
1132
|
+
type: Input
|
|
1133
|
+
}] } });
|
|
1134
|
+
|
|
1135
|
+
class ProductFormButtonComponent {
|
|
1136
|
+
matDialog;
|
|
1137
|
+
productFormService;
|
|
1138
|
+
product;
|
|
1139
|
+
saved = new EventEmitter();
|
|
1140
|
+
constructor(matDialog, productFormService) {
|
|
1141
|
+
this.matDialog = matDialog;
|
|
1142
|
+
this.productFormService = productFormService;
|
|
1143
|
+
}
|
|
1144
|
+
showForm(templateRef) {
|
|
1145
|
+
this.matDialog.open(templateRef, { width: '600px' });
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Handle on product saved event.
|
|
1149
|
+
*
|
|
1150
|
+
* @param product
|
|
1151
|
+
*/
|
|
1152
|
+
onProductSaved(product) {
|
|
1153
|
+
this.saved.emit(product);
|
|
1154
|
+
this.matDialog?.closeAll();
|
|
1155
|
+
this.productFormService.listUpdated(true);
|
|
1156
|
+
}
|
|
1157
|
+
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 });
|
|
1158
|
+
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 color=\"primary\" class=\"cursor-pointer\" [class.text-secondary]=\"product\" (click)=\"showForm(addProductForm)\">\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: i8.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 });
|
|
1159
|
+
}
|
|
1160
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductFormButtonComponent, decorators: [{
|
|
1161
|
+
type: Component,
|
|
1162
|
+
args: [{ selector: 'app-product-form-button', template: "<mat-icon color=\"primary\" class=\"cursor-pointer\" [class.text-secondary]=\"product\" (click)=\"showForm(addProductForm)\">\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" }]
|
|
1163
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductFormService }], propDecorators: { product: [{
|
|
1164
|
+
type: Input
|
|
1165
|
+
}], saved: [{
|
|
1166
|
+
type: Output
|
|
1167
|
+
}] } });
|
|
1168
|
+
|
|
1169
|
+
class ProductBatchService extends TechlifyServiceBaseClass {
|
|
1170
|
+
httpService;
|
|
1171
|
+
constructor(httpService) {
|
|
1172
|
+
super(httpService, 'products-batch');
|
|
1173
|
+
this.httpService = httpService;
|
|
1174
|
+
}
|
|
1175
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBatchService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1176
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBatchService, providedIn: 'root' });
|
|
1177
|
+
}
|
|
1178
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBatchService, decorators: [{
|
|
1179
|
+
type: Injectable,
|
|
1180
|
+
args: [{
|
|
1181
|
+
providedIn: 'root'
|
|
1182
|
+
}]
|
|
1183
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
1184
|
+
|
|
1185
|
+
class ProductBatchUpdateFormComponent extends TechlifyFormComponentInterface {
|
|
1186
|
+
formBuilder;
|
|
1187
|
+
alertService;
|
|
1188
|
+
batchService;
|
|
1189
|
+
selection;
|
|
1190
|
+
updated = new EventEmitter();
|
|
1191
|
+
isSaving;
|
|
1192
|
+
constructor(formValidatorService, formBuilder, alertService, batchService) {
|
|
1193
|
+
super(formValidatorService);
|
|
1194
|
+
this.formBuilder = formBuilder;
|
|
1195
|
+
this.alertService = alertService;
|
|
1196
|
+
this.batchService = batchService;
|
|
1197
|
+
this.form = this.formBuilder.group({
|
|
1198
|
+
type_id: [''],
|
|
1199
|
+
category_ids: [''],
|
|
1200
|
+
measure_id: [''],
|
|
1201
|
+
reorder_point: ['']
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
save() {
|
|
1205
|
+
const data = { ...this.form.value };
|
|
1206
|
+
data.ids = this.selection.selected.map((product) => product?.id);
|
|
1207
|
+
this.isSaving = true;
|
|
1208
|
+
this.batchService.store(data).subscribe({
|
|
1209
|
+
next: () => {
|
|
1210
|
+
this.isSaving = false;
|
|
1211
|
+
this.alertService.addAlert('The products updated successfully!', 'success');
|
|
1212
|
+
this.selection.clear();
|
|
1213
|
+
this.updated.emit();
|
|
1214
|
+
},
|
|
1215
|
+
error: () => {
|
|
1216
|
+
this.isSaving = false;
|
|
1217
|
+
}
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBatchUpdateFormComponent, deps: [{ token: i1.FormValidatorService }, { token: i2$2.FormBuilder }, { token: i1.AlertService }, { token: ProductBatchService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1221
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductBatchUpdateFormComponent, selector: "app-product-batch-update-form", inputs: { selection: "selection" }, outputs: { updated: "updated" }, usesInheritance: true, ngImport: i0, template: "<p class=\"text-primary fw-bold\">{{ selection.selected.length }} Product(s) Selected</p>\n<form [formGroup]=\"form\" class=\"d-flex flex-column justify-content-start\" (submit)=\"save()\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <app-searchable-selector apiUrl=\"api/product-types\" formControlName=\"type_id\"></app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_id\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Reorder Point</mat-label>\n <input matInput placeholder=\"Reorder Point\" formControlName=\"reorder_point\" type=\"number\" />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2 mt-3\">\n <button [disabled]=\"isSaving\" type=\"submit\" mat-raised-button color=\"primary\">Update</button>\n <button [disabled]=\"isSaving\" mat-flat-button type=\"button\" (click)=\"selection.clear()\">Cancel</button>\n </div>\n</form>\n", styles: [""], dependencies: [{ 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: i4$3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.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: 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.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 });
|
|
1222
|
+
}
|
|
1223
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBatchUpdateFormComponent, decorators: [{
|
|
1224
|
+
type: Component,
|
|
1225
|
+
args: [{ selector: 'app-product-batch-update-form', template: "<p class=\"text-primary fw-bold\">{{ selection.selected.length }} Product(s) Selected</p>\n<form [formGroup]=\"form\" class=\"d-flex flex-column justify-content-start\" (submit)=\"save()\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <app-searchable-selector apiUrl=\"api/product-types\" formControlName=\"type_id\"></app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_id\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Reorder Point</mat-label>\n <input matInput placeholder=\"Reorder Point\" formControlName=\"reorder_point\" type=\"number\" />\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2 mt-3\">\n <button [disabled]=\"isSaving\" type=\"submit\" mat-raised-button color=\"primary\">Update</button>\n <button [disabled]=\"isSaving\" mat-flat-button type=\"button\" (click)=\"selection.clear()\">Cancel</button>\n </div>\n</form>\n" }]
|
|
1226
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: i1.AlertService }, { type: ProductBatchService }], propDecorators: { selection: [{
|
|
1227
|
+
type: Input
|
|
1228
|
+
}], updated: [{
|
|
1229
|
+
type: Output
|
|
1230
|
+
}] } });
|
|
1231
|
+
|
|
1232
|
+
let ProductListComponent = class ProductListComponent extends TechlifyListingControllerInterface {
|
|
1233
|
+
fb;
|
|
1234
|
+
dialog;
|
|
1235
|
+
activatedRoute;
|
|
1236
|
+
productService;
|
|
1237
|
+
requestHelperService;
|
|
1238
|
+
productFormService;
|
|
1239
|
+
selection = new SelectionModel(true, []);
|
|
1240
|
+
columnConfig = [
|
|
1241
|
+
{ label: 'Initial Quantity', def: 'initial_quantity', isSelected: false, isEditable: true },
|
|
1242
|
+
{ label: 'Income Account', def: 'income_account', isSelected: false, isEditable: true },
|
|
1243
|
+
{ label: 'Expense Account', def: 'expense_account', isSelected: false, isEditable: true },
|
|
1244
|
+
{ label: 'Creator', def: 'creator', isSelected: false, isEditable: true },
|
|
1245
|
+
];
|
|
1246
|
+
selectedColumns = this.columnConfig.filter((col) => col.isSelected);
|
|
1247
|
+
get displayedColumns() {
|
|
1248
|
+
const selectedColumns = this.selectedColumns.map((col) => col.def);
|
|
1249
|
+
const defaultColumns = [
|
|
1250
|
+
'#', 'name', 'sku', 'categories', 'reorder_point', 'stock_receipts', 'stock_issuances',
|
|
1251
|
+
'on_hand', 'sale_price'
|
|
1252
|
+
];
|
|
1253
|
+
return defaultColumns.concat(...selectedColumns, 'Actions', 'Select');
|
|
1254
|
+
}
|
|
1255
|
+
importId;
|
|
1256
|
+
constructor(fb, dialog, activatedRoute, productService, requestHelperService, productFormService) {
|
|
1257
|
+
super();
|
|
1258
|
+
this.fb = fb;
|
|
1259
|
+
this.dialog = dialog;
|
|
1260
|
+
this.activatedRoute = activatedRoute;
|
|
1261
|
+
this.productService = productService;
|
|
1262
|
+
this.requestHelperService = requestHelperService;
|
|
1263
|
+
this.productFormService = productFormService;
|
|
1264
|
+
this.filterForm = this.fb.group({
|
|
1265
|
+
search: [''],
|
|
1266
|
+
category_ids: [''],
|
|
1267
|
+
type_ids: [''],
|
|
1268
|
+
income_account_ids: [''],
|
|
1269
|
+
expense_account_ids: [''],
|
|
1270
|
+
sort_by: [''],
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
ngOnInit() {
|
|
1274
|
+
if (this.activatedRoute.snapshot.params?.['import_id']) {
|
|
1275
|
+
this.importId = parseInt(this.activatedRoute.snapshot.params?.['import_id']);
|
|
1276
|
+
}
|
|
1277
|
+
// update form with URL query params
|
|
1278
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
1279
|
+
type_ids: { multiple: true },
|
|
1280
|
+
category_ids: { multiple: true },
|
|
1281
|
+
income_account_ids: { multiple: true },
|
|
1282
|
+
expense_account_ids: { multiple: true },
|
|
1283
|
+
});
|
|
1284
|
+
// Update URL query params on filter change
|
|
1285
|
+
this.filterForm.valueChanges.pipe(debounceTime(800)).subscribe(() => {
|
|
1286
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData({
|
|
1287
|
+
...this.filterForm.value,
|
|
1288
|
+
}));
|
|
1289
|
+
});
|
|
1290
|
+
// fetch task on params change
|
|
1291
|
+
this.activatedRoute.queryParams.pipe(debounceTime(800)).subscribe(() => this.reload());
|
|
1292
|
+
// listen form product add or update event and reload.
|
|
1293
|
+
this.productFormService.isListUpdated().subscribe((val) => {
|
|
1294
|
+
if (val && !this.isWorking) {
|
|
1295
|
+
this.reload();
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
loadData() {
|
|
1300
|
+
let params = {
|
|
1301
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1302
|
+
};
|
|
1303
|
+
params.page = this.page;
|
|
1304
|
+
params.perPage = this.perPage;
|
|
1305
|
+
params.with = 'categories,lastStockReceipt,lastStockIssuance,creator';
|
|
1306
|
+
if (this.importId) {
|
|
1307
|
+
params.import_id = this.importId;
|
|
1308
|
+
}
|
|
1309
|
+
this.isWorking = true;
|
|
1310
|
+
this.productService.index(params).subscribe({
|
|
1311
|
+
next: (res) => {
|
|
1312
|
+
this.isWorking = false;
|
|
1313
|
+
this.models = this.models.concat(res?.data);
|
|
1314
|
+
this.lastPage = res?.last_page;
|
|
1315
|
+
// stop reloading data once data loaded.
|
|
1316
|
+
this.productFormService.listUpdated(false);
|
|
1317
|
+
},
|
|
1318
|
+
error: () => (this.isWorking = false),
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
assignFilter(column, direction) {
|
|
1322
|
+
if (column) {
|
|
1323
|
+
return this.filterForm.get('sort_by')?.setValue(column + '|' + direction);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
sortColumn(event) {
|
|
1327
|
+
var direction = event.direction.toString().toUpperCase();
|
|
1328
|
+
this.assignFilter(event.active, direction);
|
|
1329
|
+
}
|
|
1330
|
+
isAllRowsSelected() {
|
|
1331
|
+
const numSelected = this.selection.selected.length;
|
|
1332
|
+
const numRows = this.models.length;
|
|
1333
|
+
return numSelected === numRows;
|
|
1334
|
+
}
|
|
1335
|
+
/** Selects all rows if they are not all selected; otherwise clear selection. */
|
|
1336
|
+
toggleAllRows() {
|
|
1337
|
+
if (this.isAllRowsSelected()) {
|
|
1338
|
+
this.selection.clear();
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
this.selection.select(...this.models);
|
|
1342
|
+
}
|
|
1343
|
+
checkboxLabel(row) {
|
|
1344
|
+
if (!row) {
|
|
1345
|
+
return `${this.isAllRowsSelected() ? 'deselect' : 'select'} all`;
|
|
1346
|
+
}
|
|
1347
|
+
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
|
|
1348
|
+
}
|
|
1349
|
+
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 });
|
|
1350
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductListComponent, selector: "app-product-list", usesInheritance: true, ngImport: i0, template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-between align-items-center gap-2\">\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_upload\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-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>\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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\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 </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<div class=\"d-flex justify-content-start gap-3\">\n <mat-card [style.width]=\"selection.isEmpty() ? '100%' : '85%'\">\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 [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 class=\"badge bg-secondary\" *ngFor=\"let category of element?.categories\">\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>Initial Quantity</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>Stock Receipts</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>Stock Issuances</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 [product]=\"element\"></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 [product]=\"element\" (saved)=\"reload()\"></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button [product]=\"element\" (saved)=\"reload()\"></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllRowsSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected()\"\n [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\"\n [checked]=\"selection.isSelected(row)\"\n [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></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 <mat-card\n *ngIf=\"!selection.isEmpty()\"\n style=\"width: calc(15% - 1rem)\"\n >\n <mat-card-content>\n <app-product-batch-update-form [selection]=\"selection\" (updated)=\"reload()\"></app-product-batch-update-form>\n </mat-card-content>\n </mat-card>\n</div>\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: i10$2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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: i14.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i14.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i15.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.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: i5.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: "component", type: ProductBatchUpdateFormComponent, selector: "app-product-batch-update-form", inputs: ["selection"], outputs: ["updated"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1351
|
+
};
|
|
1352
|
+
ProductListComponent = __decorate([
|
|
1353
|
+
UntilDestroy()
|
|
1354
|
+
], ProductListComponent);
|
|
1355
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductListComponent, decorators: [{
|
|
1356
|
+
type: Component,
|
|
1357
|
+
args: [{ selector: 'app-product-list', template: "<mat-card class=\"mb-3\">\n <mat-card-content>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-between align-items-center gap-2\">\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_upload\n </span>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-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>\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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\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 </div>\n </form>\n </mat-card-content>\n</mat-card>\n\n<div class=\"d-flex justify-content-start gap-3\">\n <mat-card [style.width]=\"selection.isEmpty() ? '100%' : '85%'\">\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 [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 class=\"badge bg-secondary\" *ngFor=\"let category of element?.categories\">\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>Initial Quantity</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>Stock Receipts</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>Stock Issuances</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 [product]=\"element\"></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 [product]=\"element\" (saved)=\"reload()\"></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button [product]=\"element\" (saved)=\"reload()\"></app-stock-issue-form-button>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"selection.hasValue() && isAllRowsSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected()\"\n [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\"\n [checked]=\"selection.isSelected(row)\"\n [aria-label]=\"checkboxLabel(row)\">\n </mat-checkbox>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></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 <mat-card\n *ngIf=\"!selection.isEmpty()\"\n style=\"width: calc(15% - 1rem)\"\n >\n <mat-card-content>\n <app-product-batch-update-form [selection]=\"selection\" (updated)=\"reload()\"></app-product-batch-update-form>\n </mat-card-content>\n </mat-card>\n</div>\n" }]
|
|
1358
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1$1.MatDialog }, { type: i2.ActivatedRoute }, { type: ProductService }, { type: i1.RequestHelperService }, { type: ProductFormService }] });
|
|
1359
|
+
|
|
1360
|
+
class ProductNavBarComponent {
|
|
1361
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1362
|
+
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 });
|
|
1363
|
+
}
|
|
1364
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductNavBarComponent, decorators: [{
|
|
1365
|
+
type: Component,
|
|
1366
|
+
args: [{ selector: 'app-product-nav-bar', template: "<div>\n <router-outlet></router-outlet>\n</div>\n" }]
|
|
1367
|
+
}] });
|
|
1368
|
+
|
|
1369
|
+
class ProductCategoryBadgesComponent {
|
|
1370
|
+
product;
|
|
1371
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductCategoryBadgesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1372
|
+
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: "<div *ngIf=\"product?.categories?.length > 0\" class=\"d-flex justify-content-start align-items-center gap-1\">\n <span class=\"badge bg-primary-lighter\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n</div>\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 });
|
|
1373
|
+
}
|
|
1374
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductCategoryBadgesComponent, decorators: [{
|
|
1375
|
+
type: Component,
|
|
1376
|
+
args: [{ selector: 'app-product-category-badges', standalone: true, imports: [NgIf, NgForOf], template: "<div *ngIf=\"product?.categories?.length > 0\" class=\"d-flex justify-content-start align-items-center gap-1\">\n <span class=\"badge bg-primary-lighter\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n</div>\n" }]
|
|
1377
|
+
}], propDecorators: { product: [{
|
|
1378
|
+
type: Input
|
|
1379
|
+
}] } });
|
|
1380
|
+
|
|
1381
|
+
class StockReceiptDeleteButtonComponent {
|
|
1382
|
+
matDialog;
|
|
1383
|
+
stockReceiptService;
|
|
1384
|
+
alertService;
|
|
1385
|
+
stockReceipt;
|
|
1386
|
+
deleted = new EventEmitter();
|
|
1387
|
+
isDeleting = false;
|
|
1388
|
+
constructor(matDialog, stockReceiptService, alertService) {
|
|
1389
|
+
this.matDialog = matDialog;
|
|
1390
|
+
this.stockReceiptService = stockReceiptService;
|
|
1391
|
+
this.alertService = alertService;
|
|
1392
|
+
}
|
|
1393
|
+
showDeleteConfirmModel(templateRef) {
|
|
1394
|
+
this.matDialog.open(templateRef, { width: '400px' });
|
|
1395
|
+
}
|
|
1396
|
+
delete() {
|
|
1397
|
+
this.isDeleting = true;
|
|
1398
|
+
this.stockReceiptService.delete(this.stockReceipt).subscribe({
|
|
1399
|
+
next: () => {
|
|
1400
|
+
this.matDialog.closeAll();
|
|
1401
|
+
this.isDeleting = false;
|
|
1402
|
+
this.deleted.emit();
|
|
1403
|
+
this.alertService.addAlert('Stock Receipt deleted successfully!', 'success');
|
|
1404
|
+
},
|
|
1405
|
+
error: () => {
|
|
1406
|
+
this.isDeleting = false;
|
|
1407
|
+
},
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
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 });
|
|
1411
|
+
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 class=\"material-symbols-outlined cursor-pointer\" (click)=\"showDeleteConfirmModel(deleteModelTemplate)\">\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 [disabled]=\"isDeleting\" mat-raised-button type=\"button\" color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" mat-flat-button mat-dialog-close type=\"button\">Cancel</button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i4$3.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 });
|
|
1412
|
+
}
|
|
1413
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptDeleteButtonComponent, decorators: [{
|
|
1414
|
+
type: Component,
|
|
1415
|
+
args: [{ selector: 'app-stock-receipt-delete-button', template: "<span class=\"material-symbols-outlined cursor-pointer\" (click)=\"showDeleteConfirmModel(deleteModelTemplate)\">\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 [disabled]=\"isDeleting\" mat-raised-button type=\"button\" color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" mat-flat-button mat-dialog-close type=\"button\">Cancel</button>\n </div>\n</ng-template>\n" }]
|
|
1416
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: StockReceiptService }, { type: i1.AlertService }], propDecorators: { stockReceipt: [{
|
|
1417
|
+
type: Input
|
|
1418
|
+
}], deleted: [{
|
|
1419
|
+
type: Output
|
|
1420
|
+
}] } });
|
|
1421
|
+
|
|
1422
|
+
let StockReceiptsListPageComponent = class StockReceiptsListPageComponent extends TechlifyListingControllerInterface {
|
|
1423
|
+
stockReceiptService;
|
|
1424
|
+
formBuilder;
|
|
1425
|
+
requestHelperService;
|
|
1426
|
+
activatedRoute;
|
|
1427
|
+
product;
|
|
1428
|
+
listUpdated = new EventEmitter();
|
|
1429
|
+
defaultSelectedColumns = [
|
|
1430
|
+
"no",
|
|
1431
|
+
"product",
|
|
1432
|
+
"sku",
|
|
1433
|
+
"date",
|
|
1434
|
+
"quantity",
|
|
1435
|
+
"location",
|
|
1436
|
+
"purchase_price",
|
|
1437
|
+
"amount",
|
|
1438
|
+
"supplier",
|
|
1439
|
+
"particulars",
|
|
1440
|
+
];
|
|
1441
|
+
columnConfig = [
|
|
1442
|
+
{ label: 'Creator', def: 'creator', isSelected: false, isEditable: true },
|
|
1443
|
+
];
|
|
1444
|
+
selectedColumns = this.columnConfig.filter(col => col.isSelected);
|
|
1445
|
+
get displayedColumns() {
|
|
1446
|
+
const selectedColumns = this.selectedColumns.map(col => col.def);
|
|
1447
|
+
return this.defaultSelectedColumns.concat(...selectedColumns, 'actions');
|
|
1448
|
+
}
|
|
1449
|
+
constructor(stockReceiptService, formBuilder, requestHelperService, activatedRoute) {
|
|
1450
|
+
super();
|
|
1451
|
+
this.stockReceiptService = stockReceiptService;
|
|
1452
|
+
this.formBuilder = formBuilder;
|
|
1453
|
+
this.requestHelperService = requestHelperService;
|
|
1454
|
+
this.activatedRoute = activatedRoute;
|
|
1455
|
+
this.lastPage = 0;
|
|
1456
|
+
this.filterForm = this.formBuilder.group({
|
|
1457
|
+
search: [''],
|
|
1458
|
+
product_ids: [''],
|
|
1459
|
+
category_ids: [''],
|
|
1460
|
+
duration: [''],
|
|
1461
|
+
date_from: [''],
|
|
1462
|
+
date_to: [''],
|
|
1463
|
+
supplier_ids: [''],
|
|
1464
|
+
measure_ids: [''],
|
|
1465
|
+
location_ids: [''],
|
|
1466
|
+
sort_by: ['date|desc'],
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
ngOnInit() {
|
|
1470
|
+
if (this.product) {
|
|
1471
|
+
this.filterForm.get('product_ids')?.setValue(this.product?.id);
|
|
1472
|
+
const index = this.displayedColumns.indexOf('product');
|
|
1473
|
+
if (index !== -1) {
|
|
1474
|
+
this.displayedColumns.splice(index, 1);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
this.updateFormWithQueryParams();
|
|
1478
|
+
this.subscribeToFormChanges();
|
|
1479
|
+
this.subscribeToRouteChanges();
|
|
1480
|
+
}
|
|
1481
|
+
loadData() {
|
|
1482
|
+
const params = {
|
|
1483
|
+
page: this.page,
|
|
1484
|
+
perPage: this.perPage,
|
|
1485
|
+
with: "creator,supplier,product.measure,product.categories,location",
|
|
1486
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1487
|
+
};
|
|
1488
|
+
this.isWorking = true;
|
|
1489
|
+
this.stockReceiptService.index(params).subscribe({
|
|
1490
|
+
next: (response) => {
|
|
1491
|
+
this.models = this.models.concat(response?.data);
|
|
1492
|
+
this.lastPage = response?.last_page;
|
|
1493
|
+
this.isWorking = false;
|
|
1494
|
+
},
|
|
1495
|
+
error: () => {
|
|
1496
|
+
this.isWorking = false;
|
|
1497
|
+
},
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
onSortChange(sort) {
|
|
1501
|
+
let { active, direction } = sort;
|
|
1502
|
+
if (!active) {
|
|
1503
|
+
active = 'date';
|
|
1504
|
+
}
|
|
1505
|
+
if (!direction) {
|
|
1506
|
+
direction = 'desc';
|
|
1507
|
+
active = 'date';
|
|
1508
|
+
}
|
|
1509
|
+
this.filterForm.get('sort_by').setValue(active + '|' + direction);
|
|
1510
|
+
}
|
|
1511
|
+
onDurationChange(timelineValue) {
|
|
1512
|
+
let { date_to, date_from } = timelineValue;
|
|
1513
|
+
this.filterForm.patchValue({
|
|
1514
|
+
date_from: date_from ? moment$1(date_from).format("YYYY-MM-DD") : "",
|
|
1515
|
+
date_to: date_to ? moment$1(date_to).format("YYYY-MM-DD") : "",
|
|
1516
|
+
}, { emitEvent: false });
|
|
1517
|
+
}
|
|
1518
|
+
updateFormWithQueryParams() {
|
|
1519
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
1520
|
+
product_ids: { multiple: true },
|
|
1521
|
+
measure_ids: { multiple: true },
|
|
1522
|
+
category_ids: { multiple: true },
|
|
1523
|
+
supplier_ids: { multiple: true },
|
|
1524
|
+
location_ids: { multiple: true },
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
subscribeToFormChanges() {
|
|
1528
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
1529
|
+
next: () => {
|
|
1530
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
1531
|
+
}
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
subscribeToRouteChanges() {
|
|
1535
|
+
this.activatedRoute.queryParams
|
|
1536
|
+
.pipe(debounceTime$1(500), distinctUntilChanged())
|
|
1537
|
+
.subscribe(() => {
|
|
1538
|
+
this.reload();
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
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 }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
|
|
1542
|
+
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 class=\"d-flex justify-content-between align-items-center gap-3\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Stock Receipts</h3>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <form [formGroup]=\"filterForm\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <app-timeline-filter\n appearance=\"fill\"\n labelText=\"Date\"\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>\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>\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location</mat-label>\n <app-searchable-selector\n apiUrl=\"api/inventory-locations\"\n formControlName=\"location_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>\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 <div class=\"d-flex flex-column gap-1\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n <app-product-category-badges [product]=\"element?.product\"></app-product-category-badges>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.product?.sku }}</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\">{{ element?.quantity }} {{ element?.product?.measure?.title }}</td>\n </ng-container>\n\n <!-- Location Column -->\n <ng-container matColumnDef=\"location\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Location</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/locations', element?.location_id, 'view']\"\n >\n {{ element?.location?.title }}\n </a>\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>Purchase Price</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: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { 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: "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: i5.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: i7.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: i14.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i14.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: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "component", type: i1.ColumnSelectorComponent, selector: "app-column-selector", inputs: ["label", "mode", "columnConfigs", "selectedColumns"], outputs: ["selectedColumnsChange", "displayedColumnsChange"] }, { 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 });
|
|
1543
|
+
};
|
|
1544
|
+
StockReceiptsListPageComponent = __decorate([
|
|
1545
|
+
UntilDestroy()
|
|
1546
|
+
], StockReceiptsListPageComponent);
|
|
1547
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsListPageComponent, decorators: [{
|
|
1548
|
+
type: Component,
|
|
1549
|
+
args: [{ selector: 'app-stock-receipts-list-page', template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-3\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Stock Receipts</h3>\n <app-column-selector\n mode=\"icon\"\n class=\"mb-2 d-print-none\"\n [columnConfigs]=\"columnConfig\"\n [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <form [formGroup]=\"filterForm\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <app-timeline-filter\n appearance=\"fill\"\n labelText=\"Date\"\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>\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>\n <mat-label>Measure</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-measures\"\n formControlName=\"measure_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location</mat-label>\n <app-searchable-selector\n apiUrl=\"api/inventory-locations\"\n formControlName=\"location_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>\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 <div class=\"d-flex flex-column gap-1\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n <app-product-category-badges [product]=\"element?.product\"></app-product-category-badges>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.product?.sku }}</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\">{{ element?.quantity }} {{ element?.product?.measure?.title }}</td>\n </ng-container>\n\n <!-- Location Column -->\n <ng-container matColumnDef=\"location\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Location</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/locations', element?.location_id, 'view']\"\n >\n {{ element?.location?.title }}\n </a>\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>Purchase Price</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" }]
|
|
1550
|
+
}], ctorParameters: () => [{ type: StockReceiptService }, { type: i2$2.FormBuilder }, { type: i1.RequestHelperService }, { type: i2.ActivatedRoute }], propDecorators: { product: [{
|
|
1551
|
+
type: Input
|
|
1552
|
+
}], listUpdated: [{
|
|
1553
|
+
type: Output
|
|
1554
|
+
}] } });
|
|
1555
|
+
|
|
1556
|
+
class StockIssuanceDeleteButtonComponent {
|
|
1557
|
+
matDialog;
|
|
1558
|
+
stockIssuanceService;
|
|
1559
|
+
alertService;
|
|
1560
|
+
stockIssuance;
|
|
1561
|
+
deleted = new EventEmitter();
|
|
1562
|
+
isDeleting = false;
|
|
1563
|
+
constructor(matDialog, stockIssuanceService, alertService) {
|
|
1564
|
+
this.matDialog = matDialog;
|
|
1565
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
1566
|
+
this.alertService = alertService;
|
|
1567
|
+
}
|
|
1568
|
+
showDeleteConfirmModel(templateRef) {
|
|
1569
|
+
this.matDialog.open(templateRef, { width: '400px' });
|
|
1570
|
+
}
|
|
1571
|
+
delete() {
|
|
1572
|
+
this.isDeleting = true;
|
|
1573
|
+
this.stockIssuanceService.delete(this.stockIssuance).subscribe({
|
|
1574
|
+
next: () => {
|
|
1575
|
+
this.matDialog.closeAll();
|
|
1576
|
+
this.isDeleting = false;
|
|
1577
|
+
this.deleted.emit();
|
|
1578
|
+
this.alertService.addAlert('Stock Issuance deleted successfully!', 'success');
|
|
1579
|
+
},
|
|
1580
|
+
error: () => {
|
|
1581
|
+
this.isDeleting = false;
|
|
1582
|
+
},
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
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 });
|
|
1586
|
+
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 class=\"material-symbols-outlined cursor-pointer\" (click)=\"showDeleteConfirmModel(deleteModelTemplate)\">\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 [disabled]=\"isDeleting\" mat-raised-button type=\"button\" color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" mat-flat-button mat-dialog-close type=\"button\">Cancel</button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i4$3.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 });
|
|
1587
|
+
}
|
|
1588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonComponent, decorators: [{
|
|
1589
|
+
type: Component,
|
|
1590
|
+
args: [{ selector: 'app-stock-issuance-delete-button', template: "<span class=\"material-symbols-outlined cursor-pointer\" (click)=\"showDeleteConfirmModel(deleteModelTemplate)\">\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 [disabled]=\"isDeleting\" mat-raised-button type=\"button\" color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" mat-flat-button mat-dialog-close type=\"button\">Cancel</button>\n </div>\n</ng-template>\n" }]
|
|
1591
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: StockIssuanceService }, { type: i1.AlertService }], propDecorators: { stockIssuance: [{
|
|
1592
|
+
type: Input
|
|
1593
|
+
}], deleted: [{
|
|
1594
|
+
type: Output
|
|
1595
|
+
}] } });
|
|
1596
|
+
|
|
1597
|
+
class StockIssuancesListComponent extends TechlifyListingControllerInterface {
|
|
1598
|
+
formBuilder;
|
|
1599
|
+
requestHelperService;
|
|
1600
|
+
stockIssuanceService;
|
|
1601
|
+
activatedRoute;
|
|
1602
|
+
product;
|
|
1603
|
+
issuableType;
|
|
1604
|
+
issuableId;
|
|
1605
|
+
label = 'Stock Issues';
|
|
1606
|
+
listUpdated = new EventEmitter();
|
|
1607
|
+
defaultSelectedColumns = [
|
|
1608
|
+
'no', 'product', 'sku', 'date', 'quantity', 'location', 'related', 'particulars',
|
|
1609
|
+
];
|
|
1610
|
+
columnConfig = [
|
|
1611
|
+
{ label: 'Creator', def: 'creator', isSelected: false, isEditable: true },
|
|
1612
|
+
];
|
|
1613
|
+
selectedColumns = this.columnConfig.filter(col => col.isSelected);
|
|
1614
|
+
get displayedColumns() {
|
|
1615
|
+
const selectedColumns = this.selectedColumns.map(col => col.def);
|
|
1616
|
+
return this.defaultSelectedColumns.concat(...selectedColumns, 'actions');
|
|
1617
|
+
}
|
|
1618
|
+
constructor(formBuilder, requestHelperService, stockIssuanceService, activatedRoute) {
|
|
1619
|
+
super();
|
|
1620
|
+
this.formBuilder = formBuilder;
|
|
1621
|
+
this.requestHelperService = requestHelperService;
|
|
1622
|
+
this.stockIssuanceService = stockIssuanceService;
|
|
1623
|
+
this.activatedRoute = activatedRoute;
|
|
1624
|
+
this.lastPage = 0;
|
|
1625
|
+
this.filterForm = this.formBuilder.group({
|
|
1626
|
+
duration: [''],
|
|
1627
|
+
date_from: [''],
|
|
1628
|
+
date_to: [''],
|
|
1629
|
+
measure_ids: [''],
|
|
1630
|
+
product_ids: [''],
|
|
1631
|
+
category_ids: [''],
|
|
1632
|
+
location_ids: [''],
|
|
1633
|
+
search: [''],
|
|
1634
|
+
sort_by: ['date|desc'],
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
ngOnInit() {
|
|
1638
|
+
if (this.product) {
|
|
1639
|
+
this.filterForm.get('product_ids')?.setValue(this.product?.id);
|
|
1640
|
+
const index = this.displayedColumns.indexOf('product');
|
|
1641
|
+
if (index !== -1) {
|
|
1642
|
+
this.displayedColumns.splice(index, 1);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
this.updateFormWithQueryParams();
|
|
1646
|
+
this.subscribeToFormChanges();
|
|
1647
|
+
this.subscribeToRouteChanges();
|
|
1648
|
+
}
|
|
1649
|
+
loadData() {
|
|
1650
|
+
const params = {
|
|
1651
|
+
page: this.page,
|
|
1652
|
+
perPage: this.perPage,
|
|
1653
|
+
with: 'creator,product.measure,issuable.fixedAsset,product.categories,location',
|
|
1654
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
1655
|
+
};
|
|
1656
|
+
if (this.issuableId && this.issuableType) {
|
|
1657
|
+
params.issuable_ids = this.issuableId;
|
|
1658
|
+
params.issuable_types = this.issuableType;
|
|
1659
|
+
}
|
|
1660
|
+
this.isWorking = true;
|
|
1661
|
+
this.stockIssuanceService.index(params).subscribe({
|
|
1662
|
+
next: (response) => {
|
|
1663
|
+
this.models = this.models.concat(response?.data);
|
|
1664
|
+
this.lastPage = response?.last_page;
|
|
1665
|
+
this.isWorking = false;
|
|
1666
|
+
},
|
|
1667
|
+
error: () => {
|
|
1668
|
+
this.isWorking = false;
|
|
1669
|
+
},
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
onSortChange(sort) {
|
|
1673
|
+
let { active, direction } = sort;
|
|
1674
|
+
if (!active) {
|
|
1675
|
+
active = 'date';
|
|
1676
|
+
}
|
|
1677
|
+
if (!direction) {
|
|
1678
|
+
direction = 'desc';
|
|
1679
|
+
active = 'date';
|
|
1680
|
+
}
|
|
1681
|
+
this.filterForm.get('sort_by').setValue(active + '|' + direction);
|
|
1682
|
+
}
|
|
1683
|
+
updateFormWithQueryParams() {
|
|
1684
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
1685
|
+
product_ids: { multiple: true },
|
|
1686
|
+
measure_ids: { multiple: true },
|
|
1687
|
+
category_ids: { multiple: true },
|
|
1688
|
+
supplier_ids: { multiple: true },
|
|
1689
|
+
location_ids: { multiple: true },
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
subscribeToFormChanges() {
|
|
1693
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
1694
|
+
next: () => {
|
|
1695
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
subscribeToRouteChanges() {
|
|
1700
|
+
this.activatedRoute.queryParams
|
|
1701
|
+
.pipe(debounceTime$1(500), distinctUntilChanged())
|
|
1702
|
+
.subscribe(() => {
|
|
1703
|
+
this.reload();
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
onDurationChange(timelineValue) {
|
|
1707
|
+
let { date_to, date_from } = timelineValue;
|
|
1708
|
+
this.filterForm.patchValue({
|
|
1709
|
+
date_from: date_from ? moment(date_from).format("YYYY-MM-DD") : "",
|
|
1710
|
+
date_to: date_to ? moment(date_to).format("YYYY-MM-DD") : "",
|
|
1711
|
+
}, { emitEvent: false });
|
|
1712
|
+
}
|
|
1713
|
+
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 }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
|
|
1714
|
+
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 class=\"d-flex justify-content-between align-items-center gap-3\">\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 class=\"mt-2\"\n ></app-stock-issue-form-button>\n\n <app-column-selector\n mode=\"icon\" class=\"mb-2 d-print-none\" [columnConfigs]=\"columnConfig\" [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <form [formGroup]=\"filterForm\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <app-timeline-filter\n appearance=\"fill\" labelText=\"Date\" formControlName=\"duration\" (selectionChange)=\"onDurationChange($event)\"\n [showClearButton]=\"true\" [dateFrom]=\"filterForm.value?.date_from\" [dateTo]=\"filterForm.value?.date_to\"\n ></app-timeline-filter>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location</mat-label>\n <app-searchable-selector\n apiUrl=\"api/inventory-locations\" formControlName=\"location_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n </form>\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 Issues</h3>\n\n <app-stock-issue-form-button\n class=\"mt-2\" [product]=\"product\" icon=\"add\" (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 [dataSource]=\"models\" class=\"w-100\" aria-describedby=\"Stock Issuances\"\n infiniteScroll [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (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 <div class=\"d-flex flex-column gap-1\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n <app-product-category-badges [product]=\"element?.product\"></app-product-category-badges>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.product?.sku }}</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 <!-- Location Column -->\n <ng-container matColumnDef=\"location\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Location</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/locations', element?.location_id, 'view']\"\n >\n {{ element?.location?.title }}\n </a>\n </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 class=\"text-dark\" *ngIf=\"element?.issuable\" [routerLink]=\"['/maintenances', element?.issuable_id, 'view']\">\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\">{{ element?.quantity }} {{ element?.product?.measure?.title }}</td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Purchase Price</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\" [stockIssuance]=\"element\" (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n <app-stock-issuance-delete-button\n [stockIssuance]=\"element\" (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: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.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: i14.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i14.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.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: i5.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { 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: "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: "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: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "component", type: i1.ColumnSelectorComponent, selector: "app-column-selector", inputs: ["label", "mode", "columnConfigs", "selectedColumns"], outputs: ["selectedColumnsChange", "displayedColumnsChange"] }, { kind: "pipe", type: i4.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i4.DatePipe, name: "date" }], preserveWhitespaces: true });
|
|
1715
|
+
}
|
|
1716
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListComponent, decorators: [{
|
|
1717
|
+
type: Component,
|
|
1718
|
+
args: [{ selector: 'app-stock-issuances-list', template: "<mat-card *ngIf=\"!product\" class=\"mb-2\">\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-3\">\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 class=\"mt-2\"\n ></app-stock-issue-form-button>\n\n <app-column-selector\n mode=\"icon\" class=\"mb-2 d-print-none\" [columnConfigs]=\"columnConfig\" [(selectedColumns)]=\"selectedColumns\"\n ></app-column-selector>\n </div>\n\n <form [formGroup]=\"filterForm\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <app-timeline-filter\n appearance=\"fill\" labelText=\"Date\" formControlName=\"duration\" (selectionChange)=\"onDurationChange($event)\"\n [showClearButton]=\"true\" [dateFrom]=\"filterForm.value?.date_from\" [dateTo]=\"filterForm.value?.date_to\"\n ></app-timeline-filter>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Measure</mat-label>\n <app-searchable-selector apiUrl=\"api/product-measures\" formControlName=\"measure_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location</mat-label>\n <app-searchable-selector\n apiUrl=\"api/inventory-locations\" formControlName=\"location_ids\" [multiple]=\"true\">\n </app-searchable-selector>\n </mat-form-field>\n </form>\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 Issues</h3>\n\n <app-stock-issue-form-button\n class=\"mt-2\" [product]=\"product\" icon=\"add\" (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 [dataSource]=\"models\" class=\"w-100\" aria-describedby=\"Stock Issuances\"\n infiniteScroll [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (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 <div class=\"d-flex flex-column gap-1\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/products', element?.product?.id, 'view']\"\n >\n {{ element?.product?.name }}\n </a>\n <app-product-category-badges [product]=\"element?.product\"></app-product-category-badges>\n </div>\n </td>\n </ng-container>\n\n <!-- SKU Column -->\n <ng-container matColumnDef=\"sku\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>SKU</th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.product?.sku }}</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 <!-- Location Column -->\n <ng-container matColumnDef=\"location\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Location</th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n class=\"text-decoration-none text-dark\"\n [routerLink]=\"['/inventory/locations', element?.location_id, 'view']\"\n >\n {{ element?.location?.title }}\n </a>\n </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 class=\"text-dark\" *ngIf=\"element?.issuable\" [routerLink]=\"['/maintenances', element?.issuable_id, 'view']\">\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\">{{ element?.quantity }} {{ element?.product?.measure?.title }}</td>\n </ng-container>\n\n <!-- Purchase Price Column -->\n <ng-container matColumnDef=\"purchase_price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>Purchase Price</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\" [stockIssuance]=\"element\" (saved)=\"reload(); listUpdated.emit()\"\n ></app-stock-issue-form-button>\n <app-stock-issuance-delete-button\n [stockIssuance]=\"element\" (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" }]
|
|
1719
|
+
}], ctorParameters: () => [{ type: i2$2.FormBuilder }, { type: i1.RequestHelperService }, { type: StockIssuanceService }, { type: i2.ActivatedRoute }], propDecorators: { product: [{
|
|
1720
|
+
type: Input
|
|
1721
|
+
}], issuableType: [{
|
|
1722
|
+
type: Input
|
|
1723
|
+
}], issuableId: [{
|
|
1724
|
+
type: Input
|
|
1725
|
+
}], label: [{
|
|
1726
|
+
type: Input
|
|
1727
|
+
}], listUpdated: [{
|
|
1728
|
+
type: Output
|
|
1729
|
+
}] } });
|
|
1730
|
+
|
|
1731
|
+
class ProductTaxService extends TechlifyServiceBaseClass {
|
|
1732
|
+
constructor(httpService) {
|
|
1733
|
+
super(httpService, 'product-taxes');
|
|
1734
|
+
}
|
|
1735
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1736
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, providedIn: 'root' });
|
|
1737
|
+
}
|
|
1738
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxService, decorators: [{
|
|
1739
|
+
type: Injectable,
|
|
1740
|
+
args: [{
|
|
1741
|
+
providedIn: 'root',
|
|
1742
|
+
}]
|
|
1743
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
1744
|
+
|
|
1745
|
+
class ProductTaxFormButtonComponent extends TechlifyFormComponentInterface {
|
|
1746
|
+
matDialog;
|
|
1747
|
+
productTaxService;
|
|
1748
|
+
formBuilder;
|
|
1749
|
+
alertService;
|
|
1750
|
+
product;
|
|
1751
|
+
saved = new EventEmitter();
|
|
1752
|
+
isSaving;
|
|
1753
|
+
constructor(matDialog, productTaxService, formValidatorService, formBuilder, alertService) {
|
|
1754
|
+
super(formValidatorService);
|
|
1755
|
+
this.matDialog = matDialog;
|
|
1756
|
+
this.productTaxService = productTaxService;
|
|
1757
|
+
this.formBuilder = formBuilder;
|
|
1758
|
+
this.alertService = alertService;
|
|
1759
|
+
this.errorMessages = {
|
|
1760
|
+
tax_id: {
|
|
1761
|
+
required: 'The tax field is required.',
|
|
1762
|
+
},
|
|
1763
|
+
};
|
|
1764
|
+
this.form = this.formBuilder.group({
|
|
1765
|
+
product_id: [''],
|
|
1766
|
+
tax_id: ['', Validators.required],
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
ngOnInit() {
|
|
1770
|
+
if (this.product) {
|
|
1771
|
+
this.form.get('product_id')?.setValue(this.product?.id);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
showForm(templateRef) {
|
|
1775
|
+
this.matDialog.open(templateRef, { width: '400px' });
|
|
1776
|
+
}
|
|
1777
|
+
save() {
|
|
1778
|
+
this.form.markAllAsTouched();
|
|
1779
|
+
if (this.form.invalid) {
|
|
1780
|
+
this.alertService.addAlert('Please check the form for errors.', 'error');
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
const data = { ...this.form.value };
|
|
1784
|
+
const params = {
|
|
1785
|
+
with: 'tax.type',
|
|
1786
|
+
};
|
|
1787
|
+
this.isSaving = true;
|
|
1788
|
+
this.productTaxService.store(data, params).subscribe({
|
|
1789
|
+
next: (response) => {
|
|
1790
|
+
this.isSaving = false;
|
|
1791
|
+
this.matDialog.closeAll();
|
|
1792
|
+
this.alertService.addAlert('Product tax saved successfully!', 'success');
|
|
1793
|
+
this.saved.emit(response?.item);
|
|
1794
|
+
},
|
|
1795
|
+
error: () => (this.isSaving = false),
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
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 });
|
|
1799
|
+
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 color=\"primary\" class=\"cursor-pointer\" (click)=\"showForm(formTemplate)\"> add </mat-icon>\n\n<ng-template #formTemplate>\n <form [formGroup]=\"form\" (submit)=\"save()\" mat-dialog-content class=\"d-flex flex-column gap-2\">\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 [disabled]=\"isSaving\" type=\"submit\" mat-raised-button color=\"primary\">Save</button>\n <button [disabled]=\"isSaving\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n </form>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$3.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: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i8.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 });
|
|
1800
|
+
}
|
|
1801
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxFormButtonComponent, decorators: [{
|
|
1802
|
+
type: Component,
|
|
1803
|
+
args: [{ selector: 'app-product-tax-form-button', template: "<mat-icon color=\"primary\" class=\"cursor-pointer\" (click)=\"showForm(formTemplate)\"> add </mat-icon>\n\n<ng-template #formTemplate>\n <form [formGroup]=\"form\" (submit)=\"save()\" mat-dialog-content class=\"d-flex flex-column gap-2\">\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 [disabled]=\"isSaving\" type=\"submit\" mat-raised-button color=\"primary\">Save</button>\n <button [disabled]=\"isSaving\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n </form>\n</ng-template>\n" }]
|
|
1804
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductTaxService }, { type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: i1.AlertService }], propDecorators: { product: [{
|
|
1805
|
+
type: Input
|
|
1806
|
+
}], saved: [{
|
|
1807
|
+
type: Output
|
|
1808
|
+
}] } });
|
|
1809
|
+
|
|
1810
|
+
class ProductTaxDeleteButtonComponent {
|
|
1811
|
+
matDialog;
|
|
1812
|
+
productTaxService;
|
|
1813
|
+
alertService;
|
|
1814
|
+
productTax;
|
|
1815
|
+
deleted = new EventEmitter();
|
|
1816
|
+
isDeleting;
|
|
1817
|
+
constructor(matDialog, productTaxService, alertService) {
|
|
1818
|
+
this.matDialog = matDialog;
|
|
1819
|
+
this.productTaxService = productTaxService;
|
|
1820
|
+
this.alertService = alertService;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* Delete the product.
|
|
1824
|
+
*/
|
|
1825
|
+
delete() {
|
|
1826
|
+
this.isDeleting = true;
|
|
1827
|
+
this.productTaxService.delete(this.productTax).subscribe({
|
|
1828
|
+
next: () => {
|
|
1829
|
+
this.matDialog?.closeAll();
|
|
1830
|
+
this.deleted.emit();
|
|
1831
|
+
this.isDeleting = false;
|
|
1832
|
+
this.alertService.addAlert('Product tax deleted successfully!', 'success');
|
|
1833
|
+
},
|
|
1834
|
+
error: () => (this.isDeleting = false),
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Show delete product dialog.
|
|
1839
|
+
*
|
|
1840
|
+
* @param templateRef
|
|
1841
|
+
*/
|
|
1842
|
+
showDeleteDialog(templateRef) {
|
|
1843
|
+
this.matDialog.open(templateRef, { width: '500px' });
|
|
1844
|
+
}
|
|
1845
|
+
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 });
|
|
1846
|
+
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 class=\"cursor-pointer text-secondary\" (click)=\"showDeleteDialog(deleteConfirmDialog)\"> delete </mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>Are you sure? You want to delete the product tax?</div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button [disabled]=\"isDeleting\" type=\"button\" mat-raised-button color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "component", type: i4$3.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: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
|
|
1847
|
+
}
|
|
1848
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxDeleteButtonComponent, decorators: [{
|
|
1849
|
+
type: Component,
|
|
1850
|
+
args: [{ selector: 'app-product-tax-delete-button', template: "<mat-icon class=\"cursor-pointer text-secondary\" (click)=\"showDeleteDialog(deleteConfirmDialog)\"> delete </mat-icon>\n\n<ng-template #deleteConfirmDialog>\n <h3 mat-dialog-title>Delete Product Tax</h3>\n <div mat-dialog-content>Are you sure? You want to delete the product tax?</div>\n <div mat-dialog-actions class=\"d-flex justify-content-end gap-1 mb-2\">\n <button [disabled]=\"isDeleting\" type=\"button\" mat-raised-button color=\"warn\" (click)=\"delete()\">Delete</button>\n <button [disabled]=\"isDeleting\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n</ng-template>\n" }]
|
|
1851
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductTaxService }, { type: i1.AlertService }], propDecorators: { productTax: [{
|
|
1852
|
+
type: Input
|
|
1853
|
+
}], deleted: [{
|
|
1854
|
+
type: Output
|
|
1855
|
+
}] } });
|
|
1856
|
+
|
|
1857
|
+
class ProductTaxListComponent extends TechlifyListingControllerInterface {
|
|
1858
|
+
product;
|
|
1859
|
+
displayedColumns = ['#', 'Tax', 'Actions'];
|
|
1860
|
+
ngOnInit() {
|
|
1861
|
+
this.loadData();
|
|
1862
|
+
}
|
|
1863
|
+
loadData() {
|
|
1864
|
+
this.models = this.product?.taxes ?? [];
|
|
1865
|
+
}
|
|
1866
|
+
onCreated(productTax) {
|
|
1867
|
+
this.models.unshift(productTax);
|
|
1868
|
+
this.models = [...this.models];
|
|
1869
|
+
}
|
|
1870
|
+
onDeleted(index) {
|
|
1871
|
+
this.models.splice(index, 1);
|
|
1872
|
+
this.models = [...this.models];
|
|
1873
|
+
}
|
|
1874
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1875
|
+
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 class=\"pb-3 d-flex justify-content-between align-items-center gap-3\">\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 [product]=\"product\" (saved)=\"onCreated($event)\"></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\">{{ element?.tax?.title }} ({{ element?.tax?.code }})</p>\n <small class=\"text-secondary\">{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small>\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: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.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: i5$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 });
|
|
1876
|
+
}
|
|
1877
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxListComponent, decorators: [{
|
|
1878
|
+
type: Component,
|
|
1879
|
+
args: [{ selector: 'app-product-tax-list', template: "<mat-card>\n <mat-card-content class=\"pb-3 d-flex justify-content-between align-items-center gap-3\">\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 [product]=\"product\" (saved)=\"onCreated($event)\"></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\">{{ element?.tax?.title }} ({{ element?.tax?.code }})</p>\n <small class=\"text-secondary\">{{ element?.tax?.value }} - {{ element?.tax?.type?.title }}</small>\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" }]
|
|
1880
|
+
}], propDecorators: { product: [{
|
|
1881
|
+
type: Input
|
|
1882
|
+
}] } });
|
|
1883
|
+
|
|
1884
|
+
class StockTransferService extends TechlifyServiceBaseClass {
|
|
1885
|
+
constructor(httpService) {
|
|
1886
|
+
super(httpService, 'stock-transfers');
|
|
1887
|
+
}
|
|
1888
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1889
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferService, providedIn: 'root' });
|
|
1890
|
+
}
|
|
1891
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferService, decorators: [{
|
|
1892
|
+
type: Injectable,
|
|
1893
|
+
args: [{
|
|
1894
|
+
providedIn: 'root'
|
|
1895
|
+
}]
|
|
1896
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
1897
|
+
|
|
1898
|
+
class StockTransferFormComponent extends TechlifyFormComponentInterface {
|
|
1899
|
+
formBuilder;
|
|
1900
|
+
alertService;
|
|
1901
|
+
service;
|
|
1902
|
+
productId;
|
|
1903
|
+
saved = new EventEmitter();
|
|
1904
|
+
cancelled = new EventEmitter();
|
|
1905
|
+
isWorking = false;
|
|
1906
|
+
constructor(formValidatorService, formBuilder, alertService, service) {
|
|
1907
|
+
super(formValidatorService);
|
|
1908
|
+
this.formBuilder = formBuilder;
|
|
1909
|
+
this.alertService = alertService;
|
|
1910
|
+
this.service = service;
|
|
1911
|
+
this.errorMessages = {
|
|
1912
|
+
date: {
|
|
1913
|
+
required: 'The date field is required.',
|
|
1914
|
+
},
|
|
1915
|
+
location_from_id: {
|
|
1916
|
+
required: 'The location from field is required.',
|
|
1917
|
+
},
|
|
1918
|
+
location_to_id: {
|
|
1919
|
+
required: 'The location to field is required.',
|
|
1920
|
+
},
|
|
1921
|
+
quantity: {
|
|
1922
|
+
required: 'The quantity field is required.',
|
|
1923
|
+
}
|
|
1924
|
+
};
|
|
1925
|
+
this.form = this.formBuilder.group({
|
|
1926
|
+
product_id: [''],
|
|
1927
|
+
date: [new Date(), [Validators.required]],
|
|
1928
|
+
location_from_id: ['', Validators.required],
|
|
1929
|
+
location_to_id: ['', Validators.required],
|
|
1930
|
+
quantity: [1, Validators.required],
|
|
1931
|
+
particulars: ['']
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
save() {
|
|
1935
|
+
this.form.markAsTouched();
|
|
1936
|
+
if (this.form.invalid) {
|
|
1937
|
+
console.log(this.form);
|
|
1938
|
+
this.alertService.addAlert('Please check the form for errors.', 'error');
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
const data = {
|
|
1942
|
+
...this.form.value
|
|
1943
|
+
};
|
|
1944
|
+
if (data?.date) {
|
|
1945
|
+
data.date = moment$1(data?.date).format('YYYY-MM-DD');
|
|
1946
|
+
}
|
|
1947
|
+
this.isWorking = true;
|
|
1948
|
+
this.service.store(data).subscribe({
|
|
1949
|
+
next: (response) => {
|
|
1950
|
+
this.alertService.addAlert('Stock transferred successfully.', 'success');
|
|
1951
|
+
this.saved.emit(response?.item);
|
|
1952
|
+
this.isWorking = false;
|
|
1953
|
+
},
|
|
1954
|
+
error: () => (this.isWorking = false),
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
ngOnInit() {
|
|
1958
|
+
if (this.productId) {
|
|
1959
|
+
this.form.get('product_id')?.setValue(this.productId);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferFormComponent, deps: [{ token: i1.FormValidatorService }, { token: i2$2.FormBuilder }, { token: i1.AlertService }, { token: StockTransferService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1963
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockTransferFormComponent, isStandalone: true, selector: "app-stock-transfer-form", inputs: { productId: "productId" }, outputs: { saved: "saved", cancelled: "cancelled" }, usesInheritance: true, ngImport: i0, template: "<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column justify-content-start gap-0\"\n (ngSubmit)=\"save()\"\n>\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input formControlName=\"date\" matInput [matDatepicker]=\"picker\" placeholder=\"Date\" (focus)=\"picker.open()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">{{ getErrorMessage('date') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location From</mat-label>\n <app-searchable-selector\n formControlName=\"location_from_id\"\n apiUrl=\"api/inventory-locations\"\n ></app-searchable-selector>\n <mat-hint>Where are we taking stock from?</mat-hint>\n <mat-error *ngIf=\"isFieldValid('location_from_id')\">{{ getErrorMessage('location_from_id') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location To</mat-label>\n <app-searchable-selector\n formControlName=\"location_to_id\"\n apiUrl=\"api/inventory-locations\"\n ></app-searchable-selector>\n <mat-hint>Where are we taking stock to?</mat-hint>\n <mat-error *ngIf=\"isFieldValid('location_to_id')\">{{ getErrorMessage('location_to_id') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput placeholder=\"Quantity\" formControlName=\"quantity\" type=\"number\">\n <mat-error *ngIf=\"isFieldValid('quantity')\">{{ getErrorMessage('quantity') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput placeholder=\"Particulars\" formControlName=\"particulars\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button [disabled]=\"isWorking\" type=\"submit\" mat-raised-button color=\"primary\">\n Save\n </button>\n <button [disabled]=\"isWorking\" type=\"button\" mat-flat-button (click)=\"cancelled.emit()\">\n Cancel\n </button>\n </div>\n</form>\n", styles: [""], dependencies: [{ 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.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.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: 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: "directive", type: MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], preserveWhitespaces: true });
|
|
1964
|
+
}
|
|
1965
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferFormComponent, decorators: [{
|
|
1966
|
+
type: Component,
|
|
1967
|
+
args: [{ selector: 'app-stock-transfer-form', standalone: true, imports: [
|
|
1968
|
+
ReactiveFormsModule,
|
|
1969
|
+
MatFormField,
|
|
1970
|
+
MatLabel,
|
|
1971
|
+
MatInput,
|
|
1972
|
+
MatDatepickerInput,
|
|
1973
|
+
MatDatepickerToggle,
|
|
1974
|
+
MatDatepicker,
|
|
1975
|
+
MatSuffix,
|
|
1976
|
+
SearchableSelectorModule,
|
|
1977
|
+
MatError,
|
|
1978
|
+
NgIf,
|
|
1979
|
+
MatHint,
|
|
1980
|
+
MatButton
|
|
1981
|
+
], template: "<form\n [formGroup]=\"form\"\n class=\"d-flex flex-column justify-content-start gap-0\"\n (ngSubmit)=\"save()\"\n>\n <mat-form-field>\n <mat-label>Date</mat-label>\n <input formControlName=\"date\" matInput [matDatepicker]=\"picker\" placeholder=\"Date\" (focus)=\"picker.open()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error *ngIf=\"isFieldValid('date')\">{{ getErrorMessage('date') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location From</mat-label>\n <app-searchable-selector\n formControlName=\"location_from_id\"\n apiUrl=\"api/inventory-locations\"\n ></app-searchable-selector>\n <mat-hint>Where are we taking stock from?</mat-hint>\n <mat-error *ngIf=\"isFieldValid('location_from_id')\">{{ getErrorMessage('location_from_id') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Location To</mat-label>\n <app-searchable-selector\n formControlName=\"location_to_id\"\n apiUrl=\"api/inventory-locations\"\n ></app-searchable-selector>\n <mat-hint>Where are we taking stock to?</mat-hint>\n <mat-error *ngIf=\"isFieldValid('location_to_id')\">{{ getErrorMessage('location_to_id') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Quantity</mat-label>\n <input matInput placeholder=\"Quantity\" formControlName=\"quantity\" type=\"number\">\n <mat-error *ngIf=\"isFieldValid('quantity')\">{{ getErrorMessage('quantity') }}</mat-error>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Particulars</mat-label>\n <textarea matInput placeholder=\"Particulars\" formControlName=\"particulars\"></textarea>\n </mat-form-field>\n\n <div class=\"d-flex justify-content-end align-items-center gap-2\">\n <button [disabled]=\"isWorking\" type=\"submit\" mat-raised-button color=\"primary\">\n Save\n </button>\n <button [disabled]=\"isWorking\" type=\"button\" mat-flat-button (click)=\"cancelled.emit()\">\n Cancel\n </button>\n </div>\n</form>\n" }]
|
|
1982
|
+
}], ctorParameters: () => [{ type: i1.FormValidatorService }, { type: i2$2.FormBuilder }, { type: i1.AlertService }, { type: StockTransferService }], propDecorators: { productId: [{
|
|
1983
|
+
type: Input
|
|
1984
|
+
}], saved: [{
|
|
1985
|
+
type: Output
|
|
1986
|
+
}], cancelled: [{
|
|
1987
|
+
type: Output
|
|
1988
|
+
}] } });
|
|
1989
|
+
|
|
1990
|
+
class StockTransferFormButtonComponent {
|
|
1991
|
+
matDialog;
|
|
1992
|
+
productId;
|
|
1993
|
+
saved = new EventEmitter();
|
|
1994
|
+
matDialogRef;
|
|
1995
|
+
constructor(matDialog) {
|
|
1996
|
+
this.matDialog = matDialog;
|
|
1997
|
+
}
|
|
1998
|
+
showForm(templateRef) {
|
|
1999
|
+
this.matDialogRef = this.matDialog.open(templateRef, { width: '500px' });
|
|
2000
|
+
}
|
|
2001
|
+
onSaved(model) {
|
|
2002
|
+
this.saved.emit(model);
|
|
2003
|
+
this.matDialogRef.close();
|
|
2004
|
+
}
|
|
2005
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferFormButtonComponent, deps: [{ token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
2006
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockTransferFormButtonComponent, isStandalone: true, selector: "app-stock-transfer-form-button", inputs: { productId: "productId" }, outputs: { saved: "saved" }, ngImport: i0, template: "<span\n class=\"material-symbols-outlined text-secondary cursor-pointer\"\n matTooltip=\"Stock Transfer\"\n (click)=\"showForm(formTemplate)\"\n>\n move_up\n</span>\n\n<ng-template #formTemplate>\n <h3 mat-dialog-title>Stock Transfer</h3>\n <app-stock-transfer-form\n mat-dialog-content\n [productId]=\"productId\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onSaved($event)\"\n ></app-stock-transfer-form>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: StockTransferFormComponent, selector: "app-stock-transfer-form", inputs: ["productId"], outputs: ["saved", "cancelled"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }], preserveWhitespaces: true });
|
|
2007
|
+
}
|
|
2008
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferFormButtonComponent, decorators: [{
|
|
2009
|
+
type: Component,
|
|
2010
|
+
args: [{ selector: 'app-stock-transfer-form-button', standalone: true, imports: [
|
|
2011
|
+
MatTooltip,
|
|
2012
|
+
StockTransferFormComponent,
|
|
2013
|
+
MatDialogTitle,
|
|
2014
|
+
MatDialogContent
|
|
2015
|
+
], template: "<span\n class=\"material-symbols-outlined text-secondary cursor-pointer\"\n matTooltip=\"Stock Transfer\"\n (click)=\"showForm(formTemplate)\"\n>\n move_up\n</span>\n\n<ng-template #formTemplate>\n <h3 mat-dialog-title>Stock Transfer</h3>\n <app-stock-transfer-form\n mat-dialog-content\n [productId]=\"productId\"\n (cancelled)=\"matDialogRef.close()\"\n (saved)=\"onSaved($event)\"\n ></app-stock-transfer-form>\n</ng-template>\n" }]
|
|
2016
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }], propDecorators: { productId: [{
|
|
2017
|
+
type: Input
|
|
2018
|
+
}], saved: [{
|
|
2019
|
+
type: Output
|
|
2020
|
+
}] } });
|
|
2021
|
+
|
|
2022
|
+
/*
|
|
2023
|
+
* This module imports and re-exports all Angular Material modules for convenience,
|
|
2024
|
+
* so only 1 module import is needed in your feature modules.
|
|
2025
|
+
* See https://material.angular.io/guide/getting-started#step-3-import-the-component-modules.
|
|
2026
|
+
*
|
|
2027
|
+
* To optimize your production builds, you should only import the components used in your app.
|
|
2028
|
+
*/
|
|
2029
|
+
class MaterialModule {
|
|
2030
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2031
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: MaterialModule, exports: [MatAutocompleteModule,
|
|
2032
|
+
MatBadgeModule,
|
|
2033
|
+
MatButtonModule,
|
|
2034
|
+
MatButtonToggleModule,
|
|
2035
|
+
MatCardModule,
|
|
2036
|
+
MatCheckboxModule,
|
|
2037
|
+
MatChipsModule,
|
|
2038
|
+
MatCommonModule,
|
|
2039
|
+
MatDatepickerModule,
|
|
2040
|
+
MatDialogModule,
|
|
2041
|
+
MatDividerModule,
|
|
2042
|
+
MatExpansionModule,
|
|
2043
|
+
MatFormFieldModule,
|
|
2044
|
+
MatGridListModule,
|
|
2045
|
+
MatIconModule,
|
|
2046
|
+
MatInputModule,
|
|
2047
|
+
MatLineModule,
|
|
2048
|
+
MatListModule,
|
|
2049
|
+
MatMenuModule,
|
|
2050
|
+
MatNativeDateModule,
|
|
2051
|
+
MatOptionModule,
|
|
2052
|
+
MatPaginatorModule,
|
|
2053
|
+
MatProgressBarModule,
|
|
2054
|
+
MatProgressSpinnerModule,
|
|
2055
|
+
MatPseudoCheckboxModule,
|
|
2056
|
+
MatRadioModule,
|
|
2057
|
+
MatRippleModule,
|
|
2058
|
+
MatSelectModule,
|
|
2059
|
+
MatSidenavModule,
|
|
2060
|
+
MatSlideToggleModule,
|
|
2061
|
+
MatSliderModule,
|
|
2062
|
+
MatSnackBarModule,
|
|
2063
|
+
MatSortModule,
|
|
2064
|
+
MatStepperModule,
|
|
2065
|
+
MatTableModule,
|
|
2066
|
+
MatTabsModule,
|
|
2067
|
+
MatToolbarModule,
|
|
2068
|
+
MatTooltipModule,
|
|
2069
|
+
MatTreeModule] });
|
|
2070
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MaterialModule, imports: [MatAutocompleteModule,
|
|
2071
|
+
MatBadgeModule,
|
|
2072
|
+
MatButtonModule,
|
|
2073
|
+
MatButtonToggleModule,
|
|
2074
|
+
MatCardModule,
|
|
2075
|
+
MatCheckboxModule,
|
|
2076
|
+
MatChipsModule,
|
|
2077
|
+
MatCommonModule,
|
|
2078
|
+
MatDatepickerModule,
|
|
2079
|
+
MatDialogModule,
|
|
2080
|
+
MatDividerModule,
|
|
2081
|
+
MatExpansionModule,
|
|
2082
|
+
MatFormFieldModule,
|
|
2083
|
+
MatGridListModule,
|
|
2084
|
+
MatIconModule,
|
|
2085
|
+
MatInputModule,
|
|
2086
|
+
MatLineModule,
|
|
2087
|
+
MatListModule,
|
|
2088
|
+
MatMenuModule,
|
|
2089
|
+
MatNativeDateModule,
|
|
2090
|
+
MatOptionModule,
|
|
2091
|
+
MatPaginatorModule,
|
|
2092
|
+
MatProgressBarModule,
|
|
2093
|
+
MatProgressSpinnerModule,
|
|
2094
|
+
MatPseudoCheckboxModule,
|
|
2095
|
+
MatRadioModule,
|
|
2096
|
+
MatRippleModule,
|
|
2097
|
+
MatSelectModule,
|
|
2098
|
+
MatSidenavModule,
|
|
2099
|
+
MatSlideToggleModule,
|
|
2100
|
+
MatSliderModule,
|
|
2101
|
+
MatSnackBarModule,
|
|
2102
|
+
MatSortModule,
|
|
2103
|
+
MatStepperModule,
|
|
2104
|
+
MatTableModule,
|
|
2105
|
+
MatTabsModule,
|
|
2106
|
+
MatToolbarModule,
|
|
2107
|
+
MatTooltipModule,
|
|
2108
|
+
MatTreeModule] });
|
|
2109
|
+
}
|
|
2110
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MaterialModule, decorators: [{
|
|
2111
|
+
type: NgModule,
|
|
2112
|
+
args: [{
|
|
2113
|
+
exports: [
|
|
2114
|
+
MatAutocompleteModule,
|
|
2115
|
+
MatBadgeModule,
|
|
2116
|
+
MatButtonModule,
|
|
2117
|
+
MatButtonToggleModule,
|
|
2118
|
+
MatCardModule,
|
|
2119
|
+
MatCheckboxModule,
|
|
2120
|
+
MatChipsModule,
|
|
2121
|
+
MatCommonModule,
|
|
2122
|
+
MatDatepickerModule,
|
|
2123
|
+
MatDialogModule,
|
|
2124
|
+
MatDividerModule,
|
|
2125
|
+
MatExpansionModule,
|
|
2126
|
+
MatFormFieldModule,
|
|
2127
|
+
MatGridListModule,
|
|
2128
|
+
MatIconModule,
|
|
2129
|
+
MatInputModule,
|
|
2130
|
+
MatLineModule,
|
|
2131
|
+
MatListModule,
|
|
2132
|
+
MatMenuModule,
|
|
2133
|
+
MatNativeDateModule,
|
|
2134
|
+
MatOptionModule,
|
|
2135
|
+
MatPaginatorModule,
|
|
2136
|
+
MatProgressBarModule,
|
|
2137
|
+
MatProgressSpinnerModule,
|
|
2138
|
+
MatPseudoCheckboxModule,
|
|
2139
|
+
MatRadioModule,
|
|
2140
|
+
MatRippleModule,
|
|
2141
|
+
MatSelectModule,
|
|
2142
|
+
MatSidenavModule,
|
|
2143
|
+
MatSlideToggleModule,
|
|
2144
|
+
MatSliderModule,
|
|
2145
|
+
MatSnackBarModule,
|
|
2146
|
+
MatSortModule,
|
|
2147
|
+
MatStepperModule,
|
|
2148
|
+
MatTableModule,
|
|
2149
|
+
MatTabsModule,
|
|
2150
|
+
MatToolbarModule,
|
|
2151
|
+
MatTooltipModule,
|
|
2152
|
+
MatTreeModule,
|
|
2153
|
+
],
|
|
2154
|
+
}]
|
|
2155
|
+
}] });
|
|
2156
|
+
|
|
2157
|
+
class ProductStatisticsService extends TechlifyServiceBaseClass {
|
|
2158
|
+
http;
|
|
2159
|
+
constructor(http) {
|
|
2160
|
+
super(http, 'product-statistics');
|
|
2161
|
+
this.http = http;
|
|
2162
|
+
}
|
|
2163
|
+
stockByLocation(params) {
|
|
2164
|
+
return this.http.get('api/product-statistics/stock-by-location', { params });
|
|
2165
|
+
}
|
|
2166
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductStatisticsService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2167
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductStatisticsService, providedIn: 'root' });
|
|
2168
|
+
}
|
|
2169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductStatisticsService, decorators: [{
|
|
2170
|
+
type: Injectable,
|
|
2171
|
+
args: [{
|
|
2172
|
+
providedIn: 'root'
|
|
2173
|
+
}]
|
|
2174
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
2175
|
+
|
|
2176
|
+
class ProductLocationListComponent extends TechlifyListingControllerInterface {
|
|
2177
|
+
statisticsService;
|
|
2178
|
+
errorHandler;
|
|
2179
|
+
product;
|
|
2180
|
+
constructor(statisticsService, errorHandler) {
|
|
2181
|
+
super();
|
|
2182
|
+
this.statisticsService = statisticsService;
|
|
2183
|
+
this.errorHandler = errorHandler;
|
|
2184
|
+
}
|
|
2185
|
+
displayedColumns = [
|
|
2186
|
+
'#',
|
|
2187
|
+
'Location',
|
|
2188
|
+
'Stock',
|
|
2189
|
+
'Actions'
|
|
2190
|
+
];
|
|
2191
|
+
ngOnInit() {
|
|
2192
|
+
this.loadData();
|
|
2193
|
+
}
|
|
2194
|
+
loadData() {
|
|
2195
|
+
this.statisticsService.stockByLocation({
|
|
2196
|
+
product_id: this.product.id
|
|
2197
|
+
}).subscribe({
|
|
2198
|
+
next: (response) => {
|
|
2199
|
+
this.models = response?.data;
|
|
2200
|
+
this.lastPage = response?.last_page;
|
|
2201
|
+
}, error: (error) => {
|
|
2202
|
+
this.errorHandler.handleError(error);
|
|
2203
|
+
}
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductLocationListComponent, deps: [{ token: ProductStatisticsService }, { token: i1.ErrorHandlerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2207
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ProductLocationListComponent, isStandalone: true, selector: "app-product-location-list", inputs: { product: "product" }, usesInheritance: true, ngImport: i0, template: "<mat-card>\n <mat-card-content class=\"pb-3 d-flex justify-content-between align-items-center gap-3\">\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> location_on </span>\n <strong class=\"mb-0 text-dark\">Product Locations</strong>\n </div>\n\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\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=\"Location\">\n <th mat-header-cell *matHeaderCellDef> Location </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.title }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\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-stock-transfer-form-button *ngIf=\"element?.id\" [productId]=\"product?.id\"\n (saved)=\"reload()\"></app-stock-transfer-form-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\n </mat-card-content>\n</mat-card>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MaterialModule }, { 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: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: StockTransferFormButtonComponent, selector: "app-stock-transfer-form-button", inputs: ["productId"], outputs: ["saved"] }], preserveWhitespaces: true });
|
|
2208
|
+
}
|
|
2209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductLocationListComponent, decorators: [{
|
|
2210
|
+
type: Component,
|
|
2211
|
+
args: [{ selector: 'app-product-location-list', standalone: true, imports: [
|
|
2212
|
+
CommonModule,
|
|
2213
|
+
MaterialModule,
|
|
2214
|
+
StockTransferFormButtonComponent
|
|
2215
|
+
], template: "<mat-card>\n <mat-card-content class=\"pb-3 d-flex justify-content-between align-items-center gap-3\">\n <div class=\"d-flex justify-content-start gap-2\">\n <span class=\"material-symbols-outlined\"> location_on </span>\n <strong class=\"mb-0 text-dark\">Product Locations</strong>\n </div>\n\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\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=\"Location\">\n <th mat-header-cell *matHeaderCellDef> Location </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.title }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\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-stock-transfer-form-button *ngIf=\"element?.id\" [productId]=\"product?.id\"\n (saved)=\"reload()\"></app-stock-transfer-form-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\n </mat-card-content>\n</mat-card>" }]
|
|
2216
|
+
}], ctorParameters: () => [{ type: ProductStatisticsService }, { type: i1.ErrorHandlerService }], propDecorators: { product: [{
|
|
2217
|
+
type: Input
|
|
2218
|
+
}] } });
|
|
2219
|
+
|
|
2220
|
+
class StockTransferListComponent extends TechlifyListingControllerInterface {
|
|
2221
|
+
service;
|
|
2222
|
+
fb;
|
|
2223
|
+
errorHandler;
|
|
2224
|
+
productId;
|
|
2225
|
+
displayedColumns = [
|
|
2226
|
+
'#',
|
|
2227
|
+
'date',
|
|
2228
|
+
'quantity',
|
|
2229
|
+
'location_from',
|
|
2230
|
+
'location_to',
|
|
2231
|
+
'creator'
|
|
2232
|
+
];
|
|
2233
|
+
constructor(service, fb, errorHandler) {
|
|
2234
|
+
super();
|
|
2235
|
+
this.service = service;
|
|
2236
|
+
this.fb = fb;
|
|
2237
|
+
this.errorHandler = errorHandler;
|
|
2238
|
+
this.filterForm = this.fb.group({
|
|
2239
|
+
product_id: ['']
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
ngOnInit() {
|
|
2243
|
+
if (this.productId) {
|
|
2244
|
+
this.filterForm.patchValue({
|
|
2245
|
+
product_id: this.productId
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
this.listenForChanges();
|
|
2249
|
+
this.loadData();
|
|
2250
|
+
}
|
|
2251
|
+
loadData() {
|
|
2252
|
+
this.isWorking = true;
|
|
2253
|
+
let filters = this.filterForm.value;
|
|
2254
|
+
filters.page = this.page;
|
|
2255
|
+
filters.per_page = this.productId
|
|
2256
|
+
? 9999
|
|
2257
|
+
: this.perPage;
|
|
2258
|
+
this.service.index(filters).subscribe({
|
|
2259
|
+
next: (response) => {
|
|
2260
|
+
this.models = this.models.concat(response?.data);
|
|
2261
|
+
this.lastPage = response?.last_page;
|
|
2262
|
+
this.isWorking = false;
|
|
2263
|
+
},
|
|
2264
|
+
error: (error) => {
|
|
2265
|
+
this.errorHandler.handleError(error);
|
|
2266
|
+
this.isWorking = false;
|
|
2267
|
+
},
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferListComponent, deps: [{ token: StockTransferService }, { token: i2$2.FormBuilder }, { token: i1.ErrorHandlerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2271
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StockTransferListComponent, isStandalone: true, selector: "app-stock-transfer-list", inputs: { productId: "productId" }, usesInheritance: true, ngImport: i0, template: "<mat-card>\n <mat-card-content 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 Transfers</h3>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\" aria-describedby=\"Stock Transfers\" infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\n\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=\"date\">\n <th mat-header-cell *matHeaderCellDef>Date</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column\">\n <span>{{ element?.date | date }}</span>\n <span>{{ element?.particulars }}</span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"location_from\">\n <th mat-header-cell *matHeaderCellDef>From</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.location_from?.title }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"location_to\">\n <th mat-header-cell *matHeaderCellDef>To</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.location_to?.title }}\n </td>\n </ng-container>\n\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 <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>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }, { kind: "ngmodule", type: MaterialModule }, { 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: i5.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i15.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i15.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i15.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i15.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i15.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i15.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i15.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i15.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i15.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i15.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { 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"] }], preserveWhitespaces: true });
|
|
2272
|
+
}
|
|
2273
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockTransferListComponent, decorators: [{
|
|
2274
|
+
type: Component,
|
|
2275
|
+
args: [{ selector: 'app-stock-transfer-list', standalone: true, imports: [
|
|
2276
|
+
CommonModule,
|
|
2277
|
+
MaterialModule,
|
|
2278
|
+
InfiniteScrollDirective
|
|
2279
|
+
], template: "<mat-card>\n <mat-card-content 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 Transfers</h3>\n </div>\n </mat-card-content>\n <mat-card-content class=\"p-0\">\n <table mat-table [dataSource]=\"models\" class=\"w-100\" aria-describedby=\"Stock Transfers\" infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\n\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=\"date\">\n <th mat-header-cell *matHeaderCellDef>Date</th>\n <td mat-cell *matCellDef=\"let element\">\n <div class=\"d-flex flex-column\">\n <span>{{ element?.date | date }}</span>\n <span>{{ element?.particulars }}</span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"quantity\">\n <th mat-header-cell *matHeaderCellDef>Quantity</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.quantity }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"location_from\">\n <th mat-header-cell *matHeaderCellDef>From</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.location_from?.title }}\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"location_to\">\n <th mat-header-cell *matHeaderCellDef>To</th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.location_to?.title }}\n </td>\n </ng-container>\n\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 <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>" }]
|
|
2280
|
+
}], ctorParameters: () => [{ type: StockTransferService }, { type: i2$2.FormBuilder }, { type: i1.ErrorHandlerService }], propDecorators: { productId: [{
|
|
2281
|
+
type: Input
|
|
2282
|
+
}] } });
|
|
2283
|
+
|
|
2284
|
+
class StockSummaryService {
|
|
2285
|
+
httpService;
|
|
2286
|
+
constructor(httpService) {
|
|
2287
|
+
this.httpService = httpService;
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Get the stocks summary.
|
|
2291
|
+
*
|
|
2292
|
+
* @param params
|
|
2293
|
+
*/
|
|
2294
|
+
summary(params) {
|
|
2295
|
+
return this.httpService.get('api/stocks-summary', { params });
|
|
2296
|
+
}
|
|
2297
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2298
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, providedIn: 'root' });
|
|
2299
|
+
}
|
|
2300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockSummaryService, decorators: [{
|
|
2301
|
+
type: Injectable,
|
|
2302
|
+
args: [{
|
|
2303
|
+
providedIn: 'root',
|
|
2304
|
+
}]
|
|
2305
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
2306
|
+
|
|
2307
|
+
class ProductDeleteButtonComponent {
|
|
2308
|
+
matDialog;
|
|
2309
|
+
productService;
|
|
2310
|
+
alertService;
|
|
2311
|
+
product;
|
|
2312
|
+
deleted = new EventEmitter();
|
|
2313
|
+
isDeleting;
|
|
2314
|
+
constructor(matDialog, productService, alertService) {
|
|
2315
|
+
this.matDialog = matDialog;
|
|
2316
|
+
this.productService = productService;
|
|
2317
|
+
this.alertService = alertService;
|
|
2318
|
+
}
|
|
2319
|
+
/**
|
|
2320
|
+
* Delete the product.
|
|
2321
|
+
*/
|
|
2322
|
+
deleteProduct() {
|
|
2323
|
+
this.isDeleting = true;
|
|
2324
|
+
this.productService.delete(this.product).subscribe({
|
|
2325
|
+
next: () => {
|
|
2326
|
+
this.deleted.emit();
|
|
2327
|
+
this.isDeleting = false;
|
|
2328
|
+
this.matDialog.closeAll();
|
|
2329
|
+
this.alertService.addAlert('Product deleted successfully!', 'success');
|
|
2330
|
+
},
|
|
2331
|
+
error: () => (this.isDeleting = false),
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* Show delete product dialog.
|
|
2336
|
+
*
|
|
2337
|
+
* @param templateRef
|
|
2338
|
+
*/
|
|
2339
|
+
showDeleteDialog(templateRef) {
|
|
2340
|
+
this.matDialog.open(templateRef, { width: '500px' });
|
|
2341
|
+
}
|
|
2342
|
+
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 });
|
|
2343
|
+
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 class=\"cursor-pointer text-secondary\" (click)=\"showDeleteDialog(deleteProductDialog)\"> delete </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 [disabled]=\"isDeleting\" type=\"button\" mat-raised-button color=\"warn\" (click)=\"deleteProduct()\">\n Delete\n </button>\n <button [disabled]=\"isDeleting\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: i4$3.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: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], preserveWhitespaces: true });
|
|
2344
|
+
}
|
|
2345
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductDeleteButtonComponent, decorators: [{
|
|
2346
|
+
type: Component,
|
|
2347
|
+
args: [{ selector: 'app-product-delete-button', template: "<mat-icon class=\"cursor-pointer text-secondary\" (click)=\"showDeleteDialog(deleteProductDialog)\"> delete </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 [disabled]=\"isDeleting\" type=\"button\" mat-raised-button color=\"warn\" (click)=\"deleteProduct()\">\n Delete\n </button>\n <button [disabled]=\"isDeleting\" type=\"button\" mat-flat-button mat-dialog-close>Cancel</button>\n </div>\n</ng-template>\n" }]
|
|
2348
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ProductService }, { type: i1.AlertService }], propDecorators: { product: [{
|
|
2349
|
+
type: Input
|
|
2350
|
+
}], deleted: [{
|
|
2351
|
+
type: Output
|
|
2352
|
+
}] } });
|
|
2353
|
+
|
|
2354
|
+
class ProductBasicInfoComponent {
|
|
2355
|
+
stockSummaryService;
|
|
2356
|
+
product;
|
|
2357
|
+
saved = new EventEmitter();
|
|
2358
|
+
deleted = new EventEmitter();
|
|
2359
|
+
stockSummary;
|
|
2360
|
+
constructor(stockSummaryService) {
|
|
2361
|
+
this.stockSummaryService = stockSummaryService;
|
|
2362
|
+
}
|
|
2363
|
+
ngOnInit() {
|
|
2364
|
+
if (this.product) {
|
|
2365
|
+
this.loadProductStocksSummary();
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
onProductSaved(product) {
|
|
2369
|
+
this.product = product;
|
|
2370
|
+
this.saved.emit(this.product);
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Load product stocks summary.
|
|
2374
|
+
*/
|
|
2375
|
+
loadProductStocksSummary() {
|
|
2376
|
+
const params = {
|
|
2377
|
+
product_ids: this.product?.id,
|
|
2378
|
+
include: 'stock_receipts_quantity_sum,stock_issuances_quantity_sum,stock_quantity_remaining',
|
|
2379
|
+
};
|
|
2380
|
+
this.stockSummaryService.summary(params).subscribe({
|
|
2381
|
+
next: (response) => {
|
|
2382
|
+
this.stockSummary = response;
|
|
2383
|
+
},
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, deps: [{ token: StockSummaryService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2387
|
+
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 class=\"d-flex justify-content-between align-items-center mb-1 mb-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">{{ product?.name }}</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button [product]=\"product\" (saved)=\"onProductSaved($event)\"></app-product-form-button>\n <app-product-delete-button [product]=\"product\" (deleted)=\"deleted.emit()\"></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n\n <mat-card-content class=\"mt-3\">\n <div class=\"d-flex flex-wrap gap-1\">\n <span class=\"badge badge-primary\" *ngFor=\"let category of product?.categories\">\n <span class=\"badge badge-primary\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content class=\"d-flex justify-content-between align-items-start\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </div>\n </div>\n </mat-card-content>\n\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content class=\"mt-5 d-flex justify-content-between align-items-start\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content class=\"mt-5 d-flex justify-content-between align-items-start\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 </div>\n </mat-card-content>\n\n <mat-card-content *ngIf=\"stockSummary\" class=\"mt-3 d-flex justify-content-center align-items-center\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content *ngIf=\"stockSummary\" class=\"mt-3 d-flex justify-content-center align-items-center\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 </div>\n </mat-card-content>\n </div>\n </mat-card-content>\n </mat-card-content>\n</mat-card>", 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: i5$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 });
|
|
2388
|
+
}
|
|
2389
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductBasicInfoComponent, decorators: [{
|
|
2390
|
+
type: Component,
|
|
2391
|
+
args: [{ selector: 'app-product-basic-info', template: "<mat-card *ngIf=\"product\" class=\"w-100\">\n <mat-card-content class=\"d-flex justify-content-between align-items-center mb-1 mb-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <span class=\"material-symbols-outlined\"> campaign </span>\n <strong class=\"mb-0 text-dark\">{{ product?.name }}</strong>\n </div>\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <app-product-form-button [product]=\"product\" (saved)=\"onProductSaved($event)\"></app-product-form-button>\n <app-product-delete-button [product]=\"product\" (deleted)=\"deleted.emit()\"></app-product-delete-button>\n </div>\n </mat-card-content>\n <mat-divider></mat-divider>\n\n <mat-card-content class=\"mt-3\">\n <div class=\"d-flex flex-wrap gap-1\">\n <span class=\"badge badge-primary\" *ngFor=\"let category of product?.categories\">\n <span class=\"badge badge-primary\" *ngFor=\"let category of product?.categories\">\n {{ category?.title }}\n </span>\n </span>\n </div>\n </mat-card-content>\n\n <mat-card-content class=\"d-flex justify-content-between align-items-start\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">SKU</small>\n <p class=\"mb-0\">{{ product?.sku }}</p>\n </div>\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Measure</small>\n <p class=\"mb-0\">{{ product?.measure?.title }}</p>\n </div>\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Reorder Point</small>\n <p class=\"mb-0\">{{ product?.reorder_point }}</p>\n </div>\n </div>\n </div>\n </mat-card-content>\n\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content class=\"mt-3 d-flex flex-column justify-content-start align-items-start gap-1\">\n <small class=\"text-secondary\">Description</small>\n <p class=\"mb-0\">{{ product?.description }}</p>\n </mat-card-content>\n\n <mat-card-content class=\"mt-5 d-flex justify-content-between align-items-start\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content class=\"mt-5 d-flex justify-content-between align-items-start\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <div *ngIf=\"stockSummary\" class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 </div>\n </mat-card-content>\n\n <mat-card-content *ngIf=\"stockSummary\" class=\"mt-3 d-flex justify-content-center align-items-center\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\n <mat-card-content *ngIf=\"stockSummary\" class=\"mt-3 d-flex justify-content-center align-items-center\">\n <div class=\"d-flex flex-column justify-content-start align-items-start gap-1\">\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 </div>\n </mat-card-content>\n </div>\n </mat-card-content>\n </mat-card-content>\n</mat-card>" }]
|
|
2392
|
+
}], ctorParameters: () => [{ type: StockSummaryService }], propDecorators: { product: [{
|
|
2393
|
+
type: Input
|
|
2394
|
+
}], saved: [{
|
|
2395
|
+
type: Output
|
|
2396
|
+
}], deleted: [{
|
|
2397
|
+
type: Output
|
|
2398
|
+
}] } });
|
|
2399
|
+
|
|
2400
|
+
class ProductViewPageComponent {
|
|
2401
|
+
productService;
|
|
2402
|
+
activatedRoute;
|
|
2403
|
+
location;
|
|
2404
|
+
product;
|
|
2405
|
+
id;
|
|
2406
|
+
isLoading;
|
|
2407
|
+
constructor(productService, activatedRoute, location) {
|
|
2408
|
+
this.productService = productService;
|
|
2409
|
+
this.activatedRoute = activatedRoute;
|
|
2410
|
+
this.location = location;
|
|
2411
|
+
this.id = this.activatedRoute.snapshot.params?.['id'];
|
|
2412
|
+
}
|
|
2413
|
+
ngOnInit() {
|
|
2414
|
+
if (this.id) {
|
|
2415
|
+
this.getProduct(this.id);
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* Get the product details.
|
|
2420
|
+
*
|
|
2421
|
+
* @param productId
|
|
2422
|
+
*/
|
|
2423
|
+
getProduct(productId) {
|
|
2424
|
+
this.isLoading = true;
|
|
2425
|
+
const params = {
|
|
2426
|
+
with: 'type,measure,incomeAccount,expenseAccount,categories,lastStockReceipt,lastStockIssuance,taxes.tax.type',
|
|
2427
|
+
};
|
|
2428
|
+
this.productService.show(productId, params).subscribe({
|
|
2429
|
+
next: (result) => {
|
|
2430
|
+
this.isLoading = false;
|
|
2431
|
+
this.product = result?.item;
|
|
2432
|
+
},
|
|
2433
|
+
error: () => (this.isLoading = false),
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Handle the on product update event.
|
|
2438
|
+
*
|
|
2439
|
+
* @param product
|
|
2440
|
+
*/
|
|
2441
|
+
onProductUpdated(product) {
|
|
2442
|
+
this.getProduct(this.id);
|
|
2443
|
+
}
|
|
2444
|
+
/**
|
|
2445
|
+
* Handle on product delete event.
|
|
2446
|
+
*/
|
|
2447
|
+
onProductDeleted() {
|
|
2448
|
+
this.location.back();
|
|
2449
|
+
}
|
|
2450
|
+
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 });
|
|
2451
|
+
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 *ngIf=\"product\" class=\"d-flex justify-content-start align-items-start gap-3\">\n<div *ngIf=\"product\" class=\"d-flex justify-content-start align-items-start gap-3\">\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info [product]=\"product\" #productBasicInfoComponent (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"></app-product-basic-info>\n\n <app-product-location-list [product]=\"product\"></app-product-location-list>\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 [product]=\"product\" (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"></app-stock-receipts-list-page>\n\n <app-stock-issuances-list [product]=\"product\" (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"></app-stock-issuances-list>\n\n <app-stock-transfer-list *ngIf=\"product\" [productId]=\"product.id\"></app-stock-transfer-list>\n </div>\n</div>", 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: i5.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: ProductLocationListComponent, selector: "app-product-location-list", inputs: ["product"] }, { kind: "component", type: StockTransferListComponent, selector: "app-stock-transfer-list", inputs: ["productId"] }, { kind: "component", type: ProductBasicInfoComponent, selector: "app-product-basic-info", inputs: ["product"], outputs: ["saved", "deleted"] }], preserveWhitespaces: true });
|
|
2452
|
+
}
|
|
2453
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductViewPageComponent, decorators: [{
|
|
2454
|
+
type: Component,
|
|
2455
|
+
args: [{ selector: 'app-product-view-page', template: "<mat-progress-bar mode=\"indeterminate\" *ngIf=\"isLoading\"></mat-progress-bar>\n\n<div *ngIf=\"product\" class=\"d-flex justify-content-start align-items-start gap-3\">\n<div *ngIf=\"product\" class=\"d-flex justify-content-start align-items-start gap-3\">\n <div style=\"width: calc(25% - 1rem)\" class=\"d-flex flex-column gap-3\">\n <app-product-basic-info [product]=\"product\" #productBasicInfoComponent (deleted)=\"onProductDeleted()\"\n (saved)=\"onProductUpdated($event)\"></app-product-basic-info>\n\n <app-product-location-list [product]=\"product\"></app-product-location-list>\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 [product]=\"product\" (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"></app-stock-receipts-list-page>\n\n <app-stock-issuances-list [product]=\"product\" (listUpdated)=\"\n getProduct(this.id);\n productBasicInfoComponent.loadProductStocksSummary()\n \"></app-stock-issuances-list>\n\n <app-stock-transfer-list *ngIf=\"product\" [productId]=\"product.id\"></app-stock-transfer-list>\n </div>\n</div>" }]
|
|
2456
|
+
}], ctorParameters: () => [{ type: ProductService }, { type: i2.ActivatedRoute }, { type: i4.Location }] });
|
|
2457
|
+
|
|
2458
|
+
class ProductImportPageComponent {
|
|
2459
|
+
importConfig = {
|
|
2460
|
+
apiUrl: 'api/products-import',
|
|
2461
|
+
title: 'Products',
|
|
2462
|
+
importType: 'product',
|
|
2463
|
+
properties: [
|
|
2464
|
+
{
|
|
2465
|
+
label: 'Name',
|
|
2466
|
+
value: 'name',
|
|
2467
|
+
type: 'text',
|
|
2468
|
+
},
|
|
2469
|
+
{
|
|
2470
|
+
label: 'SKU',
|
|
2471
|
+
value: 'sku',
|
|
2472
|
+
type: 'text',
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
label: 'Initial Quantity',
|
|
2476
|
+
value: 'initial_quantity',
|
|
2477
|
+
type: 'number',
|
|
2478
|
+
},
|
|
2479
|
+
{
|
|
2480
|
+
label: 'Initial Quantity Date',
|
|
2481
|
+
value: 'initial_quantity_date',
|
|
2482
|
+
type: 'date',
|
|
2483
|
+
},
|
|
2484
|
+
{
|
|
2485
|
+
label: 'Reorder Point',
|
|
2486
|
+
value: 'reorder_point',
|
|
2487
|
+
type: 'number',
|
|
2488
|
+
},
|
|
2489
|
+
{
|
|
2490
|
+
label: 'Measure',
|
|
2491
|
+
value: 'measure',
|
|
2492
|
+
type: 'text',
|
|
2493
|
+
},
|
|
2494
|
+
{
|
|
2495
|
+
label: 'Categories',
|
|
2496
|
+
value: 'categories',
|
|
2497
|
+
type: 'text',
|
|
2498
|
+
},
|
|
2499
|
+
],
|
|
2500
|
+
sampleFile: {
|
|
2501
|
+
name: 'Products Import',
|
|
2502
|
+
path: 'assets/product/product-import-sample.csv',
|
|
2503
|
+
},
|
|
2504
|
+
importHistory: {
|
|
2505
|
+
isEnabled: true,
|
|
2506
|
+
type: 'product',
|
|
2507
|
+
apiUrl: 'api/import-histories',
|
|
2508
|
+
},
|
|
2509
|
+
viewRouterLink: '/inventory/products/',
|
|
2510
|
+
};
|
|
2511
|
+
constructor() { }
|
|
2512
|
+
ngOnInit() { }
|
|
2513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2514
|
+
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 });
|
|
2515
|
+
}
|
|
2516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductImportPageComponent, decorators: [{
|
|
2517
|
+
type: Component,
|
|
2518
|
+
args: [{ selector: 'app-product-import-page', template: "<app-import-csv [config]=\"importConfig\"></app-import-csv>\n" }]
|
|
2519
|
+
}], ctorParameters: () => [] });
|
|
2520
|
+
|
|
2521
|
+
const routes$2 = [
|
|
2522
|
+
{
|
|
2523
|
+
path: '',
|
|
2524
|
+
component: ProductNavBarComponent,
|
|
2525
|
+
children: [
|
|
2526
|
+
{
|
|
2527
|
+
path: '',
|
|
2528
|
+
component: ProductListComponent,
|
|
2529
|
+
canLoad: [AuthenticationGuard],
|
|
2530
|
+
},
|
|
2531
|
+
{
|
|
2532
|
+
path: 'import',
|
|
2533
|
+
component: ProductImportPageComponent,
|
|
2534
|
+
canLoad: [AuthenticationGuard],
|
|
2535
|
+
},
|
|
2536
|
+
{
|
|
2537
|
+
path: 'measure',
|
|
2538
|
+
component: ProductMeasuresListComponent,
|
|
2539
|
+
canLoad: [AuthenticationGuard],
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
path: ':id/view',
|
|
2543
|
+
component: ProductViewPageComponent,
|
|
2544
|
+
canLoad: [AuthenticationGuard],
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
path: '**',
|
|
2548
|
+
redirectTo: '',
|
|
2549
|
+
pathMatch: 'full',
|
|
2550
|
+
canLoad: [AuthenticationGuard],
|
|
2551
|
+
},
|
|
2552
|
+
],
|
|
2553
|
+
},
|
|
2554
|
+
];
|
|
2555
|
+
class ProductRoutingModule {
|
|
2556
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2557
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
2558
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, imports: [RouterModule.forChild(routes$2), RouterModule] });
|
|
2559
|
+
}
|
|
2560
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductRoutingModule, decorators: [{
|
|
2561
|
+
type: NgModule,
|
|
2562
|
+
args: [{
|
|
2563
|
+
imports: [RouterModule.forChild(routes$2)],
|
|
2564
|
+
exports: [RouterModule],
|
|
2565
|
+
}]
|
|
2566
|
+
}] });
|
|
2567
|
+
|
|
2568
|
+
class PayeeSelectorModule {
|
|
2569
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2570
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, declarations: [PayeeSelectorComponent], imports: [CommonModule, MatFormFieldModule, ReactiveFormsModule, SearchableSelectorModule, FormsModule], exports: [PayeeSelectorComponent] });
|
|
2571
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, imports: [CommonModule, MatFormFieldModule, ReactiveFormsModule, SearchableSelectorModule, FormsModule] });
|
|
2572
|
+
}
|
|
2573
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PayeeSelectorModule, decorators: [{
|
|
2574
|
+
type: NgModule,
|
|
2575
|
+
args: [{
|
|
2576
|
+
declarations: [PayeeSelectorComponent],
|
|
2577
|
+
exports: [PayeeSelectorComponent],
|
|
2578
|
+
imports: [CommonModule, MatFormFieldModule, ReactiveFormsModule, SearchableSelectorModule, FormsModule],
|
|
2579
|
+
}]
|
|
2580
|
+
}] });
|
|
2581
|
+
|
|
2582
|
+
class StockReceiptFormModule {
|
|
2583
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2584
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, declarations: [StockReceiptFormComponent, StockReceiptFormButtonComponent], imports: [CommonModule,
|
|
2585
|
+
MatTooltipModule,
|
|
2586
|
+
MatDialogModule,
|
|
2587
|
+
PayeeSelectorModule,
|
|
2588
|
+
ReactiveFormsModule,
|
|
2589
|
+
MatFormFieldModule,
|
|
2590
|
+
MatInputModule,
|
|
2591
|
+
MatDatepickerModule,
|
|
2592
|
+
MatButtonModule], exports: [StockReceiptFormButtonComponent] });
|
|
2593
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, imports: [CommonModule,
|
|
2594
|
+
MatTooltipModule,
|
|
2595
|
+
MatDialogModule,
|
|
2596
|
+
PayeeSelectorModule,
|
|
2597
|
+
ReactiveFormsModule,
|
|
2598
|
+
MatFormFieldModule,
|
|
2599
|
+
MatInputModule,
|
|
2600
|
+
MatDatepickerModule,
|
|
2601
|
+
MatButtonModule] });
|
|
2602
|
+
}
|
|
2603
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptFormModule, decorators: [{
|
|
2604
|
+
type: NgModule,
|
|
2605
|
+
args: [{
|
|
2606
|
+
declarations: [StockReceiptFormComponent, StockReceiptFormButtonComponent],
|
|
2607
|
+
exports: [StockReceiptFormButtonComponent],
|
|
2608
|
+
imports: [
|
|
2609
|
+
CommonModule,
|
|
2610
|
+
MatTooltipModule,
|
|
2611
|
+
MatDialogModule,
|
|
2612
|
+
PayeeSelectorModule,
|
|
2613
|
+
ReactiveFormsModule,
|
|
2614
|
+
MatFormFieldModule,
|
|
2615
|
+
MatInputModule,
|
|
2616
|
+
MatDatepickerModule,
|
|
2617
|
+
MatButtonModule,
|
|
2618
|
+
],
|
|
2619
|
+
}]
|
|
2620
|
+
}] });
|
|
2621
|
+
|
|
2622
|
+
class StockIssueFormModule {
|
|
2623
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2624
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, declarations: [StockIssueFormComponent, StockIssueFormButtonComponent], imports: [CommonModule,
|
|
2625
|
+
ReactiveFormsModule,
|
|
2626
|
+
MatFormFieldModule,
|
|
2627
|
+
MatInputModule,
|
|
2628
|
+
MatDatepickerModule,
|
|
2629
|
+
MatButtonModule,
|
|
2630
|
+
MatDialogModule,
|
|
2631
|
+
MatTooltipModule,
|
|
2632
|
+
SearchableSelectorModule], exports: [StockIssueFormButtonComponent] });
|
|
2633
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, imports: [CommonModule,
|
|
2634
|
+
ReactiveFormsModule,
|
|
2635
|
+
MatFormFieldModule,
|
|
2636
|
+
MatInputModule,
|
|
2637
|
+
MatDatepickerModule,
|
|
2638
|
+
MatButtonModule,
|
|
2639
|
+
MatDialogModule,
|
|
2640
|
+
MatTooltipModule,
|
|
2641
|
+
SearchableSelectorModule] });
|
|
2642
|
+
}
|
|
2643
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssueFormModule, decorators: [{
|
|
2644
|
+
type: NgModule,
|
|
2645
|
+
args: [{
|
|
2646
|
+
declarations: [StockIssueFormComponent, StockIssueFormButtonComponent],
|
|
2647
|
+
exports: [StockIssueFormButtonComponent],
|
|
2648
|
+
imports: [
|
|
2649
|
+
CommonModule,
|
|
2650
|
+
ReactiveFormsModule,
|
|
2651
|
+
MatFormFieldModule,
|
|
2652
|
+
MatInputModule,
|
|
2653
|
+
MatDatepickerModule,
|
|
2654
|
+
MatButtonModule,
|
|
2655
|
+
MatDialogModule,
|
|
2656
|
+
MatTooltipModule,
|
|
2657
|
+
SearchableSelectorModule,
|
|
2658
|
+
],
|
|
2659
|
+
}]
|
|
2660
|
+
}] });
|
|
2661
|
+
|
|
2662
|
+
const routes$1 = [
|
|
2663
|
+
{
|
|
2664
|
+
path: '',
|
|
2665
|
+
component: StockReceiptsListPageComponent,
|
|
2666
|
+
},
|
|
2667
|
+
];
|
|
2668
|
+
class StockReceiptsRoutingModule {
|
|
2669
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2670
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
2671
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, imports: [RouterModule.forChild(routes$1), RouterModule] });
|
|
2672
|
+
}
|
|
2673
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsRoutingModule, decorators: [{
|
|
2674
|
+
type: NgModule,
|
|
2675
|
+
args: [{
|
|
2676
|
+
imports: [RouterModule.forChild(routes$1)],
|
|
2677
|
+
exports: [RouterModule],
|
|
2678
|
+
}]
|
|
2679
|
+
}] });
|
|
2680
|
+
|
|
2681
|
+
class TechlifyFilterComponent {
|
|
2682
|
+
requestHelperService;
|
|
2683
|
+
activatedRoute;
|
|
2684
|
+
filterForm;
|
|
2685
|
+
filterConfig;
|
|
2686
|
+
filterUpdated = new EventEmitter();
|
|
2687
|
+
constructor(requestHelperService, activatedRoute) {
|
|
2688
|
+
this.requestHelperService = requestHelperService;
|
|
2689
|
+
this.activatedRoute = activatedRoute;
|
|
2690
|
+
}
|
|
2691
|
+
ngOnInit() {
|
|
2692
|
+
// listen for filter changes
|
|
2693
|
+
this.filterForm.valueChanges.subscribe({
|
|
2694
|
+
next: (value) => {
|
|
2695
|
+
const params = this.requestHelperService.convertToFormData(value);
|
|
2696
|
+
this.requestHelperService.updateQueryParams(params);
|
|
2697
|
+
},
|
|
2698
|
+
});
|
|
2699
|
+
// update form with query params
|
|
2700
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
2701
|
+
duration: { number: true },
|
|
2702
|
+
expiry_duration: { number: true },
|
|
2703
|
+
payment_method_ids: { multiple: true },
|
|
2704
|
+
payment_account_ids: { multiple: true },
|
|
2705
|
+
project_ids: { multiple: true },
|
|
2706
|
+
invoice_status_ids: { multiple: true },
|
|
2707
|
+
customer_ids: { multiple: true },
|
|
2708
|
+
cost_category_ids: { multiple: true },
|
|
2709
|
+
team_member_ids: { multiple: true },
|
|
2710
|
+
task_status_ids: { multiple: true },
|
|
2711
|
+
asset_account_ids: { multiple: true },
|
|
2712
|
+
depreciation_method_ids: { multiple: true },
|
|
2713
|
+
depreciation_expense_account_ids: { multiple: true },
|
|
2714
|
+
fixed_asset_type_ids: { multiple: true },
|
|
2715
|
+
fixed_asset_document_type_ids: { multiple: true },
|
|
2716
|
+
service_center_ids: { multiple: true },
|
|
2717
|
+
fixed_asset_maintenance_status_ids: { multiple: true },
|
|
2718
|
+
milestone_ids: { multiple: true },
|
|
2719
|
+
product_ids: { multiple: true },
|
|
2720
|
+
supplier_ids: { multiple: true },
|
|
2721
|
+
measure_ids: { multiple: true },
|
|
2722
|
+
type_ids: { multiple: true },
|
|
2723
|
+
fixed_asset_ids: { multiple: true },
|
|
2724
|
+
});
|
|
2725
|
+
// listen for route change
|
|
2726
|
+
this.activatedRoute.queryParams.pipe(debounceTime$1(800), distinctUntilChanged()).subscribe((val) => {
|
|
2727
|
+
this.filterUpdated.emit(this.filterForm.value);
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
resetField(field) {
|
|
2731
|
+
this.filterForm.get(field)?.setValue('');
|
|
2732
|
+
}
|
|
2733
|
+
onDurationChange(timelineValue) {
|
|
2734
|
+
let { date_to, date_from } = timelineValue;
|
|
2735
|
+
this.filterForm.patchValue({
|
|
2736
|
+
date_from: date_from ? moment(date_from).format('YYYY-MM-DD') : '',
|
|
2737
|
+
date_to: date_to ? moment(date_to).format('YYYY-MM-DD') : '',
|
|
2738
|
+
}, { emitEvent: false });
|
|
2739
|
+
}
|
|
2740
|
+
/**
|
|
2741
|
+
* Update expiry date from and date to on value change.
|
|
2742
|
+
*
|
|
2743
|
+
* @param timelineValue
|
|
2744
|
+
*/
|
|
2745
|
+
onExpiryDurationChange(timelineValue) {
|
|
2746
|
+
let { date_to, date_from } = timelineValue;
|
|
2747
|
+
this.filterForm.patchValue({
|
|
2748
|
+
expiry_date_from: date_from ? moment(date_from).format('YYYY-MM-DD') : '',
|
|
2749
|
+
expiry_date_to: date_to ? moment(date_to).format('YYYY-MM-DD') : '',
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
/**
|
|
2753
|
+
* Get the attribute value for the field.
|
|
2754
|
+
*
|
|
2755
|
+
* @param attribute
|
|
2756
|
+
* @param field
|
|
2757
|
+
*/
|
|
2758
|
+
getFilterConfig(attribute, field) {
|
|
2759
|
+
if (!this.filterConfig)
|
|
2760
|
+
return '';
|
|
2761
|
+
// Check if the field and attribute exist in the filter config, return the value or an empty string
|
|
2762
|
+
return this.filterConfig[field] && this.filterConfig[field][attribute] !== undefined
|
|
2763
|
+
? this.filterConfig[field][attribute]
|
|
2764
|
+
: '';
|
|
2765
|
+
}
|
|
2766
|
+
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 });
|
|
2767
|
+
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 [formGroup]=\"filterForm\" fxLayout fxLayoutAlign=\"start center\" fxLayoutGap=\"10px\">\n <mat-form-field *ngIf=\"filterForm.get('search')\" [appearance]=\"getFilterConfig('appearance', 'search')\">\n <mat-label>Search</mat-label>\n <input formControlName=\"search\" matInput [placeholder]=\"getFilterConfig('placeholder', 'search')\" />\n <button *ngIf=\"filterForm.value?.search\" mat-icon-button matSuffix (click)=\"resetField('search')\">\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>{{ getFilterConfig('label', 'payment_account_ids') || 'Payment Account' }}</mat-label>\n <app-searchable-selector\n formControlName=\"payment_account_ids\"\n [apiUrl]=\"getFilterConfig('apiUrl', 'payment_account_ids') || 'api/accounts'\"\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 *ngIf=\"filterForm.value?.customer_ids\" mat-icon-button matSuffix (click)=\"resetField('customer_ids')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"filterForm.get('project_ids') && getFilterConfig('disabled', 'project_ids') === false\">\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 *ngIf=\"filterForm.value?.project_ids\" mat-icon-button matSuffix (click)=\"resetField('project_ids')\">\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 *ngIf=\"filterForm.value?.product_ids\" mat-icon-button matSuffix (click)=\"resetField('product_ids')\">\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 *ngIf=\"filterForm.value?.measure_ids\" mat-icon-button matSuffix (click)=\"resetField('measure_ids')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngxPermissionsOnly=\"['supplier.read']\">\n <mat-form-field *ngIf=\"filterForm.get('supplier_ids')\" [appearance]=\"getFilterConfig('appearance', 'supplier_ids')\">\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 *ngIf=\"filterForm.value?.supplier_ids\" mat-icon-button matSuffix (click)=\"resetField('supplier_ids')\">\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 *ngIf=\"filterForm.get('cost_category_ids')\" style=\"width: 150px\">\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 *ngIf=\"filterForm.value?.milestone_ids\" mat-icon-button matSuffix (click)=\"resetField('milestone_ids')\">\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 apiUrl=\"api/persons\" formControlName=\"team_member_ids\" titleField=\"name\" [multiple]=\"true\">\n </app-searchable-selector>\n <button *ngIf=\"filterForm.value?.team_member_ids\" mat-icon-button matSuffix (click)=\"resetField('team_member_ids')\">\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]=\"getFilterConfig('enableSearch', 'fixed_asset_document_type_ids')\"\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 class=\"mr-2 text-secondary\" *ngIf=\"getFilterConfig('showLabel', 'fixed_asset_document_status')\">\n Status\n </small>\n <mat-button-toggle-group formControlName=\"fixed_asset_document_status\" [multiple]=\"false\">\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 *ngIf=\"filterForm.get('task_status_ids')\" style=\"width: 150px\">\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 *ngIf=\"filterForm.value?.task_status_ids\" mat-icon-button matSuffix (click)=\"resetField('task_status_ids')\">\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: i4$3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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"] }, { kind: "directive", type: i13.NgxPermissionsDirective, selector: "[ngxPermissionsOnly],[ngxPermissionsExcept]", inputs: ["ngxPermissionsOnly", "ngxPermissionsOnlyThen", "ngxPermissionsOnlyElse", "ngxPermissionsExcept", "ngxPermissionsExceptElse", "ngxPermissionsExceptThen", "ngxPermissionsThen", "ngxPermissionsElse", "ngxPermissionsOnlyAuthorisedStrategy", "ngxPermissionsOnlyUnauthorisedStrategy", "ngxPermissionsExceptUnauthorisedStrategy", "ngxPermissionsExceptAuthorisedStrategy", "ngxPermissionsUnauthorisedStrategy", "ngxPermissionsAuthorisedStrategy"], outputs: ["permissionsAuthorized", "permissionsUnauthorized"] }], preserveWhitespaces: true });
|
|
2768
|
+
}
|
|
2769
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterComponent, decorators: [{
|
|
2770
|
+
type: Component,
|
|
2771
|
+
args: [{ selector: 'app-techlify-filter', template: "<form [formGroup]=\"filterForm\" fxLayout fxLayoutAlign=\"start center\" fxLayoutGap=\"10px\">\n <mat-form-field *ngIf=\"filterForm.get('search')\" [appearance]=\"getFilterConfig('appearance', 'search')\">\n <mat-label>Search</mat-label>\n <input formControlName=\"search\" matInput [placeholder]=\"getFilterConfig('placeholder', 'search')\" />\n <button *ngIf=\"filterForm.value?.search\" mat-icon-button matSuffix (click)=\"resetField('search')\">\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>{{ getFilterConfig('label', 'payment_account_ids') || 'Payment Account' }}</mat-label>\n <app-searchable-selector\n formControlName=\"payment_account_ids\"\n [apiUrl]=\"getFilterConfig('apiUrl', 'payment_account_ids') || 'api/accounts'\"\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 *ngIf=\"filterForm.value?.customer_ids\" mat-icon-button matSuffix (click)=\"resetField('customer_ids')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ng-container>\n\n <ng-container *ngIf=\"filterForm.get('project_ids') && getFilterConfig('disabled', 'project_ids') === false\">\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 *ngIf=\"filterForm.value?.project_ids\" mat-icon-button matSuffix (click)=\"resetField('project_ids')\">\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 *ngIf=\"filterForm.value?.product_ids\" mat-icon-button matSuffix (click)=\"resetField('product_ids')\">\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 *ngIf=\"filterForm.value?.measure_ids\" mat-icon-button matSuffix (click)=\"resetField('measure_ids')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n\n <ng-container *ngxPermissionsOnly=\"['supplier.read']\">\n <mat-form-field *ngIf=\"filterForm.get('supplier_ids')\" [appearance]=\"getFilterConfig('appearance', 'supplier_ids')\">\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 *ngIf=\"filterForm.value?.supplier_ids\" mat-icon-button matSuffix (click)=\"resetField('supplier_ids')\">\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 *ngIf=\"filterForm.get('cost_category_ids')\" style=\"width: 150px\">\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 *ngIf=\"filterForm.value?.milestone_ids\" mat-icon-button matSuffix (click)=\"resetField('milestone_ids')\">\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 apiUrl=\"api/persons\" formControlName=\"team_member_ids\" titleField=\"name\" [multiple]=\"true\">\n </app-searchable-selector>\n <button *ngIf=\"filterForm.value?.team_member_ids\" mat-icon-button matSuffix (click)=\"resetField('team_member_ids')\">\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]=\"getFilterConfig('enableSearch', 'fixed_asset_document_type_ids')\"\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 class=\"mr-2 text-secondary\" *ngIf=\"getFilterConfig('showLabel', 'fixed_asset_document_status')\">\n Status\n </small>\n <mat-button-toggle-group formControlName=\"fixed_asset_document_status\" [multiple]=\"false\">\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 *ngIf=\"filterForm.get('task_status_ids')\" style=\"width: 150px\">\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 *ngIf=\"filterForm.value?.task_status_ids\" mat-icon-button matSuffix (click)=\"resetField('task_status_ids')\">\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" }]
|
|
2772
|
+
}], ctorParameters: () => [{ type: i1.RequestHelperService }, { type: i2.ActivatedRoute }], propDecorators: { filterForm: [{
|
|
2773
|
+
type: Input
|
|
2774
|
+
}], filterConfig: [{
|
|
2775
|
+
type: Input
|
|
2776
|
+
}], filterUpdated: [{
|
|
2777
|
+
type: Output
|
|
2778
|
+
}] } });
|
|
2779
|
+
|
|
2780
|
+
class TechlifyFilterModule {
|
|
2781
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2782
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, declarations: [TechlifyFilterComponent], imports: [CommonModule,
|
|
2783
|
+
ReactiveFormsModule,
|
|
2784
|
+
FlexLayoutModule,
|
|
2785
|
+
SearchableSelectorModule,
|
|
2786
|
+
TimelineFilterModule,
|
|
2787
|
+
MaterialModule$1,
|
|
2788
|
+
NgxPermissionsModule], exports: [TechlifyFilterComponent] });
|
|
2789
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, imports: [CommonModule,
|
|
2790
|
+
ReactiveFormsModule,
|
|
2791
|
+
FlexLayoutModule,
|
|
2792
|
+
SearchableSelectorModule,
|
|
2793
|
+
TimelineFilterModule,
|
|
2794
|
+
MaterialModule$1,
|
|
2795
|
+
NgxPermissionsModule] });
|
|
2796
|
+
}
|
|
2797
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TechlifyFilterModule, decorators: [{
|
|
2798
|
+
type: NgModule,
|
|
2799
|
+
args: [{
|
|
2800
|
+
declarations: [TechlifyFilterComponent],
|
|
2801
|
+
imports: [
|
|
2802
|
+
CommonModule,
|
|
2803
|
+
ReactiveFormsModule,
|
|
2804
|
+
FlexLayoutModule,
|
|
2805
|
+
SearchableSelectorModule,
|
|
2806
|
+
TimelineFilterModule,
|
|
2807
|
+
MaterialModule$1,
|
|
2808
|
+
NgxPermissionsModule,
|
|
2809
|
+
],
|
|
2810
|
+
exports: [TechlifyFilterComponent],
|
|
2811
|
+
}]
|
|
2812
|
+
}] });
|
|
2813
|
+
|
|
2814
|
+
class StockReceiptsModule {
|
|
2815
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2816
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, declarations: [StockReceiptsListPageComponent, StockReceiptDeleteButtonComponent], imports: [CommonModule,
|
|
2817
|
+
StockReceiptsRoutingModule,
|
|
2818
|
+
MatCardModule,
|
|
2819
|
+
TechlifyFilterModule,
|
|
2820
|
+
MatTableModule,
|
|
2821
|
+
MatFormFieldModule,
|
|
2822
|
+
SearchableSelectorModule,
|
|
2823
|
+
TimelineFilterModule,
|
|
2824
|
+
ReactiveFormsModule,
|
|
2825
|
+
PayeeSelectorModule,
|
|
2826
|
+
MatProgressBarModule,
|
|
2827
|
+
InfiniteScrollModule,
|
|
2828
|
+
MaterialModule$1,
|
|
2829
|
+
StockReceiptFormModule,
|
|
2830
|
+
ProductCategoryBadgesComponent,
|
|
2831
|
+
ColumnSelectorModule], exports: [StockReceiptDeleteButtonComponent, StockReceiptsListPageComponent] });
|
|
2832
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, imports: [CommonModule,
|
|
2833
|
+
StockReceiptsRoutingModule,
|
|
2834
|
+
MatCardModule,
|
|
2835
|
+
TechlifyFilterModule,
|
|
2836
|
+
MatTableModule,
|
|
2837
|
+
MatFormFieldModule,
|
|
2838
|
+
SearchableSelectorModule,
|
|
2839
|
+
TimelineFilterModule,
|
|
2840
|
+
ReactiveFormsModule,
|
|
2841
|
+
PayeeSelectorModule,
|
|
2842
|
+
MatProgressBarModule,
|
|
2843
|
+
InfiniteScrollModule,
|
|
2844
|
+
MaterialModule$1,
|
|
2845
|
+
StockReceiptFormModule,
|
|
2846
|
+
ColumnSelectorModule] });
|
|
2847
|
+
}
|
|
2848
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockReceiptsModule, decorators: [{
|
|
2849
|
+
type: NgModule,
|
|
2850
|
+
args: [{
|
|
2851
|
+
declarations: [StockReceiptsListPageComponent, StockReceiptDeleteButtonComponent],
|
|
2852
|
+
exports: [StockReceiptDeleteButtonComponent, StockReceiptsListPageComponent],
|
|
2853
|
+
imports: [
|
|
2854
|
+
CommonModule,
|
|
2855
|
+
StockReceiptsRoutingModule,
|
|
2856
|
+
MatCardModule,
|
|
2857
|
+
TechlifyFilterModule,
|
|
2858
|
+
MatTableModule,
|
|
2859
|
+
MatFormFieldModule,
|
|
2860
|
+
SearchableSelectorModule,
|
|
2861
|
+
TimelineFilterModule,
|
|
2862
|
+
ReactiveFormsModule,
|
|
2863
|
+
PayeeSelectorModule,
|
|
2864
|
+
MatProgressBarModule,
|
|
2865
|
+
InfiniteScrollModule,
|
|
2866
|
+
MaterialModule$1,
|
|
2867
|
+
StockReceiptFormModule,
|
|
2868
|
+
ProductCategoryBadgesComponent,
|
|
2869
|
+
ColumnSelectorModule,
|
|
2870
|
+
],
|
|
2871
|
+
}]
|
|
2872
|
+
}] });
|
|
2873
|
+
|
|
2874
|
+
var stockReceipts_module = /*#__PURE__*/Object.freeze({
|
|
2875
|
+
__proto__: null,
|
|
2876
|
+
StockReceiptsModule: StockReceiptsModule
|
|
2877
|
+
});
|
|
2878
|
+
|
|
2879
|
+
class StockIssuanceDeleteButtonModule {
|
|
2880
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2881
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, declarations: [StockIssuanceDeleteButtonComponent], imports: [CommonModule, MaterialModule$1], exports: [StockIssuanceDeleteButtonComponent] });
|
|
2882
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, imports: [CommonModule, MaterialModule$1] });
|
|
2883
|
+
}
|
|
2884
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuanceDeleteButtonModule, decorators: [{
|
|
2885
|
+
type: NgModule,
|
|
2886
|
+
args: [{
|
|
2887
|
+
declarations: [StockIssuanceDeleteButtonComponent],
|
|
2888
|
+
imports: [CommonModule, MaterialModule$1],
|
|
2889
|
+
exports: [StockIssuanceDeleteButtonComponent],
|
|
2890
|
+
}]
|
|
2891
|
+
}] });
|
|
2892
|
+
|
|
2893
|
+
class StockIssuancesListModule {
|
|
2894
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2895
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, declarations: [StockIssuancesListComponent], imports: [CommonModule,
|
|
2896
|
+
MaterialModule$1,
|
|
2897
|
+
TechlifyFilterModule,
|
|
2898
|
+
StockIssueFormModule,
|
|
2899
|
+
InfiniteScrollModule,
|
|
2900
|
+
StockIssuanceDeleteButtonModule,
|
|
2901
|
+
MatProgressBarModule,
|
|
2902
|
+
RouterModule,
|
|
2903
|
+
SearchableSelectorModule,
|
|
2904
|
+
TimelineFilterModule,
|
|
2905
|
+
ReactiveFormsModule,
|
|
2906
|
+
ProductCategoryBadgesComponent,
|
|
2907
|
+
ColumnSelectorModule], exports: [StockIssuancesListComponent] });
|
|
2908
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, imports: [CommonModule,
|
|
2909
|
+
MaterialModule$1,
|
|
2910
|
+
TechlifyFilterModule,
|
|
2911
|
+
StockIssueFormModule,
|
|
2912
|
+
InfiniteScrollModule,
|
|
2913
|
+
StockIssuanceDeleteButtonModule,
|
|
2914
|
+
MatProgressBarModule,
|
|
2915
|
+
RouterModule,
|
|
2916
|
+
SearchableSelectorModule,
|
|
2917
|
+
TimelineFilterModule,
|
|
2918
|
+
ReactiveFormsModule,
|
|
2919
|
+
ColumnSelectorModule] });
|
|
2920
|
+
}
|
|
2921
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StockIssuancesListModule, decorators: [{
|
|
2922
|
+
type: NgModule,
|
|
2923
|
+
args: [{
|
|
2924
|
+
declarations: [StockIssuancesListComponent],
|
|
2925
|
+
imports: [
|
|
2926
|
+
CommonModule,
|
|
2927
|
+
MaterialModule$1,
|
|
2928
|
+
TechlifyFilterModule,
|
|
2929
|
+
StockIssueFormModule,
|
|
2930
|
+
InfiniteScrollModule,
|
|
2931
|
+
StockIssuanceDeleteButtonModule,
|
|
2932
|
+
MatProgressBarModule,
|
|
2933
|
+
RouterModule,
|
|
2934
|
+
SearchableSelectorModule,
|
|
2935
|
+
TimelineFilterModule,
|
|
2936
|
+
ReactiveFormsModule,
|
|
2937
|
+
ProductCategoryBadgesComponent,
|
|
2938
|
+
ColumnSelectorModule,
|
|
2939
|
+
],
|
|
2940
|
+
exports: [StockIssuancesListComponent],
|
|
2941
|
+
}]
|
|
2942
|
+
}] });
|
|
2943
|
+
|
|
2944
|
+
class ProductTaxModule {
|
|
2945
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2946
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, declarations: [ProductTaxListComponent, ProductTaxFormButtonComponent, ProductTaxDeleteButtonComponent], imports: [CommonModule, MaterialModule$1, ReactiveFormsModule, SearchableSelectorModule], exports: [ProductTaxListComponent] });
|
|
2947
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, imports: [CommonModule, MaterialModule$1, ReactiveFormsModule, SearchableSelectorModule] });
|
|
2948
|
+
}
|
|
2949
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductTaxModule, decorators: [{
|
|
2950
|
+
type: NgModule,
|
|
2951
|
+
args: [{
|
|
2952
|
+
declarations: [ProductTaxListComponent, ProductTaxFormButtonComponent, ProductTaxDeleteButtonComponent],
|
|
2953
|
+
imports: [CommonModule, MaterialModule$1, ReactiveFormsModule, SearchableSelectorModule],
|
|
2954
|
+
exports: [ProductTaxListComponent],
|
|
2955
|
+
}]
|
|
2956
|
+
}] });
|
|
2957
|
+
|
|
2958
|
+
class ProductModule {
|
|
2959
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2960
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, declarations: [ProductListComponent,
|
|
2961
|
+
ProductFormComponent,
|
|
2962
|
+
ProductNavBarComponent,
|
|
2963
|
+
ProductMeasuresListComponent,
|
|
2964
|
+
ProductMeasureFormComponent,
|
|
2965
|
+
ProductViewPageComponent,
|
|
2966
|
+
ProductFormButtonComponent,
|
|
2967
|
+
ProductDeleteButtonComponent,
|
|
2968
|
+
ProductBasicInfoComponent,
|
|
2969
|
+
ProductImportPageComponent,
|
|
2970
|
+
ProductBatchUpdateFormComponent], imports: [CommonModule,
|
|
2971
|
+
ProductRoutingModule,
|
|
2972
|
+
SearchableSelectorModule,
|
|
2973
|
+
TimelineFilterModule,
|
|
2974
|
+
StockReceiptFormModule,
|
|
2975
|
+
StockIssueFormModule,
|
|
2976
|
+
ImportCsvModule,
|
|
2977
|
+
StockReceiptsModule,
|
|
2978
|
+
StockIssuancesListModule,
|
|
2979
|
+
ProductTaxModule,
|
|
2980
|
+
MaterialModule$1,
|
|
2981
|
+
MatProgressBarModule,
|
|
2982
|
+
InfiniteScrollModule,
|
|
2983
|
+
FlexModule,
|
|
2984
|
+
ReactiveFormsModule,
|
|
2985
|
+
FormsModule,
|
|
2986
|
+
ColumnSelectorModule,
|
|
2987
|
+
ProductLocationListComponent,
|
|
2988
|
+
StockTransferListComponent], exports: [ProductFormComponent,
|
|
2989
|
+
ProductBasicInfoComponent,
|
|
2990
|
+
ProductFormButtonComponent] });
|
|
2991
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, imports: [CommonModule,
|
|
2992
|
+
ProductRoutingModule,
|
|
2993
|
+
SearchableSelectorModule,
|
|
2994
|
+
TimelineFilterModule,
|
|
2995
|
+
StockReceiptFormModule,
|
|
2996
|
+
StockIssueFormModule,
|
|
2997
|
+
ImportCsvModule,
|
|
2998
|
+
StockReceiptsModule,
|
|
2999
|
+
StockIssuancesListModule,
|
|
3000
|
+
ProductTaxModule,
|
|
3001
|
+
MaterialModule$1,
|
|
3002
|
+
MatProgressBarModule,
|
|
3003
|
+
InfiniteScrollModule,
|
|
3004
|
+
FlexModule,
|
|
3005
|
+
ReactiveFormsModule,
|
|
3006
|
+
FormsModule,
|
|
3007
|
+
ColumnSelectorModule,
|
|
3008
|
+
ProductLocationListComponent,
|
|
3009
|
+
StockTransferListComponent] });
|
|
3010
|
+
}
|
|
3011
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductModule, decorators: [{
|
|
3012
|
+
type: NgModule,
|
|
3013
|
+
args: [{
|
|
3014
|
+
declarations: [
|
|
3015
|
+
ProductListComponent,
|
|
3016
|
+
ProductFormComponent,
|
|
3017
|
+
ProductNavBarComponent,
|
|
3018
|
+
ProductMeasuresListComponent,
|
|
3019
|
+
ProductMeasureFormComponent,
|
|
3020
|
+
ProductViewPageComponent,
|
|
3021
|
+
ProductFormButtonComponent,
|
|
3022
|
+
ProductDeleteButtonComponent,
|
|
3023
|
+
ProductBasicInfoComponent,
|
|
3024
|
+
ProductImportPageComponent,
|
|
3025
|
+
ProductBatchUpdateFormComponent,
|
|
3026
|
+
],
|
|
3027
|
+
imports: [
|
|
3028
|
+
CommonModule,
|
|
3029
|
+
ProductRoutingModule,
|
|
3030
|
+
SearchableSelectorModule,
|
|
3031
|
+
TimelineFilterModule,
|
|
3032
|
+
StockReceiptFormModule,
|
|
3033
|
+
StockIssueFormModule,
|
|
3034
|
+
ImportCsvModule,
|
|
3035
|
+
StockReceiptsModule,
|
|
3036
|
+
StockIssuancesListModule,
|
|
3037
|
+
ProductTaxModule,
|
|
3038
|
+
MaterialModule$1,
|
|
3039
|
+
MatProgressBarModule,
|
|
3040
|
+
InfiniteScrollModule,
|
|
3041
|
+
FlexModule,
|
|
3042
|
+
ReactiveFormsModule,
|
|
3043
|
+
FormsModule,
|
|
3044
|
+
ColumnSelectorModule,
|
|
3045
|
+
ProductLocationListComponent,
|
|
3046
|
+
StockTransferListComponent
|
|
3047
|
+
],
|
|
3048
|
+
exports: [
|
|
3049
|
+
ProductFormComponent,
|
|
3050
|
+
ProductBasicInfoComponent,
|
|
3051
|
+
ProductFormButtonComponent,
|
|
3052
|
+
],
|
|
3053
|
+
}]
|
|
3054
|
+
}] });
|
|
3055
|
+
|
|
3056
|
+
var product_module = /*#__PURE__*/Object.freeze({
|
|
3057
|
+
__proto__: null,
|
|
3058
|
+
ProductModule: ProductModule
|
|
3059
|
+
});
|
|
3060
|
+
|
|
3061
|
+
class ProductQuickSearchComponent extends TechlifyListingControllerInterface {
|
|
3062
|
+
productService;
|
|
3063
|
+
displayedColumns = ['#', 'Product', 'SKU', 'On Hand', 'Actions'];
|
|
3064
|
+
searchControl = new FormControl('');
|
|
3065
|
+
constructor(productService) {
|
|
3066
|
+
super();
|
|
3067
|
+
this.productService = productService;
|
|
3068
|
+
this.lastPage = 0;
|
|
3069
|
+
this.perPage = 1000;
|
|
3070
|
+
}
|
|
3071
|
+
ngOnInit() {
|
|
3072
|
+
this.loadData();
|
|
3073
|
+
this.searchControl.valueChanges.pipe(debounceTime$1(500)).subscribe(() => this.reload());
|
|
3074
|
+
}
|
|
3075
|
+
loadData() {
|
|
3076
|
+
const params = {
|
|
3077
|
+
page: this.page,
|
|
3078
|
+
perPage: this.perPage,
|
|
3079
|
+
search: this.searchControl.value,
|
|
3080
|
+
sort_by: 'created_at|desc',
|
|
3081
|
+
with: 'type,categories',
|
|
3082
|
+
};
|
|
3083
|
+
this.isWorking = true;
|
|
3084
|
+
this.productService.index(params).subscribe({
|
|
3085
|
+
next: (response) => {
|
|
3086
|
+
this.models = this.models?.concat(response?.data);
|
|
3087
|
+
this.lastPage = response?.last_page;
|
|
3088
|
+
this.isWorking = false;
|
|
3089
|
+
},
|
|
3090
|
+
error: () => (this.isWorking = false),
|
|
3091
|
+
});
|
|
3092
|
+
}
|
|
3093
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductQuickSearchComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3094
|
+
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 mat-table [dataSource]=\"models\" class=\"w-100\" infiniteScroll [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\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 <div class=\"d-flex flex-column\">\n <a [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\n {{ element?.name }}\n </a>\n \n <div *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\">\n <span class=\"badge bg-secondary\" *ngFor=\"let category of element?.categories\">\n {{ category?.title }}\n </span>\n </div>\n </div>\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 <!-- 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 class=\"cursor-pointer\" matTooltip=\"View\"\n [routerLink]=\"['/inventory/products', element.id, 'view']\" routerLinkActive=\"route-link-active\">\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button [product]=\"element\" (saved)=\"reload()\"></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button [product]=\"element\" (saved)=\"reload()\"></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>", 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 });
|
|
3095
|
+
}
|
|
3096
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductQuickSearchComponent, decorators: [{
|
|
3097
|
+
type: Component,
|
|
3098
|
+
args: [{ selector: 'app-product-quick-search', standalone: true, imports: [
|
|
3099
|
+
InfiniteScrollDirective,
|
|
3100
|
+
MatCard,
|
|
3101
|
+
MatCardContent,
|
|
3102
|
+
MatCell,
|
|
3103
|
+
MatCellDef,
|
|
3104
|
+
MatColumnDef,
|
|
3105
|
+
MatHeaderCell,
|
|
3106
|
+
MatHeaderRow,
|
|
3107
|
+
MatTable,
|
|
3108
|
+
MatHeaderCellDef,
|
|
3109
|
+
RouterLink,
|
|
3110
|
+
MatHeaderRowDef,
|
|
3111
|
+
MatRowDef,
|
|
3112
|
+
MatRow,
|
|
3113
|
+
MatProgressBar,
|
|
3114
|
+
NgIf,
|
|
3115
|
+
MatFormField,
|
|
3116
|
+
MatLabel,
|
|
3117
|
+
MatInput,
|
|
3118
|
+
ReactiveFormsModule,
|
|
3119
|
+
NgForOf,
|
|
3120
|
+
MatSortHeader,
|
|
3121
|
+
MatIcon,
|
|
3122
|
+
MatTooltip,
|
|
3123
|
+
ProductModule,
|
|
3124
|
+
RouterLinkActive,
|
|
3125
|
+
StockReceiptFormModule,
|
|
3126
|
+
StockIssueFormModule,
|
|
3127
|
+
], 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 mat-table [dataSource]=\"models\" class=\"w-100\" infiniteScroll [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\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 <div class=\"d-flex flex-column\">\n <a [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\n {{ element?.name }}\n </a>\n \n <div *ngIf=\"element?.categories?.length > 0\"\n class=\"d-flex justify-content-start align-items-center gap-1 flex-wrap\">\n <span class=\"badge bg-secondary\" *ngFor=\"let category of element?.categories\">\n {{ category?.title }}\n </span>\n </div>\n </div>\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 <!-- 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 class=\"cursor-pointer\" matTooltip=\"View\"\n [routerLink]=\"['/inventory/products', element.id, 'view']\" routerLinkActive=\"route-link-active\">\n remove_red_eye\n </mat-icon>\n\n <app-stock-receipt-form-button [product]=\"element\" (saved)=\"reload()\"></app-stock-receipt-form-button>\n\n <app-stock-issue-form-button [product]=\"element\" (saved)=\"reload()\"></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>" }]
|
|
3128
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
3129
|
+
|
|
3130
|
+
class InventoryDashboardPageComponent {
|
|
3131
|
+
productService;
|
|
3132
|
+
lowStockProductsCount;
|
|
3133
|
+
stockReceiptsQtySum;
|
|
3134
|
+
stockIssuanceQtySum;
|
|
3135
|
+
constructor(productService) {
|
|
3136
|
+
this.productService = productService;
|
|
3137
|
+
}
|
|
3138
|
+
ngOnInit() {
|
|
3139
|
+
this.loadProductSummary();
|
|
3140
|
+
}
|
|
3141
|
+
loadProductSummary() {
|
|
3142
|
+
const params = {
|
|
3143
|
+
include: 'low_stock_products_count,stock_receipts_quantity_sum,stock_issuances_quantity_sum',
|
|
3144
|
+
date_from: moment().startOf('month').format('YYYY-MM-DD'),
|
|
3145
|
+
date_to: moment().endOf('month').format('YYYY-MM-DD'),
|
|
3146
|
+
};
|
|
3147
|
+
this.productService.summary(params).subscribe({
|
|
3148
|
+
next: (response) => {
|
|
3149
|
+
this.lowStockProductsCount = response?.low_stock_products_count;
|
|
3150
|
+
this.stockReceiptsQtySum = response?.stock_receipts_quantity_sum;
|
|
3151
|
+
this.stockIssuanceQtySum = response?.stock_issuances_quantity_sum;
|
|
3152
|
+
},
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryDashboardPageComponent, deps: [{ token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3156
|
+
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\"> inventory_2 </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\"> arrow_circle_down </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\"> arrow_circle_up </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\"> description </span>\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <span class=\"material-symbols-outlined\"> chevron_forward </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\"> description </span>\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <span class=\"material-symbols-outlined\"> chevron_forward </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: i8.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 });
|
|
3157
|
+
}
|
|
3158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryDashboardPageComponent, decorators: [{
|
|
3159
|
+
type: Component,
|
|
3160
|
+
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\"> inventory_2 </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\"> arrow_circle_down </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\"> arrow_circle_up </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\"> description </span>\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <span class=\"material-symbols-outlined\"> chevron_forward </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\"> description </span>\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <span class=\"material-symbols-outlined\"> chevron_forward </span>\n </a>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n" }]
|
|
3161
|
+
}], ctorParameters: () => [{ type: ProductService }] });
|
|
3162
|
+
|
|
3163
|
+
class LowStockReportService extends TechlifyServiceBaseClass {
|
|
3164
|
+
httpService;
|
|
3165
|
+
constructor(httpService) {
|
|
3166
|
+
super(httpService, 'reports/low-stock-report');
|
|
3167
|
+
this.httpService = httpService;
|
|
3168
|
+
}
|
|
3169
|
+
export(params) {
|
|
3170
|
+
return this.http.get('api/reports/low-stock-report/export', { params });
|
|
3171
|
+
}
|
|
3172
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3173
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, providedIn: 'root' });
|
|
3174
|
+
}
|
|
3175
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportService, decorators: [{
|
|
3176
|
+
type: Injectable,
|
|
3177
|
+
args: [{
|
|
3178
|
+
providedIn: 'root',
|
|
3179
|
+
}]
|
|
3180
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
3181
|
+
|
|
3182
|
+
class LowStockReportComponent extends TechlifyListingControllerInterface {
|
|
3183
|
+
service;
|
|
3184
|
+
activatedRoute;
|
|
3185
|
+
requestHelperService;
|
|
3186
|
+
formBuilder;
|
|
3187
|
+
displayedColumns = [
|
|
3188
|
+
'#',
|
|
3189
|
+
'Product',
|
|
3190
|
+
'Type',
|
|
3191
|
+
'Categories',
|
|
3192
|
+
'Reorder Point',
|
|
3193
|
+
'Stock',
|
|
3194
|
+
'Last Purchase',
|
|
3195
|
+
'30d Issues',
|
|
3196
|
+
'30d Receipts',
|
|
3197
|
+
'60d Issues',
|
|
3198
|
+
'60d Receipts',
|
|
3199
|
+
'90d Issues',
|
|
3200
|
+
'90d Receipts',
|
|
3201
|
+
'1y Issues',
|
|
3202
|
+
'1y Receipts',
|
|
3203
|
+
];
|
|
3204
|
+
totalInventoryValue = 0;
|
|
3205
|
+
isExporting = false;
|
|
3206
|
+
constructor(service, activatedRoute, requestHelperService, formBuilder) {
|
|
3207
|
+
super();
|
|
3208
|
+
this.service = service;
|
|
3209
|
+
this.activatedRoute = activatedRoute;
|
|
3210
|
+
this.requestHelperService = requestHelperService;
|
|
3211
|
+
this.formBuilder = formBuilder;
|
|
3212
|
+
this.filterForm = this.formBuilder.group({
|
|
3213
|
+
category_ids: [''],
|
|
3214
|
+
search: [''],
|
|
3215
|
+
sort_by: ['id|desc'],
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3218
|
+
ngOnInit() {
|
|
3219
|
+
this.updateFormWithQueryParams();
|
|
3220
|
+
this.subscribeToFormChanges();
|
|
3221
|
+
this.subscribeToRouteChanges();
|
|
3222
|
+
}
|
|
3223
|
+
loadData() {
|
|
3224
|
+
const params = {
|
|
3225
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
3226
|
+
page: this.page,
|
|
3227
|
+
perPage: this.perPage,
|
|
3228
|
+
with: 'categories,lastStockReceipt,type,measure',
|
|
3229
|
+
};
|
|
3230
|
+
this.isWorking = true;
|
|
3231
|
+
this.service.index(params).subscribe({
|
|
3232
|
+
next: (response) => {
|
|
3233
|
+
this.models = this.models?.concat(response?.data);
|
|
3234
|
+
this.isWorking = false;
|
|
3235
|
+
this.models.forEach((model) => {
|
|
3236
|
+
this.totalInventoryValue += model?.inventory_value;
|
|
3237
|
+
});
|
|
3238
|
+
},
|
|
3239
|
+
error: () => (this.isWorking = false),
|
|
3240
|
+
});
|
|
3241
|
+
}
|
|
3242
|
+
onSortChange(sort) {
|
|
3243
|
+
let { active, direction } = sort;
|
|
3244
|
+
if (!active)
|
|
3245
|
+
active = 'id';
|
|
3246
|
+
if (!direction)
|
|
3247
|
+
direction = 'desc';
|
|
3248
|
+
this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
|
|
3249
|
+
}
|
|
3250
|
+
export() {
|
|
3251
|
+
const params = {
|
|
3252
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
3253
|
+
page: this.page,
|
|
3254
|
+
perPage: 50000,
|
|
3255
|
+
with: 'categories,lastStockReceipt',
|
|
3256
|
+
};
|
|
3257
|
+
this.isExporting = true;
|
|
3258
|
+
this.service.export(params).subscribe({
|
|
3259
|
+
next: (response) => {
|
|
3260
|
+
this.isExporting = false;
|
|
3261
|
+
window.open(response?.item?.file_link, '_blank');
|
|
3262
|
+
},
|
|
3263
|
+
error: () => (this.isExporting = false),
|
|
3264
|
+
});
|
|
3265
|
+
}
|
|
3266
|
+
updateFormWithQueryParams() {
|
|
3267
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
3268
|
+
category_ids: { multiple: true },
|
|
3269
|
+
});
|
|
3270
|
+
}
|
|
3271
|
+
subscribeToFormChanges() {
|
|
3272
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
3273
|
+
next: () => {
|
|
3274
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
3275
|
+
},
|
|
3276
|
+
});
|
|
3277
|
+
}
|
|
3278
|
+
subscribeToRouteChanges() {
|
|
3279
|
+
this.activatedRoute.queryParams.pipe(debounceTime$1(500), distinctUntilChanged()).subscribe(() => {
|
|
3280
|
+
this.reload();
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
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 });
|
|
3284
|
+
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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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>Last Purchase</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 }} - {{ element?.last_stock_receipt?.quantity }}\n {{ 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 });
|
|
3285
|
+
}
|
|
3286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportComponent, decorators: [{
|
|
3287
|
+
type: Component,
|
|
3288
|
+
args: [{ selector: 'app-low-stock-report', standalone: true, imports: [
|
|
3289
|
+
CurrencyPipe,
|
|
3290
|
+
FormsModule,
|
|
3291
|
+
InfiniteScrollDirective,
|
|
3292
|
+
MatCard,
|
|
3293
|
+
MatCardContent,
|
|
3294
|
+
MatCell,
|
|
3295
|
+
MatCellDef,
|
|
3296
|
+
MatColumnDef,
|
|
3297
|
+
MatFooterCell,
|
|
3298
|
+
MatFooterRow,
|
|
3299
|
+
MatFooterRowDef,
|
|
3300
|
+
MatFormField,
|
|
3301
|
+
MatHeaderCell,
|
|
3302
|
+
MatHeaderRow,
|
|
3303
|
+
MatHeaderRowDef,
|
|
3304
|
+
MatInput,
|
|
3305
|
+
MatLabel,
|
|
3306
|
+
MatProgressBar,
|
|
3307
|
+
MatRow,
|
|
3308
|
+
MatRowDef,
|
|
3309
|
+
MatSort,
|
|
3310
|
+
MatSortHeader,
|
|
3311
|
+
MatTable,
|
|
3312
|
+
NgIf,
|
|
3313
|
+
ProductCategoryBadgesComponent,
|
|
3314
|
+
ReactiveFormsModule,
|
|
3315
|
+
SearchableSelectorModule,
|
|
3316
|
+
RouterLink,
|
|
3317
|
+
MatFooterCellDef,
|
|
3318
|
+
MatHeaderCellDef,
|
|
3319
|
+
MatFooterCellDef,
|
|
3320
|
+
MatHeaderCellDef,
|
|
3321
|
+
MatHeaderCellDef,
|
|
3322
|
+
DatePipe,
|
|
3323
|
+
], 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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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>Last Purchase</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 }} - {{ element?.last_stock_receipt?.quantity }}\n {{ 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" }]
|
|
3324
|
+
}], ctorParameters: () => [{ type: LowStockReportService }, { type: i2.ActivatedRoute }, { type: i1.RequestHelperService }, { type: i2$2.FormBuilder }] });
|
|
3325
|
+
|
|
3326
|
+
class InventoryValueReportService extends TechlifyServiceBaseClass {
|
|
3327
|
+
constructor(httpService) {
|
|
3328
|
+
super(httpService, 'reports/inventory-value-report');
|
|
3329
|
+
}
|
|
3330
|
+
export(params) {
|
|
3331
|
+
return this.http.get('api/reports/inventory-value-report/export', { params });
|
|
3332
|
+
}
|
|
3333
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3334
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, providedIn: 'root' });
|
|
3335
|
+
}
|
|
3336
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportService, decorators: [{
|
|
3337
|
+
type: Injectable,
|
|
3338
|
+
args: [{
|
|
3339
|
+
providedIn: 'root',
|
|
3340
|
+
}]
|
|
3341
|
+
}], ctorParameters: () => [{ type: i1.HttpService }] });
|
|
3342
|
+
|
|
3343
|
+
class InventoryValueReportComponent extends TechlifyListingControllerInterface {
|
|
3344
|
+
service;
|
|
3345
|
+
activatedRoute;
|
|
3346
|
+
requestHelperService;
|
|
3347
|
+
formBuilder;
|
|
3348
|
+
displayedColumns = [
|
|
3349
|
+
'#',
|
|
3350
|
+
'Product',
|
|
3351
|
+
'Description',
|
|
3352
|
+
'Categories',
|
|
3353
|
+
'Available Stock',
|
|
3354
|
+
'Average Price',
|
|
3355
|
+
'Inventory Value',
|
|
3356
|
+
'Last Purchase Price',
|
|
3357
|
+
'Inventory Value Based On Last Purchase Price',
|
|
3358
|
+
];
|
|
3359
|
+
totalInventoryValue = 0;
|
|
3360
|
+
isExporting = false;
|
|
3361
|
+
constructor(service, activatedRoute, requestHelperService, formBuilder) {
|
|
3362
|
+
super();
|
|
3363
|
+
this.service = service;
|
|
3364
|
+
this.activatedRoute = activatedRoute;
|
|
3365
|
+
this.requestHelperService = requestHelperService;
|
|
3366
|
+
this.formBuilder = formBuilder;
|
|
3367
|
+
this.filterForm = this.formBuilder.group({
|
|
3368
|
+
category_ids: [''],
|
|
3369
|
+
search: [''],
|
|
3370
|
+
sort_by: ['id|desc'],
|
|
3371
|
+
});
|
|
3372
|
+
}
|
|
3373
|
+
ngOnInit() {
|
|
3374
|
+
this.updateFormWithQueryParams();
|
|
3375
|
+
this.subscribeToFormChanges();
|
|
3376
|
+
this.subscribeToRouteChanges();
|
|
3377
|
+
}
|
|
3378
|
+
loadData() {
|
|
3379
|
+
const params = {
|
|
3380
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
3381
|
+
page: this.page,
|
|
3382
|
+
perPage: this.perPage,
|
|
3383
|
+
with: 'categories,lastStockReceipt',
|
|
3384
|
+
};
|
|
3385
|
+
this.isWorking = true;
|
|
3386
|
+
this.service.index(params).subscribe({
|
|
3387
|
+
next: (response) => {
|
|
3388
|
+
this.models = this.models?.concat(response?.data);
|
|
3389
|
+
this.isWorking = false;
|
|
3390
|
+
this.models.forEach((model) => {
|
|
3391
|
+
this.totalInventoryValue += model?.inventory_value;
|
|
3392
|
+
});
|
|
3393
|
+
},
|
|
3394
|
+
error: () => (this.isWorking = false),
|
|
3395
|
+
});
|
|
3396
|
+
}
|
|
3397
|
+
updateFormWithQueryParams() {
|
|
3398
|
+
this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
|
|
3399
|
+
category_ids: { multiple: true },
|
|
3400
|
+
});
|
|
3401
|
+
}
|
|
3402
|
+
subscribeToFormChanges() {
|
|
3403
|
+
this.filterForm.valueChanges.pipe(debounceTime$1(800)).subscribe({
|
|
3404
|
+
next: () => {
|
|
3405
|
+
this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
|
|
3406
|
+
},
|
|
3407
|
+
});
|
|
3408
|
+
}
|
|
3409
|
+
subscribeToRouteChanges() {
|
|
3410
|
+
this.activatedRoute.queryParams.pipe(debounceTime$1(500), distinctUntilChanged()).subscribe(() => {
|
|
3411
|
+
this.reload();
|
|
3412
|
+
});
|
|
3413
|
+
}
|
|
3414
|
+
onSortChange(sort) {
|
|
3415
|
+
let { active, direction } = sort;
|
|
3416
|
+
if (!active)
|
|
3417
|
+
active = 'id';
|
|
3418
|
+
if (!direction)
|
|
3419
|
+
direction = 'desc';
|
|
3420
|
+
this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
|
|
3421
|
+
}
|
|
3422
|
+
export(type = 'excel') {
|
|
3423
|
+
const params = {
|
|
3424
|
+
...this.requestHelperService.convertToFormData(this.filterForm.value),
|
|
3425
|
+
page: this.page,
|
|
3426
|
+
perPage: 50000,
|
|
3427
|
+
with: 'categories,lastStockReceipt',
|
|
3428
|
+
export_type: type,
|
|
3429
|
+
};
|
|
3430
|
+
this.isExporting = true;
|
|
3431
|
+
this.service.export(params).subscribe({
|
|
3432
|
+
next: (response) => {
|
|
3433
|
+
this.isExporting = false;
|
|
3434
|
+
window.open(response?.item?.file_link, '_blank');
|
|
3435
|
+
},
|
|
3436
|
+
error: () => (this.isExporting = false),
|
|
3437
|
+
});
|
|
3438
|
+
}
|
|
3439
|
+
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 });
|
|
3440
|
+
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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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?.inventory_value_based_on_last_price ?? 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 });
|
|
3441
|
+
}
|
|
3442
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportComponent, decorators: [{
|
|
3443
|
+
type: Component,
|
|
3444
|
+
args: [{ selector: 'app-inventory-value-report', standalone: true, imports: [
|
|
3445
|
+
MatCard,
|
|
3446
|
+
MatCardContent,
|
|
3447
|
+
MatTable,
|
|
3448
|
+
MatColumnDef,
|
|
3449
|
+
MatColumnDef,
|
|
3450
|
+
MatCellDef,
|
|
3451
|
+
MatRow,
|
|
3452
|
+
MatCellDef,
|
|
3453
|
+
MatHeaderCell,
|
|
3454
|
+
MatCell,
|
|
3455
|
+
MatRowDef,
|
|
3456
|
+
MatCellDef,
|
|
3457
|
+
MatHeaderCell,
|
|
3458
|
+
MatColumnDef,
|
|
3459
|
+
MatCell,
|
|
3460
|
+
MatColumnDef,
|
|
3461
|
+
MatHeaderCell,
|
|
3462
|
+
MatHeaderRowDef,
|
|
3463
|
+
MatHeaderCell,
|
|
3464
|
+
MatCell,
|
|
3465
|
+
MatHeaderRow,
|
|
3466
|
+
MatCell,
|
|
3467
|
+
MatCellDef,
|
|
3468
|
+
MatHeaderCellDef,
|
|
3469
|
+
MatHeaderCellDef,
|
|
3470
|
+
MatHeaderCellDef,
|
|
3471
|
+
MatHeaderCellDef,
|
|
3472
|
+
RouterLink,
|
|
3473
|
+
ProductCategoryBadgesComponent,
|
|
3474
|
+
CurrencyPipe,
|
|
3475
|
+
MatProgressBar,
|
|
3476
|
+
NgIf,
|
|
3477
|
+
MatFooterRowDef,
|
|
3478
|
+
MatFooterRow,
|
|
3479
|
+
MatFooterCellDef,
|
|
3480
|
+
MatFooterCell,
|
|
3481
|
+
MatFormField,
|
|
3482
|
+
MatLabel,
|
|
3483
|
+
ReactiveFormsModule,
|
|
3484
|
+
SearchableSelectorModule,
|
|
3485
|
+
MatInput,
|
|
3486
|
+
InfiniteScrollDirective,
|
|
3487
|
+
MatSort,
|
|
3488
|
+
MatSortHeader,
|
|
3489
|
+
], 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 apiUrl=\"api/product-categories\" formControlName=\"category_ids\" [multiple]=\"true\">\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\n [dataSource]=\"models\"\n class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n (scrolled)=\"onScroll()\"\n matSort\n (matSortChange)=\"onSortChange($event)\"\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 [routerLink]=\"['/inventory/products', element?.id, 'view']\" class=\"text-dark\">\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?.inventory_value_based_on_last_price ?? 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" }]
|
|
3490
|
+
}], ctorParameters: () => [{ type: InventoryValueReportService }, { type: i2.ActivatedRoute }, { type: i1.RequestHelperService }, { type: i2$2.FormBuilder }] });
|
|
3491
|
+
|
|
3492
|
+
const routes = [
|
|
3493
|
+
{
|
|
3494
|
+
path: 'reports/low-stock-report',
|
|
3495
|
+
component: LowStockReportComponent,
|
|
3496
|
+
},
|
|
3497
|
+
{
|
|
3498
|
+
path: 'reports/inventory-value-report',
|
|
3499
|
+
component: InventoryValueReportComponent,
|
|
3500
|
+
},
|
|
3501
|
+
{
|
|
3502
|
+
path: 'suppliers',
|
|
3503
|
+
loadChildren: () => import('./techlify-inventory-common-supplier.module-CYq-2pV1.mjs').then((m) => m.SupplierModule),
|
|
3504
|
+
},
|
|
3505
|
+
{
|
|
3506
|
+
path: 'locations',
|
|
3507
|
+
loadChildren: () => import('./techlify-inventory-common-location.module-Cwx9mHKE.mjs').then((mod) => mod.LocationModule),
|
|
3508
|
+
},
|
|
3509
|
+
{
|
|
3510
|
+
path: "measures",
|
|
3511
|
+
loadChildren: () => import('./techlify-inventory-common-measure.module-C2v0-n_m.mjs').then((mod) => mod.MeasureModule),
|
|
3512
|
+
},
|
|
3513
|
+
{
|
|
3514
|
+
path: 'stock-issuances',
|
|
3515
|
+
loadChildren: () => import('./techlify-inventory-common-stock-issuances.module-CPccetrp.mjs').then((mod) => mod.StockIssuancesModule),
|
|
3516
|
+
},
|
|
3517
|
+
{
|
|
3518
|
+
path: 'stock-receipts',
|
|
3519
|
+
loadChildren: () => Promise.resolve().then(function () { return stockReceipts_module; }).then((mod) => mod.StockReceiptsModule),
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
path: 'categories',
|
|
3523
|
+
loadChildren: () => import('./techlify-inventory-common-category.module-BsvJ6rVx.mjs').then((mod) => mod.CategoryModule),
|
|
3524
|
+
},
|
|
3525
|
+
{
|
|
3526
|
+
path: 'products',
|
|
3527
|
+
loadChildren: () => Promise.resolve().then(function () { return product_module; }).then((mod) => mod.ProductModule),
|
|
3528
|
+
},
|
|
3529
|
+
{
|
|
3530
|
+
path: 'dashboard',
|
|
3531
|
+
component: InventoryDashboardPageComponent,
|
|
3532
|
+
},
|
|
3533
|
+
{
|
|
3534
|
+
path: '**',
|
|
3535
|
+
redirectTo: 'dashboard',
|
|
3536
|
+
pathMatch: 'full',
|
|
3537
|
+
},
|
|
3538
|
+
];
|
|
3539
|
+
class InventoryCommonRoutingModule {
|
|
3540
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3541
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, imports: [i2.RouterModule], exports: [RouterModule] });
|
|
3542
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
|
|
3543
|
+
}
|
|
3544
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonRoutingModule, decorators: [{
|
|
3545
|
+
type: NgModule,
|
|
3546
|
+
args: [{
|
|
3547
|
+
imports: [RouterModule.forChild(routes)],
|
|
3548
|
+
exports: [RouterModule],
|
|
3549
|
+
}]
|
|
3550
|
+
}] });
|
|
3551
|
+
|
|
3552
|
+
class LowStockProductsWidgetModule {
|
|
3553
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3554
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, declarations: [LowStockProductsWidgetComponent], imports: [CommonModule, MaterialModule$1, InfiniteScrollModule, MatProgressBarModule, RouterModule], exports: [LowStockProductsWidgetComponent] });
|
|
3555
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, imports: [CommonModule, MaterialModule$1, InfiniteScrollModule, MatProgressBarModule, RouterModule] });
|
|
3556
|
+
}
|
|
3557
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockProductsWidgetModule, decorators: [{
|
|
3558
|
+
type: NgModule,
|
|
3559
|
+
args: [{
|
|
3560
|
+
declarations: [LowStockProductsWidgetComponent],
|
|
3561
|
+
imports: [CommonModule, MaterialModule$1, InfiniteScrollModule, MatProgressBarModule, RouterModule],
|
|
3562
|
+
exports: [LowStockProductsWidgetComponent],
|
|
3563
|
+
}]
|
|
3564
|
+
}] });
|
|
3565
|
+
|
|
3566
|
+
class ProductSummaryChartModule {
|
|
3567
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3568
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, imports: [CommonModule, MaterialModule$1, MatProgressBarModule, GoogleChartsModule] });
|
|
3569
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, imports: [CommonModule, MaterialModule$1, MatProgressBarModule, GoogleChartsModule] });
|
|
3570
|
+
}
|
|
3571
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductSummaryChartModule, decorators: [{
|
|
3572
|
+
type: NgModule,
|
|
3573
|
+
args: [{
|
|
3574
|
+
imports: [CommonModule, MaterialModule$1, MatProgressBarModule, GoogleChartsModule],
|
|
3575
|
+
}]
|
|
3576
|
+
}] });
|
|
3577
|
+
|
|
3578
|
+
class InventoryCommonModule {
|
|
3579
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3580
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, declarations: [InventoryDashboardPageComponent], imports: [CommonModule,
|
|
3581
|
+
InventoryCommonRoutingModule,
|
|
3582
|
+
MaterialModule$1,
|
|
3583
|
+
LowStockProductsWidgetModule,
|
|
3584
|
+
ProductSummaryChartModule,
|
|
3585
|
+
ProductSummaryChartComponent,
|
|
3586
|
+
ProductQuickSearchComponent] });
|
|
3587
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, imports: [CommonModule,
|
|
3588
|
+
InventoryCommonRoutingModule,
|
|
3589
|
+
MaterialModule$1,
|
|
3590
|
+
LowStockProductsWidgetModule,
|
|
3591
|
+
ProductSummaryChartModule,
|
|
3592
|
+
ProductSummaryChartComponent,
|
|
3593
|
+
ProductQuickSearchComponent] });
|
|
3594
|
+
}
|
|
3595
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryCommonModule, decorators: [{
|
|
3596
|
+
type: NgModule,
|
|
3597
|
+
args: [{
|
|
3598
|
+
declarations: [InventoryDashboardPageComponent],
|
|
3599
|
+
imports: [
|
|
3600
|
+
CommonModule,
|
|
3601
|
+
InventoryCommonRoutingModule,
|
|
3602
|
+
MaterialModule$1,
|
|
3603
|
+
LowStockProductsWidgetModule,
|
|
3604
|
+
ProductSummaryChartModule,
|
|
3605
|
+
ProductSummaryChartComponent,
|
|
3606
|
+
ProductQuickSearchComponent,
|
|
3607
|
+
],
|
|
3608
|
+
}]
|
|
3609
|
+
}] });
|
|
3610
|
+
|
|
3611
|
+
/*
|
|
3612
|
+
* Public API Surface of inventory-common
|
|
3613
|
+
*/
|
|
3614
|
+
|
|
3615
|
+
/**
|
|
3616
|
+
* Generated bundle index. Do not edit.
|
|
3617
|
+
*/
|
|
3618
|
+
|
|
3619
|
+
export { InventoryCommonRoutingModule as I, MaterialModule as M, ProductModule as P, SupplierFormComponent as S, TechlifyFormService as T, SupplierService as a, ProductCategoryBadgesComponent as b, StockTransferFormButtonComponent as c, TechlifyFilterComponent as d, TechlifyFilterModule as e, StockIssuancesListComponent as f, StockReceiptFormModule as g, StockIssueFormModule as h, StockIssuancesListModule as i, InventoryCommonModule as j, StockSummaryService as k };
|
|
3620
|
+
//# sourceMappingURL=techlify-inventory-common-techlify-inventory-common-BMNkSTd6.mjs.map
|