tin-spa 20.3.1 → 20.3.2
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/fesm2022/tin-spa.mjs +447 -74
- package/fesm2022/tin-spa.mjs.map +1 -1
- package/index.d.ts +39 -2
- package/package.json +1 -1
package/fesm2022/tin-spa.mjs
CHANGED
|
@@ -683,8 +683,17 @@ class DetailsDialogProcessor {
|
|
|
683
683
|
}
|
|
684
684
|
function transformStepUrl(stepConfig) {
|
|
685
685
|
if (stepConfig.loadAction && stepConfig.loadIDField) {
|
|
686
|
-
//
|
|
687
|
-
|
|
686
|
+
// Changed: Support generic {propertyName} placeholders
|
|
687
|
+
if (stepConfig.loadAction.url.includes('{')) {
|
|
688
|
+
stepConfig.loadAction.url = stepConfig.loadAction.url.replace(/\{(\w+)\}/g, (match, propName) => {
|
|
689
|
+
const value = updatedDetailsConfig.details?.[propName];
|
|
690
|
+
return value !== undefined && value !== null ? String(value) : match;
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
// Fallback to legacy {id} replacement for backward compatibility
|
|
695
|
+
stepConfig.loadAction.url = `${stepConfig.loadAction.url.replace('{id}', updatedDetailsConfig.details[stepConfig.loadIDField])}`;
|
|
696
|
+
}
|
|
688
697
|
// console.log("Transformed step URL", stepConfig.loadAction.url);
|
|
689
698
|
}
|
|
690
699
|
}
|
|
@@ -755,7 +764,16 @@ class DetailsDialogProcessor {
|
|
|
755
764
|
static loadDetailsFromUrl(detailsConfig, formConfig) {
|
|
756
765
|
let action;
|
|
757
766
|
if (formConfig.loadAction) {
|
|
758
|
-
if
|
|
767
|
+
// Changed: Check if URL contains {propertyName} placeholders first - takes priority over hero field
|
|
768
|
+
if (formConfig.loadAction.url.includes('{') && detailsConfig.details) {
|
|
769
|
+
const transformedUrl = formConfig.loadAction.url.replace(/\{(\w+)\}/g, (match, propName) => {
|
|
770
|
+
const value = detailsConfig.details?.[propName];
|
|
771
|
+
return value !== undefined && value !== null ? String(value) : match;
|
|
772
|
+
});
|
|
773
|
+
action = { url: transformedUrl };
|
|
774
|
+
console.log("Transformed form URL (placeholder)", transformedUrl);
|
|
775
|
+
}
|
|
776
|
+
else if (detailsConfig.heroField && detailsConfig.details) {
|
|
759
777
|
// console.log("DetailsConfig Hero ID Field " + detailsConfig.heroField);
|
|
760
778
|
action = { url: `${formConfig.loadAction.url}/${detailsConfig.details[detailsConfig.heroField]}` };
|
|
761
779
|
}
|
|
@@ -802,6 +820,19 @@ var InvoiceStatus;
|
|
|
802
820
|
InvoiceStatus[InvoiceStatus["Discarded"] = 3] = "Discarded";
|
|
803
821
|
InvoiceStatus[InvoiceStatus["Paying"] = 4] = "Paying"; // Changed: Added Paying status for partially paid invoices
|
|
804
822
|
})(InvoiceStatus || (InvoiceStatus = {}));
|
|
823
|
+
// Added: Invoice item type enum - mirrors backend InvoiceItemType
|
|
824
|
+
var InvoiceItemType;
|
|
825
|
+
(function (InvoiceItemType) {
|
|
826
|
+
InvoiceItemType[InvoiceItemType["General"] = 0] = "General";
|
|
827
|
+
InvoiceItemType[InvoiceItemType["Product"] = 1] = "Product";
|
|
828
|
+
InvoiceItemType[InvoiceItemType["Service"] = 2] = "Service";
|
|
829
|
+
})(InvoiceItemType || (InvoiceItemType = {}));
|
|
830
|
+
// Transaction timing enum - separates WHEN payment occurs from HOW
|
|
831
|
+
var TransactionTiming;
|
|
832
|
+
(function (TransactionTiming) {
|
|
833
|
+
TransactionTiming[TransactionTiming["Immediate"] = 0] = "Immediate";
|
|
834
|
+
TransactionTiming[TransactionTiming["Deferred"] = 1] = "Deferred"; // Payment occurs later - creates AR/AP
|
|
835
|
+
})(TransactionTiming || (TransactionTiming = {}));
|
|
805
836
|
// Inventory receipt status tracking enum - mirrors backend
|
|
806
837
|
var InventoryReceiptStatus;
|
|
807
838
|
(function (InventoryReceiptStatus) {
|
|
@@ -1509,6 +1540,7 @@ class DataServiceLib {
|
|
|
1509
1540
|
this.capInventoryDashboard = new CapItem;
|
|
1510
1541
|
this.capInventoryStock = new CapItem; // Changed: Added new cap item for inventory stock view
|
|
1511
1542
|
this.capProducts = new CapItem;
|
|
1543
|
+
this.capServiceItems = new CapItem; // Added: Capability for service items
|
|
1512
1544
|
this.capBundleProducts = new CapItem; // Added: Capability for bundle products
|
|
1513
1545
|
this.capInventoryItems = new CapItem;
|
|
1514
1546
|
this.capPurchaseOrders = new CapItem;
|
|
@@ -2239,9 +2271,9 @@ class DataServiceLib {
|
|
|
2239
2271
|
this.capInventory.name = "cap34";
|
|
2240
2272
|
this.capInventory.display = "Inventory";
|
|
2241
2273
|
this.capInventory.icon = "inventory";
|
|
2242
|
-
this.capInventory.capSubItems = [this.capSales, this.capInventoryReceipts, this.capProducts, this.capBundleProducts, this.capInventoryStock, this.capInventoryTransactions, this.capInventoryItems,
|
|
2274
|
+
this.capInventory.capSubItems = [this.capSales, this.capInventoryReceipts, this.capProducts, this.capServiceItems, this.capBundleProducts, this.capInventoryStock, this.capInventoryTransactions, this.capInventoryItems,
|
|
2243
2275
|
this.capPurchaseOrders, this.capSalesOrders, this.capRequisitions, this.capInventoryAdjustments,
|
|
2244
|
-
this.capInventoryReturns, this.capRequisitionReturns, this.capProductionRecipes, this.capProductionOrders, this.capInventoryDashboard];
|
|
2276
|
+
this.capInventoryReturns, this.capRequisitionReturns, this.capProductionRecipes, this.capProductionOrders, this.capInventoryDashboard]; // Changed: Added capServiceItems to inventory menu
|
|
2245
2277
|
this.capInventoryDashboard.name = "cap35";
|
|
2246
2278
|
this.capInventoryDashboard.display = "Dashboard";
|
|
2247
2279
|
this.capInventoryDashboard.link = "home/admin/inventory-dashboard";
|
|
@@ -2254,6 +2286,10 @@ class DataServiceLib {
|
|
|
2254
2286
|
this.capProducts.display = "Products";
|
|
2255
2287
|
this.capProducts.link = "home/admin/inventory-products";
|
|
2256
2288
|
this.capProducts.icon = "category";
|
|
2289
|
+
this.capServiceItems.name = "cap59"; // Added: Service items capability
|
|
2290
|
+
this.capServiceItems.display = "Services";
|
|
2291
|
+
this.capServiceItems.link = "home/admin/inventory-service-items";
|
|
2292
|
+
this.capServiceItems.icon = "build";
|
|
2257
2293
|
this.capBundleProducts.name = "cap57"; // Added: Bundle products capability
|
|
2258
2294
|
this.capBundleProducts.display = "Bundle Products";
|
|
2259
2295
|
this.capBundleProducts.link = "home/admin/bundle-products";
|
|
@@ -2681,7 +2717,7 @@ class AccountingService {
|
|
|
2681
2717
|
loadAction: { url: 'accounts/id' },
|
|
2682
2718
|
heroField: 'accountID',
|
|
2683
2719
|
};
|
|
2684
|
-
this.accountCreateButton = { name: 'create', display: 'Create', dialog: true, action: { url: 'accounts?action=create', method: 'post' } };
|
|
2720
|
+
this.accountCreateButton = { name: 'create', display: 'Create Account', dialog: true, action: { url: 'accounts?action=create', method: 'post' } };
|
|
2685
2721
|
this.finAccounEditButton = { name: 'edit', dialog: true, action: { url: 'accounts?action=edit', method: 'post' } };
|
|
2686
2722
|
this.accountBaseDetailsConfig = {
|
|
2687
2723
|
formConfig: this.accountFormConfig,
|
|
@@ -2719,7 +2755,6 @@ class AccountingService {
|
|
|
2719
2755
|
showFilter: false,
|
|
2720
2756
|
minColumns: ['paymentDate', 'amount', 'methodName'],
|
|
2721
2757
|
columns: [
|
|
2722
|
-
{ name: 'invoicePaymentID', type: 'number', alias: 'ID', hiddenCondition: () => true },
|
|
2723
2758
|
{ name: 'paymentDate', type: 'date', alias: 'Date' },
|
|
2724
2759
|
{ name: 'amount', type: 'money', alias: 'Amount' },
|
|
2725
2760
|
{ name: 'methodName', type: 'text', alias: 'Method' },
|
|
@@ -2730,9 +2765,21 @@ class AccountingService {
|
|
|
2730
2765
|
action: { url: 'invoicepayments/migrate', method: 'post',
|
|
2731
2766
|
successMessage: 'Migration completed successfully' },
|
|
2732
2767
|
confirm: { message: 'This will migrate existing invoice payments from the legacy PaidAmount field to the new InvoicePayments table. Continue?' }
|
|
2733
|
-
}
|
|
2768
|
+
},
|
|
2769
|
+
{ name: 'edit', dialog: true, action: { url: 'invoicepayments?action=edit', method: 'post' }, visible: x => x.status != InvoiceStatus.Paid }, // Changed: Added edit button, hide on Paid invoices
|
|
2770
|
+
{ name: 'delete', inDialog: true, icon: { name: 'delete', color: 'red' }, action: { url: 'invoicepayments?action=delete', method: 'post', successMessage: 'Payment deleted' }, confirm: { message: 'Delete this payment? The linked financial transaction will be reversed.' }, visible: x => x.status != InvoiceStatus.Paid } // Changed: Added delete button with reversal warning, hide on Paid invoices
|
|
2734
2771
|
],
|
|
2735
|
-
loadAction: { url: 'invoicepayments/x/x' }, loadCriteria: 'invoice', loadIDField: 'invoiceID'
|
|
2772
|
+
loadAction: { url: 'invoicepayments/x/x' }, loadCriteria: 'invoice', loadIDField: 'invoiceID',
|
|
2773
|
+
formConfig: {
|
|
2774
|
+
title: 'Edit Payment',
|
|
2775
|
+
fields: [
|
|
2776
|
+
{ name: 'paymentDate', type: 'date', alias: 'Payment Date', required: true },
|
|
2777
|
+
{ name: 'method', type: 'select', alias: 'Payment Method', required: true, loadAction: { url: 'invoicepayments/list/methods' } },
|
|
2778
|
+
{ name: 'amount', type: 'money', alias: 'Amount', required: true },
|
|
2779
|
+
{ name: 'reference', type: 'text', alias: 'Reference' }
|
|
2780
|
+
],
|
|
2781
|
+
loadAction: { url: 'invoicepayments/id' }
|
|
2782
|
+
}
|
|
2736
2783
|
};
|
|
2737
2784
|
// Invoice form configuration with customer and status fields
|
|
2738
2785
|
this.invoiceFormConfig = {
|
|
@@ -2753,6 +2800,36 @@ class AccountingService {
|
|
|
2753
2800
|
loadAction: { url: 'invoices/id' },
|
|
2754
2801
|
heroField: 'invoiceID',
|
|
2755
2802
|
};
|
|
2803
|
+
// Invoice items form configuration
|
|
2804
|
+
this.invoiceItemsFormConfig = {
|
|
2805
|
+
title: 'Invoice Item',
|
|
2806
|
+
fields: [
|
|
2807
|
+
{ name: 'itemType', type: 'select', required: true, alias: 'Item Type', loadAction: { url: 'invoiceitems/list/item-types' }, defaultValue: 0 }, // Added: Item type selector
|
|
2808
|
+
{ name: 'productID', type: 'select', alias: 'Product', loadAction: { url: 'products/list/invoice-items' },
|
|
2809
|
+
hiddenCondition: x => x.itemType !== 1, // Added: Product selector - visible only when itemType = Product (1)
|
|
2810
|
+
onSelectChange: (selectedId, formData, option) => {
|
|
2811
|
+
if (option) {
|
|
2812
|
+
formData.description = option.description || option.name;
|
|
2813
|
+
formData.unitPrice = option.unitPrice;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
},
|
|
2817
|
+
{ name: 'serviceItemID', type: 'select', alias: 'Service', loadAction: { url: 'serviceitems/list/active' },
|
|
2818
|
+
hiddenCondition: x => x.itemType !== 2, // Added: Service selector - visible only when itemType = Service (2)
|
|
2819
|
+
onSelectChange: (selectedId, formData, option) => {
|
|
2820
|
+
if (option) {
|
|
2821
|
+
formData.description = option.description || option.name;
|
|
2822
|
+
formData.unitPrice = option.unitPrice;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
},
|
|
2826
|
+
{ name: 'description', type: 'text', required: true, alias: 'Description', span: true }, // Changed: Description field (backend will populate for Product/Service)
|
|
2827
|
+
{ name: 'quantity', type: 'number', required: true, defaultValue: 1 },
|
|
2828
|
+
{ name: 'unitPrice', type: 'money', alias: 'Unit Price', required: true }, // Changed: Unit price field (backend will populate for Product/Service)
|
|
2829
|
+
],
|
|
2830
|
+
loadAction: { url: 'invoiceitems/id/{invoiceItemID}' },
|
|
2831
|
+
heroField: 'invoiceItemID',
|
|
2832
|
+
};
|
|
2756
2833
|
// Invoice items table for manual line item entry
|
|
2757
2834
|
this.invoiceItemsTableConfig = {
|
|
2758
2835
|
tabTitle: 'Invoice Items',
|
|
@@ -2770,20 +2847,17 @@ class AccountingService {
|
|
|
2770
2847
|
{ name: 'create', display: 'Add Item', dialog: true, action: { url: 'invoiceitems?action=create', method: 'post' },
|
|
2771
2848
|
disabled: x => x.status != InvoiceStatus.Draft
|
|
2772
2849
|
},
|
|
2773
|
-
{ name: 'edit', dialog: true, action: { url: 'invoiceitems?action=edit', method: 'post' },
|
|
2774
|
-
|
|
2850
|
+
{ name: 'edit', dialog: true, action: { url: 'invoiceitems?action=edit', method: 'post' },
|
|
2851
|
+
disabled: x => x.status != InvoiceStatus.Draft
|
|
2852
|
+
},
|
|
2853
|
+
{ name: 'delete', inDialog: true, icon: { name: 'delete', color: 'red' }, action: { url: 'invoiceitems?action=delete', method: 'post',
|
|
2854
|
+
successMessage: 'Deleted' },
|
|
2855
|
+
confirm: { message: 'Delete this item?' },
|
|
2856
|
+
disabled: x => x.status != InvoiceStatus.Draft
|
|
2857
|
+
},
|
|
2775
2858
|
],
|
|
2776
2859
|
loadAction: { url: 'invoiceitems/x/x' }, loadCriteria: 'invoice', loadIDField: 'invoiceID',
|
|
2777
|
-
formConfig:
|
|
2778
|
-
title: 'Invoice Item',
|
|
2779
|
-
fields: [
|
|
2780
|
-
{ name: 'description', type: 'text', required: true, span: true },
|
|
2781
|
-
{ name: 'quantity', type: 'number', required: true, defaultValue: 1 },
|
|
2782
|
-
{ name: 'unitPrice', type: 'number', alias: 'Unit Price', required: true },
|
|
2783
|
-
{ name: 'amount', type: 'number', readonly: true, hideOnCreate: true }
|
|
2784
|
-
],
|
|
2785
|
-
loadAction: { url: 'invoiceitems/id' }
|
|
2786
|
-
}
|
|
2860
|
+
formConfig: this.invoiceItemsFormConfig // Changed: Reference extracted form config
|
|
2787
2861
|
};
|
|
2788
2862
|
// Invoice action buttons
|
|
2789
2863
|
this.invoiceRecordPaymentButton = { name: 'record-payment', display: 'Record Payment', dialog: true, icon: { name: 'payment', color: 'blue' },
|
|
@@ -2791,7 +2865,8 @@ class AccountingService {
|
|
|
2791
2865
|
visible: x => (x.status == InvoiceStatus.Submitted || x.status == InvoiceStatus.Paying) && x.outstandingAmount > 0 // Changed: Allow on both Submitted and Paying
|
|
2792
2866
|
}; // Changed: Use detailsConfig to open payment form dialog
|
|
2793
2867
|
this.invoiceDiscardButton = { name: 'discard', inDialog: true, display: 'Discard', icon: { name: 'close', color: 'red' },
|
|
2794
|
-
action: { url: 'invoices?action=discard', method: 'post', successMessage: 'Discarded' },
|
|
2868
|
+
action: { url: 'invoices?action=discard', method: 'post', successMessage: 'Discarded' },
|
|
2869
|
+
confirm: { message: 'Invoice will be marked as cancelled?' },
|
|
2795
2870
|
visible: x => x.status == InvoiceStatus.Draft || x.status == InvoiceStatus.Submitted // Changed: Only allow on Draft and Submitted
|
|
2796
2871
|
};
|
|
2797
2872
|
this.invoiceSubmitButton = { name: 'submit', inDialog: true, display: 'Submit', icon: { name: 'send', },
|
|
@@ -2800,8 +2875,9 @@ class AccountingService {
|
|
|
2800
2875
|
visible: x => x.status == InvoiceStatus.Draft,
|
|
2801
2876
|
disabled: x => x.totalAmount == 0
|
|
2802
2877
|
};
|
|
2803
|
-
this.invoiceEditButton = { name: 'edit', dialog: true, action: { url: 'invoices?action=edit', method: 'post', },
|
|
2804
|
-
|
|
2878
|
+
this.invoiceEditButton = { name: 'edit', dialog: true, action: { url: 'invoices?action=edit', method: 'post', },
|
|
2879
|
+
confirm: { message: 'Proceed ?' },
|
|
2880
|
+
visible: x => x.status == InvoiceStatus.Draft // Changed: Draft only
|
|
2805
2881
|
};
|
|
2806
2882
|
this.invoiceDownloadButton = { name: 'pdf', display: 'Download PDF', inDialog: true, icon: { name: 'picture_as_pdf', color: 'red' } };
|
|
2807
2883
|
// Invoice details dialog with items, payments history, and action buttons
|
|
@@ -2831,7 +2907,7 @@ class AccountingService {
|
|
|
2831
2907
|
collapseButtons: true,
|
|
2832
2908
|
greyOut: x => x.status == InvoiceStatus.Paid,
|
|
2833
2909
|
columns: [
|
|
2834
|
-
{ name: 'invoiceNumber', type: '
|
|
2910
|
+
{ name: 'invoiceNumber', type: 'button', alias: 'Invoice #', detailsConfig: this.invoiceDetailsDialogConfig },
|
|
2835
2911
|
{ name: 'customerName', type: 'text', alias: 'Customer' },
|
|
2836
2912
|
{ name: 'invoiceDate', type: 'date' },
|
|
2837
2913
|
{ name: 'dueDate', type: 'date', alias: 'Due Date' },
|
|
@@ -2851,14 +2927,16 @@ class AccountingService {
|
|
|
2851
2927
|
{ name: 'outstandingAmount', type: 'money', alias: 'Outstanding' }
|
|
2852
2928
|
],
|
|
2853
2929
|
buttons: [
|
|
2854
|
-
{ name: 'create', display: 'Create', dialog: true,
|
|
2855
|
-
|
|
2856
|
-
|
|
2930
|
+
{ name: 'create', display: 'Create', dialog: true, onSuccessButton: this.invoiceViewButton,
|
|
2931
|
+
action: { url: 'invoices?action=create', method: 'post' }
|
|
2932
|
+
},
|
|
2933
|
+
// { name: 'view', dialog: true, detailsConfig: this.invoiceDetailsDialogConfig },
|
|
2857
2934
|
this.invoiceSubmitButton,
|
|
2935
|
+
this.invoiceRecordPaymentButton,
|
|
2858
2936
|
// this.invoicePayButton,
|
|
2859
2937
|
this.invoiceDiscardButton,
|
|
2860
|
-
this.invoiceEditButton,
|
|
2861
|
-
this.invoiceDownloadButton,
|
|
2938
|
+
// this.invoiceEditButton,
|
|
2939
|
+
// this.invoiceDownloadButton,
|
|
2862
2940
|
],
|
|
2863
2941
|
loadAction: { url: 'invoices/all/x' },
|
|
2864
2942
|
formConfig: this.invoiceFormConfig,
|
|
@@ -2881,9 +2959,10 @@ class AccountingService {
|
|
|
2881
2959
|
// Added: Base aging table configuration with common properties
|
|
2882
2960
|
this.agingBaseTableConfig = {
|
|
2883
2961
|
showFilter: true,
|
|
2962
|
+
flatButtons: true,
|
|
2884
2963
|
minColumns: ['invoiceNumber', 'customerName', 'outstandingAmount'],
|
|
2885
2964
|
columns: [
|
|
2886
|
-
{ name: 'invoiceNumber', type: 'text', alias: 'Invoice #' },
|
|
2965
|
+
{ name: 'invoiceNumber', type: 'text', alias: 'Invoice #', detailsConfig: this.invoiceDetailsDialogConfig },
|
|
2887
2966
|
{ name: 'customerName', type: 'text', alias: 'Customer' },
|
|
2888
2967
|
{ name: 'invoiceDate', type: 'date', alias: 'Invoice Date' },
|
|
2889
2968
|
{ name: 'dueDate', type: 'date', alias: 'Due Date' },
|
|
@@ -2892,7 +2971,10 @@ class AccountingService {
|
|
|
2892
2971
|
{ name: 'paidAmount', type: 'money', alias: 'Paid' },
|
|
2893
2972
|
{ name: 'outstandingAmount', type: 'money', alias: 'Outstanding' }
|
|
2894
2973
|
],
|
|
2895
|
-
buttons: [
|
|
2974
|
+
buttons: [
|
|
2975
|
+
{ name: 'view', dialog: true, detailsConfig: this.invoiceDetailsDialogConfig },
|
|
2976
|
+
this.invoiceRecordPaymentButton,
|
|
2977
|
+
]
|
|
2896
2978
|
};
|
|
2897
2979
|
//--------------------------Customer Invoices-------------------------
|
|
2898
2980
|
// Customer invoice form without customerID field
|
|
@@ -3072,15 +3154,15 @@ class AccountingService {
|
|
|
3072
3154
|
{ name: 'red', condition: x => x.status == 1 },
|
|
3073
3155
|
],
|
|
3074
3156
|
},
|
|
3075
|
-
{ name: 'amount', type: 'money',
|
|
3076
|
-
color: { name: 'red', condition: x => x.reducesBalance && !x.isAggregate },
|
|
3077
|
-
},
|
|
3078
3157
|
{ name: 'typeName', type: 'text', alias: 'Type' },
|
|
3079
3158
|
{ name: 'debitAccountName', type: 'text', alias: 'Debit Account' },
|
|
3080
3159
|
{ name: 'creditAccountName', type: 'text', alias: 'Credit Account' },
|
|
3160
|
+
{ name: 'amount', type: 'money',
|
|
3161
|
+
color: { name: 'red', condition: x => x.reducesBalance && !x.isAggregate },
|
|
3162
|
+
},
|
|
3081
3163
|
],
|
|
3082
3164
|
buttons: [
|
|
3083
|
-
{ name: 'create', display: 'Create', dialog: true, action: { url: 'transactions/dto?action=create', method: 'post' } },
|
|
3165
|
+
{ name: 'create', display: 'Create Transaction', dialog: true, action: { url: 'transactions/dto?action=create', method: 'post' } },
|
|
3084
3166
|
{ name: 'view', dialog: true, detailsConfig: this.transactionDetailsConfig },
|
|
3085
3167
|
this.transactionEditButton,
|
|
3086
3168
|
this.transactionVoidButton,
|
|
@@ -3091,12 +3173,91 @@ class AccountingService {
|
|
|
3091
3173
|
this.accountTransactionsTableConfig = {
|
|
3092
3174
|
...this.transactionsTableConfig,
|
|
3093
3175
|
causeFormRefresh: true,
|
|
3176
|
+
minColumns: ['date', 'description', 'amount', 'runningBalance'],
|
|
3094
3177
|
tabTitle: 'Account Transactions',
|
|
3095
3178
|
loadAction: { url: 'transactions/account/x' }, loadCriteria: 'account', loadIDField: 'accountID',
|
|
3096
3179
|
columns: [
|
|
3097
3180
|
...this.transactionsTableConfig.columns,
|
|
3098
|
-
{ name: 'runningBalance', type: 'money', alias: 'Balance' }
|
|
3181
|
+
{ name: 'runningBalance', type: 'money', alias: 'Balance' }
|
|
3182
|
+
],
|
|
3183
|
+
};
|
|
3184
|
+
//--------------------------Transaction Templates-------------------------
|
|
3185
|
+
// Template form configuration (accountID hidden - auto-populated from context)
|
|
3186
|
+
this.transactionTemplateFormConfig = {
|
|
3187
|
+
security: { allow: [this.dataService.capTransactions] },
|
|
3188
|
+
title: 'Transaction Template',
|
|
3189
|
+
includeAudit: true,
|
|
3190
|
+
fields: [
|
|
3191
|
+
{ name: 'name', type: 'text', required: true, span: true },
|
|
3192
|
+
{ name: 'accountID', type: 'number', hidden: true }, // Auto-populated from Account Details context
|
|
3193
|
+
{ name: 'transactionTypeID', type: 'select', alias: 'Transaction Type', required: true, detailsConfig: this.transactionTypeDetailsConfig, loadAction: { url: 'transactionTypes/list/x' } },
|
|
3194
|
+
{ name: 'blank', type: 'blank' },
|
|
3195
|
+
{ name: 'debitAccountID', type: 'select', alias: 'Default Debit Account', nullable: true, masterField: 'transactionTypeID', masterValueField: 'debitAccountType', masterDefaultValueField: 'defaultDebitAccountID', masterOptionValue: 'type', loadAction: { url: 'accounts/list/x' }, detailsConfig: this.accountBaseDetailsConfig },
|
|
3196
|
+
{ name: 'creditAccountID', type: 'select', alias: 'Default Credit Account', nullable: true, masterField: 'transactionTypeID', masterValueField: 'creditAccountType', masterDefaultValueField: 'defaultCreditAccountID', masterOptionValue: 'type', loadAction: { url: 'accounts/list/x' }, detailsConfig: this.accountBaseDetailsConfig },
|
|
3197
|
+
{ name: 'description', type: 'text', alias: 'Default Description', span: true },
|
|
3198
|
+
{ name: 'defaultAmount', type: 'money', alias: 'Default Amount', span: true },
|
|
3199
|
+
],
|
|
3200
|
+
loadAction: { url: 'transactiontemplates/id' },
|
|
3201
|
+
heroField: 'transactionTemplateID',
|
|
3202
|
+
};
|
|
3203
|
+
// Process form configuration (convert template to transaction)
|
|
3204
|
+
this.transactionTemplateProcessFormConfig = {
|
|
3205
|
+
title: 'Create Transaction from Template',
|
|
3206
|
+
fixedTitle: true,
|
|
3207
|
+
fields: [
|
|
3208
|
+
{ name: 'transactionTemplateID', type: 'number', hidden: true },
|
|
3209
|
+
{ name: 'name', type: 'label', alias: 'Template', readonly: true, span: true },
|
|
3210
|
+
{ name: 'transactionTypeID', type: 'select', alias: 'Transaction Type', required: true, detailsConfig: this.transactionTypeDetailsConfig, loadAction: { url: 'transactionTypes/list/x' } },
|
|
3211
|
+
{ name: 'date', type: 'date', required: true, defaultValue: 'now' },
|
|
3212
|
+
{ name: 'debitAccountID', type: 'select', alias: 'Debit Account', required: true, masterField: 'transactionTypeID', masterValueField: 'debitAccountType', masterOptionValue: 'type', loadAction: { url: 'accounts/list/x' }, detailsConfig: this.accountBaseDetailsConfig },
|
|
3213
|
+
{ name: 'creditAccountID', type: 'select', alias: 'Credit Account', required: true, masterField: 'transactionTypeID', masterValueField: 'creditAccountType', masterOptionValue: 'type', loadAction: { url: 'accounts/list/x' }, detailsConfig: this.accountBaseDetailsConfig },
|
|
3214
|
+
{ name: 'description', type: 'text', required: true, span: true },
|
|
3215
|
+
{ name: 'amount', type: 'money', required: true, span: true },
|
|
3216
|
+
],
|
|
3217
|
+
};
|
|
3218
|
+
// Template action buttons
|
|
3219
|
+
this.transactionTemplateCreateButton = { name: 'create', display: 'Create Template', dialog: true, action: { url: 'transactiontemplates?action=create', method: 'post' } };
|
|
3220
|
+
this.transactionTemplateEditButton = { name: 'edit', dialog: true, action: { url: 'transactiontemplates?action=edit', method: 'post' } };
|
|
3221
|
+
// Template details config (for view/edit)
|
|
3222
|
+
this.transactionTemplateDetailsConfig = {
|
|
3223
|
+
formConfig: this.transactionTemplateFormConfig,
|
|
3224
|
+
heroField: 'transactionTemplateID',
|
|
3225
|
+
buttons: [this.transactionTemplateCreateButton, this.transactionTemplateEditButton]
|
|
3226
|
+
};
|
|
3227
|
+
// Process details config (for processing template)
|
|
3228
|
+
this.transactionTemplateProcessDetailsConfig = {
|
|
3229
|
+
formConfig: this.transactionTemplateProcessFormConfig,
|
|
3230
|
+
heroField: 'transactionTemplateID',
|
|
3231
|
+
mode: 'edit',
|
|
3232
|
+
buttons: [
|
|
3233
|
+
{ name: 'process', display: 'Create Transaction', icon: { name: 'play_arrow', color: 'green' }, inDialog: true,
|
|
3234
|
+
action: { url: 'transactiontemplates/dto?action=process', method: 'post',
|
|
3235
|
+
successMessage: 'Transaction created from template' }
|
|
3236
|
+
}
|
|
3237
|
+
]
|
|
3238
|
+
};
|
|
3239
|
+
// Templates table configuration (3rd tab in Account Details)
|
|
3240
|
+
this.transactionTemplatesTableConfig = {
|
|
3241
|
+
tabTitle: 'Transaction Templates',
|
|
3242
|
+
showFilter: true,
|
|
3243
|
+
minColumns: ['name', 'transactionTypeName', 'defaultAmountDisplay'],
|
|
3244
|
+
flatButtons: true,
|
|
3245
|
+
columns: [
|
|
3246
|
+
{ name: 'name', type: 'button', detailsConfig: this.transactionTemplateProcessDetailsConfig },
|
|
3247
|
+
{ name: 'transactionTypeName', type: 'text', alias: 'Type' },
|
|
3248
|
+
{ name: 'debitAccountName', type: 'text', alias: 'Debit Account' },
|
|
3249
|
+
{ name: 'creditAccountName', type: 'text', alias: 'Credit Account' },
|
|
3250
|
+
{ name: 'defaultAmountDisplay', type: 'text', alias: 'Default Amount' },
|
|
3099
3251
|
],
|
|
3252
|
+
buttons: [
|
|
3253
|
+
this.transactionTemplateCreateButton,
|
|
3254
|
+
{ name: 'process', display: 'Create Transaction', icon: { name: 'play_arrow', color: 'green' }, dialog: true, detailsConfig: this.transactionTemplateProcessDetailsConfig },
|
|
3255
|
+
{ name: 'view', dialog: true, detailsConfig: this.transactionTemplateDetailsConfig },
|
|
3256
|
+
{ name: 'edit', dialog: true, action: { url: 'transactiontemplates?action=edit', method: 'post' }, detailsConfig: this.transactionTemplateDetailsConfig }, // Changed: Inline edit button with both action and detailsConfig
|
|
3257
|
+
{ name: 'delete', inDialog: true, icon: { name: 'delete', color: 'red' }, action: { url: 'transactiontemplates?action=delete', method: 'post', successMessage: 'Template deleted' }, confirm: { message: 'Delete this template?' } },
|
|
3258
|
+
],
|
|
3259
|
+
loadAction: { url: 'transactiontemplates/account/x' }, loadCriteria: 'account', loadIDField: 'accountID',
|
|
3260
|
+
formConfig: this.transactionTemplateFormConfig
|
|
3100
3261
|
};
|
|
3101
3262
|
//--------------------------Accounts-------------------------
|
|
3102
3263
|
this.accountDetailsConfig = {
|
|
@@ -3109,6 +3270,7 @@ class AccountingService {
|
|
|
3109
3270
|
buttons: [],
|
|
3110
3271
|
loadAction: { url: 'transactionTypes/account/x' }, loadCriteria: 'account', loadIDField: 'accountID'
|
|
3111
3272
|
},
|
|
3273
|
+
{ ...this.transactionTemplatesTableConfig }, // Changed: Added 3rd tab for transaction templates
|
|
3112
3274
|
]
|
|
3113
3275
|
};
|
|
3114
3276
|
this.accountsTableConfig = {
|
|
@@ -3727,6 +3889,47 @@ class InventoryService {
|
|
|
3727
3889
|
loadAction: { url: 'products/bundles/x' },
|
|
3728
3890
|
formConfig: this.bundleProductFormConfig
|
|
3729
3891
|
};
|
|
3892
|
+
//--------------------------ServiceItems-------------------------
|
|
3893
|
+
// ServiceItem form configuration - follows Product pattern
|
|
3894
|
+
this.serviceItemFormConfig = {
|
|
3895
|
+
title: 'Service',
|
|
3896
|
+
includeAudit: true,
|
|
3897
|
+
fields: [
|
|
3898
|
+
{ name: 'name', type: 'text', required: true, alias: 'Service Name' },
|
|
3899
|
+
{ name: 'description', type: 'text', alias: 'Description' },
|
|
3900
|
+
{ name: 'unitPrice', type: 'money', required: true, alias: 'Unit Price' },
|
|
3901
|
+
{ name: 'isActive', type: 'checkbox', alias: 'Active', defaultValue: true }
|
|
3902
|
+
],
|
|
3903
|
+
loadAction: { url: 'serviceitems/id' },
|
|
3904
|
+
heroField: 'serviceItemID'
|
|
3905
|
+
};
|
|
3906
|
+
this.serviceItemCreateButton = { name: 'create', display: 'Create Service', dialog: true, action: { url: 'serviceitems?action=create', method: 'post' } };
|
|
3907
|
+
this.serviceItemEditButton = { name: 'edit', dialog: true, action: { url: 'serviceitems?action=edit', method: 'post' } };
|
|
3908
|
+
this.serviceItemDeleteButton = { name: 'delete', dialog: true, action: { url: 'serviceitems?action=delete', method: 'post' } };
|
|
3909
|
+
this.serviceItemDetailsConfig = {
|
|
3910
|
+
formConfig: this.serviceItemFormConfig,
|
|
3911
|
+
heroField: 'serviceItemID',
|
|
3912
|
+
buttons: [this.serviceItemCreateButton, this.serviceItemEditButton, this.serviceItemDeleteButton]
|
|
3913
|
+
};
|
|
3914
|
+
this.serviceItemsTableConfig = {
|
|
3915
|
+
showFilter: true,
|
|
3916
|
+
flatButtons: true,
|
|
3917
|
+
minColumns: ['name', 'unitPrice', 'statusName'],
|
|
3918
|
+
columns: [
|
|
3919
|
+
{ name: 'name', type: 'text', alias: 'Service Name' },
|
|
3920
|
+
{ name: 'description', type: 'text', alias: 'Description' },
|
|
3921
|
+
{ name: 'unitPrice', type: 'money', alias: 'Unit Price' },
|
|
3922
|
+
{ name: 'statusName', type: 'text', alias: 'Status' }
|
|
3923
|
+
],
|
|
3924
|
+
buttons: [
|
|
3925
|
+
this.serviceItemCreateButton,
|
|
3926
|
+
{ name: 'view', dialog: true, detailsConfig: this.serviceItemDetailsConfig },
|
|
3927
|
+
this.serviceItemEditButton,
|
|
3928
|
+
this.serviceItemDeleteButton
|
|
3929
|
+
],
|
|
3930
|
+
loadAction: { url: 'serviceitems/all/x' },
|
|
3931
|
+
formConfig: this.serviceItemFormConfig
|
|
3932
|
+
};
|
|
3730
3933
|
//--------------------------Requisitions-------------------------
|
|
3731
3934
|
this.requisitionItemFormConfig = {
|
|
3732
3935
|
title: 'Requisition Item',
|
|
@@ -3818,10 +4021,10 @@ class InventoryService {
|
|
|
3818
4021
|
};
|
|
3819
4022
|
//--------------------------Purchase Orders-------------------------
|
|
3820
4023
|
// Payment type options (used across forms)
|
|
4024
|
+
// Changed: Removed Credit option - timing now determines credit vs cash purchase
|
|
3821
4025
|
this.paymentTypeOptions = [
|
|
3822
4026
|
{ value: 0, name: 'Cash' },
|
|
3823
|
-
{ value: 1, name: 'Bank' }
|
|
3824
|
-
{ value: 2, name: 'Credit' }
|
|
4027
|
+
{ value: 1, name: 'Bank' }
|
|
3825
4028
|
];
|
|
3826
4029
|
// PO Item form configuration
|
|
3827
4030
|
this.purchaseOrderItemFormConfig = {
|
|
@@ -4005,9 +4208,15 @@ class InventoryService {
|
|
|
4005
4208
|
{ name: 'supplierID', type: 'select', required: true, alias: 'Supplier', section: 'receiptInfo',
|
|
4006
4209
|
loadAction: { url: 'suppliers/list/x' }, detailsConfig: this.dataService.supplierDetailsConfig, infoMessage: 'Supplier providing the goods'
|
|
4007
4210
|
},
|
|
4008
|
-
{ name: '
|
|
4009
|
-
|
|
4010
|
-
|
|
4211
|
+
{ name: 'timing', type: 'select', required: true, alias: 'Transaction Type', section: 'receiptInfo',
|
|
4212
|
+
loadAction: { url: 'inventoryreceipts/list/timing' }, defaultFirstValue: true,
|
|
4213
|
+
infoMessage: 'Cash Purchase (pay now) or Credit Purchase (pay later)'
|
|
4214
|
+
},
|
|
4215
|
+
{ name: 'paymentType', type: 'select', required: true, alias: 'Payment Method', section: 'receiptInfo', defaultFirstValue: true,
|
|
4216
|
+
options: this.paymentTypeOptions, infoMessage: 'Payment method used for this purchase',
|
|
4217
|
+
hiddenCondition: x => x.timing === 1,
|
|
4218
|
+
requiredCondition: x => x.timing === 0
|
|
4219
|
+
},
|
|
4011
4220
|
{ name: 'receiptNumber', type: 'text', alias: 'Receipt Number', readonly: true, hideOnCreate: true, section: 'receiptInfo', infoMessage: 'Auto-generated unique receipt identifier' },
|
|
4012
4221
|
{ name: 'poNumber', type: 'text', alias: 'PO Number', hideOnCreate: true, section: 'receiptInfo', infoMessage: 'Linked purchase order if receiving against a PO',
|
|
4013
4222
|
hiddenCondition: (row) => !row.purchaseOrderID,
|
|
@@ -4034,12 +4243,16 @@ class InventoryService {
|
|
|
4034
4243
|
{ name: 'totals', type: 'section', alias: 'Totals', hideOnCreate: true, collapsed: true },
|
|
4035
4244
|
{ name: 'totalAmount', type: 'money', alias: 'Total Amount', readonly: true, section: 'totals', infoMessage: 'Total value of all items' },
|
|
4036
4245
|
{ name: 'additionalInfo', type: 'section', alias: 'Additional Information', collapsed: true },
|
|
4037
|
-
{ name: 'notes', type: 'text', alias: 'Notes', span: true, section: 'additionalInfo', infoMessage: 'Additional notes about this receipt' }
|
|
4246
|
+
{ name: 'notes', type: 'text', alias: 'Notes', span: true, section: 'additionalInfo', infoMessage: 'Additional notes about this receipt' },
|
|
4247
|
+
{ name: 'supplierInvoiceNumber', type: 'text', alias: 'Supplier Invoice #', section: 'additionalInfo', infoMessage: 'Invoice number from supplier' },
|
|
4038
4248
|
],
|
|
4039
4249
|
loadAction: { url: 'inventoryreceipts/id' },
|
|
4040
4250
|
heroField: 'inventoryReceiptID'
|
|
4041
4251
|
};
|
|
4042
|
-
this.inventoryReceiptEditButton = { name: 'edit', dialog: true,
|
|
4252
|
+
this.inventoryReceiptEditButton = { name: 'edit', dialog: true,
|
|
4253
|
+
action: { url: 'inventoryreceipts?action=edit', method: 'post' },
|
|
4254
|
+
visible: (x) => x.status !== InventoryReceiptStatus.Completed
|
|
4255
|
+
};
|
|
4043
4256
|
this.inventoryReceiptCompleteButton = { name: 'complete', display: 'Complete Receipt', inDialog: true, // Changed: Updated display text and action name
|
|
4044
4257
|
icon: { name: 'check_circle', color: 'green' },
|
|
4045
4258
|
action: { url: 'inventoryreceipts?action=complete', method: 'post', successMessage: 'Receipt Completed' }, // Changed: Updated endpoint and message
|
|
@@ -4072,7 +4285,7 @@ class InventoryService {
|
|
|
4072
4285
|
{ name: 'receiptDate', type: 'date', alias: 'Date' },
|
|
4073
4286
|
{ name: 'supplierName', type: 'text', alias: 'Supplier' },
|
|
4074
4287
|
{ name: 'productsDisplay', type: 'text', alias: 'Products' }, // Added: Display product names or count
|
|
4075
|
-
{ name: '
|
|
4288
|
+
{ name: 'timingName', type: 'text', alias: 'Payment' },
|
|
4076
4289
|
{ name: 'status', type: 'icon', alias: 'Status', detailsConfig: this.inventoryReceiptDetailsConfig, // Changed: Use status instead of statusName
|
|
4077
4290
|
icons: [
|
|
4078
4291
|
{ name: 'article', color: '#9E9E9E', condition: (x) => x.status === InventoryReceiptStatus.Draft, tip: 'Draft' }, // Changed: Use status enum
|
|
@@ -4373,7 +4586,23 @@ class InventoryService {
|
|
|
4373
4586
|
fields: [
|
|
4374
4587
|
{ name: 'saleInfo', type: 'section', alias: 'Sale Information' }, // Changed: Hide when single product mode or when editing existing sale
|
|
4375
4588
|
{ name: 'saleDate', type: 'date', required: true, alias: 'Sale Date', section: 'saleInfo', infoMessage: 'Date when the sale was completed' },
|
|
4376
|
-
{ name: 'customerID', type: 'select', required: true, alias: 'Customer', section: 'saleInfo',
|
|
4589
|
+
{ name: 'customerID', type: 'select', required: true, alias: 'Customer', section: 'saleInfo',
|
|
4590
|
+
loadAction: { url: 'customers/list/x' }, detailsConfig: this.dataService.customerDetailsConfig
|
|
4591
|
+
},
|
|
4592
|
+
{ name: 'timing', type: 'select', required: true, alias: 'Transaction Type', section: 'saleInfo',
|
|
4593
|
+
loadAction: { url: 'sales/list/timing' }, defaultFirstValue: true, infoMessage: 'Cash Sale (pay now) or Credit Sale (pay later)'
|
|
4594
|
+
},
|
|
4595
|
+
{ name: 'paymentMethod', type: 'select', required: true, alias: 'Payment Method', section: 'saleInfo', defaultFirstValue: true, infoMessage: 'Method of payment used for this sale',
|
|
4596
|
+
requiredCondition: x => x.timing === 0,
|
|
4597
|
+
hiddenCondition: x => x.timing === 1,
|
|
4598
|
+
options: [
|
|
4599
|
+
{ name: 'Cash', value: 0 },
|
|
4600
|
+
{ name: 'Bank Transfer', value: 1 },
|
|
4601
|
+
{ name: 'Mobile Money', value: 2 },
|
|
4602
|
+
{ name: 'Card', value: 3 },
|
|
4603
|
+
{ name: 'Complementary', value: 5 }
|
|
4604
|
+
],
|
|
4605
|
+
},
|
|
4377
4606
|
{ name: 'multipleProducts', type: 'checkbox', alias: 'Multiple Products', defaultValue: false, hideOnExists: true, infoMessage: 'Check this box if you want to add multiple products to this sale' }, // Changed: Added checkbox for multiple products mode
|
|
4378
4607
|
{ name: 'saleType', type: 'select', required: true, alias: 'Sale Type', section: 'saleInfo', options: [{ name: 'Quick Sale', value: 0 }, { name: 'From Order', value: 1 }], defaultFirstValue: true, hideOnCreate: true, infoMessage: 'Select if this is a quick sale or created from an order' },
|
|
4379
4608
|
{ name: 'quickSaleItem', type: 'section', alias: 'Quick Sale Item', hiddenCondition: x => x.multipleProducts === true || x.saleID }, // Changed: Section for single product entry
|
|
@@ -4386,17 +4615,16 @@ class InventoryService {
|
|
|
4386
4615
|
},
|
|
4387
4616
|
{ name: 'quantity', type: 'number', required: true, alias: 'Quantity', section: 'quickSaleItem', defaultValue: 1, hiddenCondition: x => x.multipleProducts === true, infoMessage: 'Quantity of the product' }, // Changed: Quantity field for quick sale
|
|
4388
4617
|
{ name: 'unitPrice', type: 'money', required: true, alias: 'Unit Price', section: 'quickSaleItem', hiddenCondition: x => x.multipleProducts === true, infoMessage: 'Price per unit' }, // Changed: Unit price field for quick sale
|
|
4389
|
-
{ name: 'paymentInfo', type: 'section', alias: 'Payment Information', collapsedCondition: x => x.saleID },
|
|
4390
|
-
{ name: 'paymentMethod', type: 'select', required: true, alias: 'Payment Method', section: 'paymentInfo', options: [{ name: 'Cash', value: 0 }, { name: 'Bank Transfer', value: 1 }, { name: 'Mobile Money', value: 2 }, { name: 'Card', value: 3 }, { name: 'Credit', value: 4 }, { name: 'Complementary', value: 5 }], defaultFirstValue: true, infoMessage: 'Method of payment used for this sale' },
|
|
4391
|
-
{ name: 'paymentReference', type: 'text', alias: 'Payment Reference', section: 'paymentInfo', infoMessage: 'Transaction reference number or payment receipt' },
|
|
4392
|
-
{ name: 'paymentStatus', type: 'select', alias: 'Payment Status', readonly: true, section: 'paymentInfo', loadAction: { url: 'sales/list/payment-status' }, hideOnCreate: true, infoMessage: 'Current payment status of the sale' },
|
|
4393
4618
|
{ name: 'totals', type: 'section', alias: 'Totals', collapsed: true, hideOnCreate: true },
|
|
4394
4619
|
{ name: 'subTotal', type: 'money', alias: 'Sub Total', readonly: true, section: 'totals', infoMessage: 'Total before tax and discounts' },
|
|
4395
4620
|
{ name: 'taxAmount', type: 'money', alias: 'Tax Amount', section: 'totals', infoMessage: 'Tax amount applied to the sale' },
|
|
4396
4621
|
{ name: 'discount', type: 'money', alias: 'Discount', section: 'totals', infoMessage: 'Discount amount applied to the sale' },
|
|
4397
4622
|
{ name: 'totalAmount', type: 'money', alias: 'Total Amount', readonly: true, section: 'totals', infoMessage: 'Final amount after tax and discounts' },
|
|
4398
4623
|
{ name: 'additionalInfo', type: 'section', alias: 'Additional Information', collapsed: true },
|
|
4399
|
-
{ name: 'notes', type: 'text', alias: 'Notes', span: true, section: 'additionalInfo', infoMessage: 'Additional notes or comments about this sale' }
|
|
4624
|
+
{ name: 'notes', type: 'text', alias: 'Notes', span: true, section: 'additionalInfo', infoMessage: 'Additional notes or comments about this sale' },
|
|
4625
|
+
{ name: 'paymentReference', type: 'text', alias: 'Payment Reference', section: 'additionalInfo', infoMessage: 'Transaction reference number or payment receipt',
|
|
4626
|
+
hiddenCondition: x => x.timing === 1
|
|
4627
|
+
},
|
|
4400
4628
|
],
|
|
4401
4629
|
loadAction: { url: 'sales/id' },
|
|
4402
4630
|
heroField: 'saleID'
|
|
@@ -4410,26 +4638,72 @@ class InventoryService {
|
|
|
4410
4638
|
{ name: 'Partial', value: 2, icon: 'payment' }
|
|
4411
4639
|
]
|
|
4412
4640
|
};
|
|
4641
|
+
// Added: Sale payment form configuration (matches invoice payment form)
|
|
4642
|
+
this.salePaymentFormConfig = {
|
|
4643
|
+
security: { allow: [this.dataService.capSales] },
|
|
4644
|
+
title: 'Record Payment',
|
|
4645
|
+
fixedTitle: true,
|
|
4646
|
+
fields: [
|
|
4647
|
+
{ name: 'saleID', type: 'number', hidden: true },
|
|
4648
|
+
{ name: 'paymentDate', type: 'date', alias: 'Payment Date', required: true },
|
|
4649
|
+
{ name: 'method', type: 'select', alias: 'Payment Method', required: true, defaultValue: 1, loadAction: { url: 'invoicepayments/list/methods' } }, // Changed: Default to 1 (Bank)
|
|
4650
|
+
{ name: 'totalAmount', type: 'label', alias: 'Total Amount', readonly: true },
|
|
4651
|
+
{ name: 'amount', type: 'money', alias: 'Amount', required: true, span: true },
|
|
4652
|
+
{ name: 'paymentReferenceTemp', type: 'text', alias: 'Reference', span: true }
|
|
4653
|
+
],
|
|
4654
|
+
};
|
|
4655
|
+
// Added: Sale payment button (matches invoice payment button pattern)
|
|
4656
|
+
this.salePaymentCreateButton = {
|
|
4657
|
+
name: 'edit', // Changed: Use standard 'edit' button name for framework recognition
|
|
4658
|
+
action: { url: 'sales?action=record-payment', method: 'post', successMessage: 'Payment recorded successfully' }
|
|
4659
|
+
};
|
|
4660
|
+
// Added: Sale payment details dialog config
|
|
4661
|
+
this.salePaymentDetailsConfig = {
|
|
4662
|
+
formConfig: this.salePaymentFormConfig,
|
|
4663
|
+
heroField: 'saleID',
|
|
4664
|
+
mode: 'edit',
|
|
4665
|
+
buttons: [
|
|
4666
|
+
this.salePaymentCreateButton // Changed: Use separate button definition
|
|
4667
|
+
]
|
|
4668
|
+
};
|
|
4669
|
+
// Added: Sale payment record button
|
|
4670
|
+
this.saleRecordPaymentButton = {
|
|
4671
|
+
name: 'record-payment', display: 'Record Payment', inDialog: true, dialog: true, icon: { name: 'payment', color: 'blue' },
|
|
4672
|
+
detailsConfig: this.salePaymentDetailsConfig,
|
|
4673
|
+
visible: x => x.timing === 1 && x.paymentStatus !== 1
|
|
4674
|
+
};
|
|
4675
|
+
// Added: Sale payments table for payment history (from linked invoice)
|
|
4676
|
+
this.salePaymentsTableConfig = {
|
|
4677
|
+
tabTitle: 'Payment History',
|
|
4678
|
+
showFilter: false,
|
|
4679
|
+
minColumns: ['paymentDate', 'amount', 'methodName'],
|
|
4680
|
+
columns: [
|
|
4681
|
+
{ name: 'paymentDate', type: 'date', alias: 'Date' },
|
|
4682
|
+
{ name: 'amount', type: 'money', alias: 'Amount' },
|
|
4683
|
+
{ name: 'methodName', type: 'text', alias: 'Method' },
|
|
4684
|
+
{ name: 'reference', type: 'text', alias: 'Reference' }
|
|
4685
|
+
],
|
|
4686
|
+
loadAction: { url: 'invoicepayments/x/x' }, loadCriteria: 'invoice', loadIDField: 'invoiceID',
|
|
4687
|
+
hideTabCondition: (x) => x.timing !== 1 // Changed: Only show for deferred payments (credit sales)
|
|
4688
|
+
};
|
|
4413
4689
|
// Details dialog config for sale with complete button (only visible if not yet paid)
|
|
4414
4690
|
this.saleDetailsConfig = {
|
|
4415
4691
|
formConfig: this.saleFormConfig,
|
|
4416
|
-
tableConfigs: [this.saleItemsTableConfig],
|
|
4692
|
+
tableConfigs: [this.saleItemsTableConfig, this.salePaymentsTableConfig], // Added: Include payment history table
|
|
4417
4693
|
heroField: 'saleID',
|
|
4418
4694
|
stepConfig: this.saleStepConfig, // Changed: Added step config for payment status tracking
|
|
4419
4695
|
buttons: [
|
|
4420
4696
|
{ name: 'complete', display: 'Complete Sale', color: 'primary', inDialog: true,
|
|
4421
4697
|
action: { url: 'sales?action=complete', method: 'post' },
|
|
4422
4698
|
confirm: { message: 'Complete this sale? This will reduce inventory and create accounting entries.' },
|
|
4423
|
-
visible: x => x.paymentStatus !== 1
|
|
4424
|
-
}
|
|
4699
|
+
visible: x => x.timing === 0 && x.paymentStatus !== 1 // Changed: Only for immediate sales that aren't paid (deferred sales are auto-completed)
|
|
4700
|
+
},
|
|
4701
|
+
this.saleRecordPaymentButton // Added: Record payment button for credit sales
|
|
4425
4702
|
]
|
|
4426
4703
|
};
|
|
4427
4704
|
this.saleViewButton = { name: 'view', dialog: true, detailsConfig: this.saleDetailsConfig };
|
|
4428
4705
|
this.saleCreateButton = {
|
|
4429
|
-
name: 'create',
|
|
4430
|
-
display: 'Quick Sale',
|
|
4431
|
-
dialog: true,
|
|
4432
|
-
action: { url: 'sales?action=create', method: 'post' },
|
|
4706
|
+
name: 'create', display: 'Quick Sale', dialog: true, action: { url: 'sales?action=create', method: 'post' },
|
|
4433
4707
|
};
|
|
4434
4708
|
this.saleVoidButton = { name: 'void', display: 'Void', icon: { name: 'undo', color: 'red' },
|
|
4435
4709
|
confirm: { message: 'Caution: Voiding this sale will reverse all inventory transactions and void accounting entries. This action cannot be undone.' },
|
|
@@ -4444,7 +4718,7 @@ class InventoryService {
|
|
|
4444
4718
|
{ name: 'saleDate', type: 'date', alias: 'Date' },
|
|
4445
4719
|
{ name: 'displayCustomerName', type: 'text', alias: 'Customer' },
|
|
4446
4720
|
{ name: 'productsDisplay', type: 'text', alias: 'Products' }, // Added: Display product names or count
|
|
4447
|
-
{ name: '
|
|
4721
|
+
{ name: 'timingName', type: 'text', alias: 'Payment' },
|
|
4448
4722
|
{ name: 'paymentStatus', type: 'icon', alias: 'Status', detailsConfig: this.inventoryReceiptDetailsConfig, // Changed: Use status instead of statusName
|
|
4449
4723
|
icons: [
|
|
4450
4724
|
{ name: 'article', color: '#9E9E9E', condition: (x) => x.paymentStatus === 0, tip: 'Unpaid' }, // Changed: Use status enum
|
|
@@ -4455,7 +4729,10 @@ class InventoryService {
|
|
|
4455
4729
|
{ name: 'totalAmount', type: 'money', alias: 'Total' }
|
|
4456
4730
|
],
|
|
4457
4731
|
buttons: [
|
|
4458
|
-
this.saleViewButton,
|
|
4732
|
+
this.saleViewButton,
|
|
4733
|
+
this.saleRecordPaymentButton,
|
|
4734
|
+
this.saleCreateButton,
|
|
4735
|
+
this.saleVoidButton
|
|
4459
4736
|
],
|
|
4460
4737
|
loadAction: { url: 'sales/all/x' },
|
|
4461
4738
|
formConfig: this.saleFormConfig
|
|
@@ -6000,6 +6277,7 @@ class SelectCommonComponent {
|
|
|
6000
6277
|
this.subscription = this.field.optionsSubject.subscribe(newOptions => {
|
|
6001
6278
|
if (newOptions) {
|
|
6002
6279
|
this.options = newOptions;
|
|
6280
|
+
this.setDefaultValue(); // Changed: Apply default after options update via subscription
|
|
6003
6281
|
this.updateSelectedOptionHint();
|
|
6004
6282
|
}
|
|
6005
6283
|
});
|
|
@@ -6016,15 +6294,54 @@ class SelectCommonComponent {
|
|
|
6016
6294
|
this.updateSelectedOptionHint();
|
|
6017
6295
|
}
|
|
6018
6296
|
setDefaultValue() {
|
|
6019
|
-
|
|
6020
|
-
|
|
6297
|
+
// Guard: Need options to set any default
|
|
6298
|
+
if (!this.options || this.options.length === 0) {
|
|
6299
|
+
return;
|
|
6300
|
+
}
|
|
6301
|
+
// Guard: Check if value is already meaningfully set
|
|
6302
|
+
const hasValue = this.value != null &&
|
|
6303
|
+
this.value !== undefined &&
|
|
6304
|
+
!(typeof this.value === 'string' && this.value === '') &&
|
|
6305
|
+
!(typeof this.value === 'number' && this.value === 0 && !this.nullable);
|
|
6306
|
+
if (hasValue) {
|
|
6307
|
+
// Value already set - verify it exists in options
|
|
6308
|
+
const valueExists = this.options.some(opt => this.compareValues(opt[this.optionValue], this.value));
|
|
6309
|
+
if (valueExists) {
|
|
6310
|
+
return; // Valid value already selected
|
|
6311
|
+
}
|
|
6312
|
+
}
|
|
6313
|
+
// Priority 1: Use field.defaultValue if configured
|
|
6314
|
+
const defaultVal = this.field?.defaultValue;
|
|
6315
|
+
if (defaultVal != null && defaultVal !== undefined) {
|
|
6316
|
+
const matchingOption = this.options.find(opt => this.compareValues(opt[this.optionValue], defaultVal));
|
|
6317
|
+
if (matchingOption) {
|
|
6318
|
+
this.value = matchingOption[this.optionValue];
|
|
6319
|
+
this.changed();
|
|
6320
|
+
return;
|
|
6321
|
+
}
|
|
6322
|
+
}
|
|
6323
|
+
// Priority 2: Use defaultFirstValue if configured
|
|
6324
|
+
if (this.defaultFirstValue) {
|
|
6021
6325
|
this.value = this.options[0][this.optionValue];
|
|
6022
6326
|
this.changed();
|
|
6023
6327
|
}
|
|
6024
6328
|
}
|
|
6329
|
+
// Changed: Added helper method for type-coerced value comparison (handles number vs string)
|
|
6330
|
+
compareValues(optionValue, targetValue) {
|
|
6331
|
+
if (optionValue === targetValue)
|
|
6332
|
+
return true;
|
|
6333
|
+
if (optionValue == null || targetValue == null)
|
|
6334
|
+
return false;
|
|
6335
|
+
return String(optionValue) === String(targetValue);
|
|
6336
|
+
}
|
|
6025
6337
|
changed() {
|
|
6026
6338
|
this.valueChange.emit(this.value);
|
|
6027
6339
|
this.updateSelectedOptionHint();
|
|
6340
|
+
// Added: Call onSelectChange callback if provided
|
|
6341
|
+
if (this.field?.onSelectChange && this.data) {
|
|
6342
|
+
const selectedOption = this.options?.find(opt => opt[this.optionValue] === this.value);
|
|
6343
|
+
this.field.onSelectChange(this.value, this.data, selectedOption);
|
|
6344
|
+
}
|
|
6028
6345
|
}
|
|
6029
6346
|
updateSelectedOptionHint() {
|
|
6030
6347
|
if (!this.options || this.options.length === 0 || this.value == null || this.value == undefined) {
|
|
@@ -6063,7 +6380,18 @@ class SelectCommonComponent {
|
|
|
6063
6380
|
this.getData(refreshAction);
|
|
6064
6381
|
}
|
|
6065
6382
|
transformLoadUrl(action) {
|
|
6066
|
-
if (!action?.url || !this.
|
|
6383
|
+
if (!action?.url || !this.data)
|
|
6384
|
+
return action;
|
|
6385
|
+
// Changed: Check if URL contains {propertyName} placeholders first
|
|
6386
|
+
if (action.url.includes('{')) {
|
|
6387
|
+
const transformedUrl = action.url.replace(/\{(\w+)\}/g, (match, propName) => {
|
|
6388
|
+
const value = this.data?.[propName];
|
|
6389
|
+
return value !== undefined && value !== null ? String(value) : match;
|
|
6390
|
+
});
|
|
6391
|
+
return { ...action, url: transformedUrl };
|
|
6392
|
+
}
|
|
6393
|
+
// Changed: Fallback to existing loadIDField pattern for backward compatibility
|
|
6394
|
+
if (!this.loadIDField)
|
|
6067
6395
|
return action;
|
|
6068
6396
|
const idValue = this.data[this.loadIDField];
|
|
6069
6397
|
if (!idValue)
|
|
@@ -6981,7 +7309,18 @@ class ViewerComponent {
|
|
|
6981
7309
|
// fileList: string[];
|
|
6982
7310
|
loadData() {
|
|
6983
7311
|
console.log("Calling files");
|
|
6984
|
-
let url = this.fileAction.url
|
|
7312
|
+
let url = this.fileAction.url;
|
|
7313
|
+
// Changed: Support generic {propertyName} placeholders first
|
|
7314
|
+
if (url.includes('{')) {
|
|
7315
|
+
url = url.replace(/\{(\w+)\}/g, (match, propName) => {
|
|
7316
|
+
const value = { folderName: this.folderName }[propName];
|
|
7317
|
+
return value !== undefined && value !== null ? String(value) : match;
|
|
7318
|
+
});
|
|
7319
|
+
}
|
|
7320
|
+
else {
|
|
7321
|
+
// Fallback: Legacy /x replacement for backward compatibility
|
|
7322
|
+
url = url.replace("/x", '/' + this.folderName);
|
|
7323
|
+
}
|
|
6985
7324
|
this.dataService.CallApi({ url: url }, "").subscribe((apiResponse) => {
|
|
6986
7325
|
this.fileNames = apiResponse.data;
|
|
6987
7326
|
// console.log(this.fileNames)
|
|
@@ -7557,12 +7896,22 @@ class NotesComponent {
|
|
|
7557
7896
|
return;
|
|
7558
7897
|
}
|
|
7559
7898
|
// Otherwise, load from the URL if configured
|
|
7560
|
-
if (this.loadAction && this.data
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7899
|
+
if (this.loadAction && this.data) {
|
|
7900
|
+
let url = this.loadAction.url;
|
|
7901
|
+
// Changed: Support generic {propertyName} placeholders first
|
|
7902
|
+
if (url.includes('{')) {
|
|
7903
|
+
url = url.replace(/\{(\w+)\}/g, (match, propName) => {
|
|
7904
|
+
const value = this.data?.[propName];
|
|
7905
|
+
return value !== undefined && value !== null ? String(value) : match;
|
|
7906
|
+
});
|
|
7907
|
+
}
|
|
7908
|
+
else if (this.loadIDField) {
|
|
7909
|
+
// Fallback: Use loadIDField for backward compatibility
|
|
7910
|
+
const idValue = this.data[this.loadIDField];
|
|
7911
|
+
if (!idValue)
|
|
7912
|
+
return;
|
|
7913
|
+
url = url.replace('/x', '/' + idValue);
|
|
7564
7914
|
}
|
|
7565
|
-
let url = this.loadAction.url.replace('{x}', idValue);
|
|
7566
7915
|
this.dataService.CallApi({ ...this.loadAction, url }).subscribe((apiResponse) => {
|
|
7567
7916
|
if (apiResponse.success && apiResponse.data) {
|
|
7568
7917
|
this.notes = apiResponse.data;
|
|
@@ -14852,11 +15201,11 @@ class RolesComponent {
|
|
|
14852
15201
|
});
|
|
14853
15202
|
}
|
|
14854
15203
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: RolesComponent, deps: [{ token: HttpService }, { token: i1$2.Router }, { token: AuthService }, { token: DataServiceLib }, { token: DialogService }, { token: i5.MatDialog }, { token: MessageService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
14855
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: RolesComponent, isStandalone: false, selector: "spa-roles", ngImport: i0, template: "<h4> Roles </h4>\r\n<hr />\r\n\r\n<div class=\"container-fluid mb-5\">\r\n\r\n <div class=\"d-flex justify-content-between mb-2\">\r\n\r\n <div >\r\n <button id=\"btnNewRole\" mat-raised-button color=\"primary\" (click)=\"addRole()\">New Role</button>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end\">\r\n <button id=\"btnRefresh\" mat-icon-button color=\"primary\" (click)=\"refresh()\" matTooltip=\"refresh data\" matTooltipPosition=\"right\"><mat-icon >refresh</mat-icon></button>\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <div class=\"row mt-2 mb-1\" *ngFor=\"let role of roles\">\r\n\r\n <mat-card class=\"mat-elevation-z8\" style=\"width:100%\">\r\n\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n\r\n <label style=\"font-size: 16px;\">{{role.roleName}}</label>\r\n\r\n <button mat-icon-button color=\"primary\" matTooltip=\"Rename Role\" (click)=\"renameRole(role)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <hr style=\"margin-top: 0px;\">\r\n\r\n <div class=\"tin-row\" style=\" font-size:12px;\">\r\n\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capItem of appConfig.capItems\">\r\n\r\n <!-- Main item-->\r\n <mat-checkbox *ngIf=\"capItem.isBool || capItem.capSubItems\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capItem.name]\" (ngModelChange)=\"onCapItemChange(capItem, $event, role)\">\r\n {{capItem.display}}\r\n <span *ngIf=\"!role[capItem.name] && hasSubItemsAccess(capItem, role)\" class=\"asterisk\" style=\"color: red;\">*</span>\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capItem.isBool && !capItem.capSubItems\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capItem.display\"\r\n [(value)]=\"role[capItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n\r\n <ng-container *ngIf=\"capItem.capSubItems && role[capItem.name]\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubItem of capItem.capSubItems\">\r\n\r\n\r\n <!-- Sub Item -->\r\n <mat-checkbox *ngIf=\"capSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubItem.name]\">\r\n {{capSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubItem.display\"\r\n [(value)]=\"role[capSubItem.name]\"\r\n width=\"150px\"\r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n <ng-container *ngIf=\"capSubItem.capSubItems\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubSubItem of capSubItem.capSubItems\">\r\n\r\n <!-- Sub Sub Items -->\r\n <mat-checkbox *ngIf=\"capSubSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubSubItem.name]\">\r\n {{capSubSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubSubItem.display\"\r\n [(value)]=\"role[capSubSubItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <mat-card-actions>\r\n\r\n <button mat-raised-button color=\"primary\" (click)=\"updateRole(role)\" style=\"margin-right:10px;\">\r\n <mat-icon>done_all</mat-icon>\r\n Update\r\n </button>\r\n\r\n <button mat-raised-button (click)=\"deleteRole(role)\" style=\"margin-right:10px\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n </mat-card-actions>\r\n\r\n </mat-card>\r\n\r\n </div>\r\n\r\n\r\n</div>\r\n\r\n", styles: [""], dependencies: [{ kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SelectComponent, selector: "spa-select", inputs: ["detailsConfig"] }] }); }
|
|
15204
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: RolesComponent, isStandalone: false, selector: "spa-roles", ngImport: i0, template: "<h4> Roles </h4>\r\n<hr />\r\n\r\n<div class=\"container-fluid mb-5\">\r\n\r\n <div class=\"d-flex justify-content-between mb-2\">\r\n\r\n <div >\r\n <button id=\"btnNewRole\" mat-raised-button color=\"primary\" (click)=\"addRole()\">New Role</button>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end\">\r\n <button id=\"btnRefresh\" mat-icon-button color=\"primary\" (click)=\"refresh()\" matTooltip=\"refresh data\" matTooltipPosition=\"right\"><mat-icon >refresh</mat-icon></button>\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <div class=\"row mt-2 mb-1\" *ngFor=\"let role of roles\">\r\n\r\n <mat-card class=\"mat-elevation-z8\" style=\"width:100%\">\r\n\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n\r\n <label style=\"font-size: 16px;\">{{role.roleName}}</label>\r\n\r\n <button mat-icon-button color=\"primary\" matTooltip=\"Rename Role\" (click)=\"renameRole(role)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <hr style=\"margin-top: 0px;\">\r\n\r\n <div class=\"tin-row\" style=\" font-size:12px;\">\r\n\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capItem of appConfig.capItems\">\r\n\r\n <!-- Main item-->\r\n <mat-checkbox *ngIf=\"capItem.isBool || capItem.capSubItems\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capItem.name]\" (ngModelChange)=\"onCapItemChange(capItem, $event, role)\">\r\n {{capItem.display}}\r\n <span *ngIf=\"!role[capItem.name] && hasSubItemsAccess(capItem, role)\" class=\"asterisk\" style=\"color: red;\">*</span>\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capItem.isBool && !capItem.capSubItems\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capItem.display\"\r\n [(value)]=\"role[capItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n\r\n <ng-container *ngIf=\"capItem.capSubItems && role[capItem.name]\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubItem of capItem.capSubItems\">\r\n\r\n\r\n <!-- Sub Item -->\r\n <mat-checkbox *ngIf=\"capSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubItem.name]\">\r\n {{capSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubItem.display\"\r\n [(value)]=\"role[capSubItem.name]\"\r\n width=\"150px\"\r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n <ng-container *ngIf=\"capSubItem.capSubItems\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubSubItem of capSubItem.capSubItems\">\r\n\r\n <!-- Sub Sub Items -->\r\n <mat-checkbox *ngIf=\"capSubSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubSubItem.name]\">\r\n {{capSubSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubSubItem.display\"\r\n [(value)]=\"role[capSubSubItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <mat-card-actions>\r\n\r\n <button mat-raised-button color=\"primary\" (click)=\"updateRole(role)\" style=\"margin-right:10px;\">\r\n <mat-icon>done_all</mat-icon>\r\n Update\r\n </button>\r\n\r\n <button mat-raised-button (click)=\"deleteRole(role)\" style=\"margin-right:10px\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n </mat-card-actions>\r\n\r\n </mat-card>\r\n\r\n </div>\r\n\r\n <hr style=\"margin-top: 50px;\" />\r\n\r\n\r\n</div>\r\n\r\n", styles: [""], dependencies: [{ kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6$2.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SelectComponent, selector: "spa-select", inputs: ["detailsConfig"] }] }); }
|
|
14856
15205
|
}
|
|
14857
15206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: RolesComponent, decorators: [{
|
|
14858
15207
|
type: Component,
|
|
14859
|
-
args: [{ selector: "spa-roles", standalone: false, template: "<h4> Roles </h4>\r\n<hr />\r\n\r\n<div class=\"container-fluid mb-5\">\r\n\r\n <div class=\"d-flex justify-content-between mb-2\">\r\n\r\n <div >\r\n <button id=\"btnNewRole\" mat-raised-button color=\"primary\" (click)=\"addRole()\">New Role</button>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end\">\r\n <button id=\"btnRefresh\" mat-icon-button color=\"primary\" (click)=\"refresh()\" matTooltip=\"refresh data\" matTooltipPosition=\"right\"><mat-icon >refresh</mat-icon></button>\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <div class=\"row mt-2 mb-1\" *ngFor=\"let role of roles\">\r\n\r\n <mat-card class=\"mat-elevation-z8\" style=\"width:100%\">\r\n\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n\r\n <label style=\"font-size: 16px;\">{{role.roleName}}</label>\r\n\r\n <button mat-icon-button color=\"primary\" matTooltip=\"Rename Role\" (click)=\"renameRole(role)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <hr style=\"margin-top: 0px;\">\r\n\r\n <div class=\"tin-row\" style=\" font-size:12px;\">\r\n\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capItem of appConfig.capItems\">\r\n\r\n <!-- Main item-->\r\n <mat-checkbox *ngIf=\"capItem.isBool || capItem.capSubItems\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capItem.name]\" (ngModelChange)=\"onCapItemChange(capItem, $event, role)\">\r\n {{capItem.display}}\r\n <span *ngIf=\"!role[capItem.name] && hasSubItemsAccess(capItem, role)\" class=\"asterisk\" style=\"color: red;\">*</span>\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capItem.isBool && !capItem.capSubItems\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capItem.display\"\r\n [(value)]=\"role[capItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n\r\n <ng-container *ngIf=\"capItem.capSubItems && role[capItem.name]\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubItem of capItem.capSubItems\">\r\n\r\n\r\n <!-- Sub Item -->\r\n <mat-checkbox *ngIf=\"capSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubItem.name]\">\r\n {{capSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubItem.display\"\r\n [(value)]=\"role[capSubItem.name]\"\r\n width=\"150px\"\r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n <ng-container *ngIf=\"capSubItem.capSubItems\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubSubItem of capSubItem.capSubItems\">\r\n\r\n <!-- Sub Sub Items -->\r\n <mat-checkbox *ngIf=\"capSubSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubSubItem.name]\">\r\n {{capSubSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubSubItem.display\"\r\n [(value)]=\"role[capSubSubItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <mat-card-actions>\r\n\r\n <button mat-raised-button color=\"primary\" (click)=\"updateRole(role)\" style=\"margin-right:10px;\">\r\n <mat-icon>done_all</mat-icon>\r\n Update\r\n </button>\r\n\r\n <button mat-raised-button (click)=\"deleteRole(role)\" style=\"margin-right:10px\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n </mat-card-actions>\r\n\r\n </mat-card>\r\n\r\n </div>\r\n\r\n\r\n</div>\r\n\r\n" }]
|
|
15208
|
+
args: [{ selector: "spa-roles", standalone: false, template: "<h4> Roles </h4>\r\n<hr />\r\n\r\n<div class=\"container-fluid mb-5\">\r\n\r\n <div class=\"d-flex justify-content-between mb-2\">\r\n\r\n <div >\r\n <button id=\"btnNewRole\" mat-raised-button color=\"primary\" (click)=\"addRole()\">New Role</button>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end\">\r\n <button id=\"btnRefresh\" mat-icon-button color=\"primary\" (click)=\"refresh()\" matTooltip=\"refresh data\" matTooltipPosition=\"right\"><mat-icon >refresh</mat-icon></button>\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <div class=\"row mt-2 mb-1\" *ngFor=\"let role of roles\">\r\n\r\n <mat-card class=\"mat-elevation-z8\" style=\"width:100%\">\r\n\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n\r\n <label style=\"font-size: 16px;\">{{role.roleName}}</label>\r\n\r\n <button mat-icon-button color=\"primary\" matTooltip=\"Rename Role\" (click)=\"renameRole(role)\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <hr style=\"margin-top: 0px;\">\r\n\r\n <div class=\"tin-row\" style=\" font-size:12px;\">\r\n\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capItem of appConfig.capItems\">\r\n\r\n <!-- Main item-->\r\n <mat-checkbox *ngIf=\"capItem.isBool || capItem.capSubItems\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capItem.name]\" (ngModelChange)=\"onCapItemChange(capItem, $event, role)\">\r\n {{capItem.display}}\r\n <span *ngIf=\"!role[capItem.name] && hasSubItemsAccess(capItem, role)\" class=\"asterisk\" style=\"color: red;\">*</span>\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capItem.isBool && !capItem.capSubItems\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capItem.display\"\r\n [(value)]=\"role[capItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n\r\n <ng-container *ngIf=\"capItem.capSubItems && role[capItem.name]\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubItem of capItem.capSubItems\">\r\n\r\n\r\n <!-- Sub Item -->\r\n <mat-checkbox *ngIf=\"capSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubItem.name]\">\r\n {{capSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubItem.display\"\r\n [(value)]=\"role[capSubItem.name]\"\r\n width=\"150px\"\r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n <ng-container *ngIf=\"capSubItem.capSubItems\">\r\n\r\n <div class=\"tin-row\" *ngFor=\"let capSubSubItem of capSubItem.capSubItems\">\r\n\r\n <!-- Sub Sub Items -->\r\n <mat-checkbox *ngIf=\"capSubSubItem.isBool\"\r\n color=\"primary\" style=\"min-width: 100px;\" [(ngModel)]=\"role[capSubSubItem.name]\">\r\n {{capSubSubItem.display}}\r\n </mat-checkbox>\r\n\r\n <spa-select\r\n *ngIf=\"!capSubSubItem.isBool\"\r\n [options]=\"roleAccessOptions\"\r\n optionDisplay=\"name\"\r\n optionValue=\"value\"\r\n [display]=\"capSubSubItem.display\"\r\n [(value)]=\"role[capSubSubItem.name]\"\r\n width=\"150px\" \r\n style=\"font-size: 12px;\">\r\n </spa-select>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n </div>\r\n\r\n\r\n <mat-card-actions>\r\n\r\n <button mat-raised-button color=\"primary\" (click)=\"updateRole(role)\" style=\"margin-right:10px;\">\r\n <mat-icon>done_all</mat-icon>\r\n Update\r\n </button>\r\n\r\n <button mat-raised-button (click)=\"deleteRole(role)\" style=\"margin-right:10px\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n </mat-card-actions>\r\n\r\n </mat-card>\r\n\r\n </div>\r\n\r\n <hr style=\"margin-top: 50px;\" />\r\n\r\n\r\n</div>\r\n\r\n" }]
|
|
14860
15209
|
}], ctorParameters: () => [{ type: HttpService }, { type: i1$2.Router }, { type: AuthService }, { type: DataServiceLib }, { type: DialogService }, { type: i5.MatDialog }, { type: MessageService }] });
|
|
14861
15210
|
|
|
14862
15211
|
class CreateAccountComponent {
|
|
@@ -16064,6 +16413,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
16064
16413
|
}]
|
|
16065
16414
|
}] });
|
|
16066
16415
|
|
|
16416
|
+
// ServiceItems component for managing service items
|
|
16417
|
+
class ServiceItemsComponent {
|
|
16418
|
+
constructor() {
|
|
16419
|
+
this.inventoryService = inject(InventoryService);
|
|
16420
|
+
this.pageConfig = {
|
|
16421
|
+
title: 'Services',
|
|
16422
|
+
tableConfig: this.inventoryService.serviceItemsTableConfig
|
|
16423
|
+
};
|
|
16424
|
+
}
|
|
16425
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: ServiceItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
16426
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: ServiceItemsComponent, isStandalone: false, selector: "spa-service-items", ngImport: i0, template: '<spa-page [config]="pageConfig"></spa-page>', isInline: true, dependencies: [{ kind: "component", type: PageComponent, selector: "spa-page", inputs: ["config"], outputs: ["searchModeActivated", "searchModeDeactivated", "refreshClick", "actionClick", "actionResponse", "inputChange", "createClick", "searchClick", "dataLoad", "titleActionChange"] }] }); }
|
|
16427
|
+
}
|
|
16428
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: ServiceItemsComponent, decorators: [{
|
|
16429
|
+
type: Component,
|
|
16430
|
+
args: [{
|
|
16431
|
+
selector: 'spa-service-items',
|
|
16432
|
+
standalone: false,
|
|
16433
|
+
template: '<spa-page [config]="pageConfig"></spa-page>'
|
|
16434
|
+
}]
|
|
16435
|
+
}] });
|
|
16436
|
+
|
|
16067
16437
|
class GptCachesComponent {
|
|
16068
16438
|
constructor() {
|
|
16069
16439
|
this.dataService = inject(DataServiceLib);
|
|
@@ -16124,6 +16494,7 @@ const routes$1 = [
|
|
|
16124
16494
|
{ path: "loans", component: LoansComponent },
|
|
16125
16495
|
{ path: "loans-payments", component: LoanPaymentsComponent },
|
|
16126
16496
|
{ path: "inventory-products", component: ProductsComponent },
|
|
16497
|
+
{ path: "inventory-service-items", component: ServiceItemsComponent }, // Added: Service items route
|
|
16127
16498
|
{ path: "inventory-items", component: InventoryItemsComponent },
|
|
16128
16499
|
{ path: "purchase-orders", component: PurchaseOrdersComponent },
|
|
16129
16500
|
{ path: "inventory-receipts", component: InventoryReceiptsComponent },
|
|
@@ -16180,7 +16551,8 @@ class AdminModule {
|
|
|
16180
16551
|
InventoryStockComponent,
|
|
16181
16552
|
ProductionRecipesComponent,
|
|
16182
16553
|
ProductionOrdersComponent,
|
|
16183
|
-
BundleProductsComponent // Added: Bundle products component
|
|
16554
|
+
BundleProductsComponent, // Added: Bundle products component
|
|
16555
|
+
ServiceItemsComponent // Added: Service items component
|
|
16184
16556
|
], imports: [CommonModule,
|
|
16185
16557
|
AdminRoutingModule,
|
|
16186
16558
|
SpaAdminModule] }); }
|
|
@@ -16216,7 +16588,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
16216
16588
|
InventoryStockComponent,
|
|
16217
16589
|
ProductionRecipesComponent,
|
|
16218
16590
|
ProductionOrdersComponent,
|
|
16219
|
-
BundleProductsComponent // Added: Bundle products component
|
|
16591
|
+
BundleProductsComponent, // Added: Bundle products component
|
|
16592
|
+
ServiceItemsComponent // Added: Service items component
|
|
16220
16593
|
],
|
|
16221
16594
|
imports: [
|
|
16222
16595
|
CommonModule,
|
|
@@ -16273,5 +16646,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
16273
16646
|
* Generated bundle index. Do not edit.
|
|
16274
16647
|
*/
|
|
16275
16648
|
|
|
16276
|
-
export { Account, AccountsComponent as AccountingAccountsComponent, AggregatesComponent as AccountingAggregatesComponent, AgingComponent as AccountingAgingComponent, InvoicesComponent as AccountingInvoicesComponent, OutstandingInvoicesComponent as AccountingOutstandingInvoicesComponent, AccountingService, TransactionTypesComponent as AccountingTransactionTypesComponent, TransactionsComponent as AccountingTransactionsComponent, Action, ActivityComponent, AdminModule, AlertComponent, AlertConfig, AlertMessage, ApiResponse, AppConfig, AppModelsComponent, AttachComponent, AuthService, BrandsComponent, CacheConfig, CapItem, CapsulesComponent, CategoriesComponent, ChangePasswordComponent, ChangeUserPassword, CheckComponent, ChipsComponent, Constants, Core, CreateAccountComponent, CustomersComponent, DataServiceLib, DateComponent, DatetimeComponent, DepartmentsComponent, DetailsDialog, DetailsDialogConfig, DetailsDialogProcessor, DetailsSource, DialogService, EmailComponent, EmployeesComponent, ExportService, FilterComponent, FormComponent, FormConfig, GeneralService, GradesComponent, GroupsComponent, HtmlComponent, HttpService, IndexModule, InventoryReceiptStatus, InventoryService, InvoiceStatus, LabelComponent, ListDialogComponent, ListDialogConfig, LoaderComponent, LoaderService, LoanPaymentsComponent, LoanProductsComponent, LoansComponent, LoansService, LogLevel, LogService, LoginComponent, LogsComponent, MembershipComponent, MessageService, MoneyComponent, MovementType, NavMenuComponent, NotesComponent, NotesConfig, NumberComponent, OnboardingComponent, OptionComponent, PageComponent, PageConfig, PlansComponent, PositionsComponent, Profile, ProfileComponent, RecoverAccountComponent, Register, Role, RoleAccess, RolesComponent, SearchComponent, SearchConfig, SecurityConfig, SelectBitwiseComponent, SelectComponent, SelectMultiComponent, SettingsComponent, SignupComponent, SpaAdminModule, SpaIndexModule, SpaMatModule, SpaUserModule, StatusesComponent, Step, StepConfig, StepsComponent, StorageService, SubCategoriesComponent, SuppliersComponent, TabService, TableComponent, TableConfig, TabsComponent, TabsInternalComponent, TabsLiteComponent, TasksComponent, TenantsComponent, TextAreaComponent, TextComponent, TextMaskComponent, TextMultiComponent, TextSingleComponent, TileConfig, TilesComponent, TinSpaComponent, TinSpaModule, TinSpaService, TitleActionsComponent, UnitOfMeasure, User, UserModule, UsersComponent, ViewerComponent, WelcomeComponent, authGuard, dialogOptions, loginConfig, messageDialog, viewerDialog };
|
|
16649
|
+
export { Account, AccountsComponent as AccountingAccountsComponent, AggregatesComponent as AccountingAggregatesComponent, AgingComponent as AccountingAgingComponent, InvoicesComponent as AccountingInvoicesComponent, OutstandingInvoicesComponent as AccountingOutstandingInvoicesComponent, AccountingService, TransactionTypesComponent as AccountingTransactionTypesComponent, TransactionsComponent as AccountingTransactionsComponent, Action, ActivityComponent, AdminModule, AlertComponent, AlertConfig, AlertMessage, ApiResponse, AppConfig, AppModelsComponent, AttachComponent, AuthService, BrandsComponent, CacheConfig, CapItem, CapsulesComponent, CategoriesComponent, ChangePasswordComponent, ChangeUserPassword, CheckComponent, ChipsComponent, Constants, Core, CreateAccountComponent, CustomersComponent, DataServiceLib, DateComponent, DatetimeComponent, DepartmentsComponent, DetailsDialog, DetailsDialogConfig, DetailsDialogProcessor, DetailsSource, DialogService, EmailComponent, EmployeesComponent, ExportService, FilterComponent, FormComponent, FormConfig, GeneralService, GradesComponent, GroupsComponent, HtmlComponent, HttpService, IndexModule, InventoryReceiptStatus, InventoryService, InvoiceItemType, InvoiceStatus, LabelComponent, ListDialogComponent, ListDialogConfig, LoaderComponent, LoaderService, LoanPaymentsComponent, LoanProductsComponent, LoansComponent, LoansService, LogLevel, LogService, LoginComponent, LogsComponent, MembershipComponent, MessageService, MoneyComponent, MovementType, NavMenuComponent, NotesComponent, NotesConfig, NumberComponent, OnboardingComponent, OptionComponent, PageComponent, PageConfig, PlansComponent, PositionsComponent, Profile, ProfileComponent, RecoverAccountComponent, Register, Role, RoleAccess, RolesComponent, SearchComponent, SearchConfig, SecurityConfig, SelectBitwiseComponent, SelectComponent, SelectMultiComponent, SettingsComponent, SignupComponent, SpaAdminModule, SpaIndexModule, SpaMatModule, SpaUserModule, StatusesComponent, Step, StepConfig, StepsComponent, StorageService, SubCategoriesComponent, SuppliersComponent, TabService, TableComponent, TableConfig, TabsComponent, TabsInternalComponent, TabsLiteComponent, TasksComponent, TenantsComponent, TextAreaComponent, TextComponent, TextMaskComponent, TextMultiComponent, TextSingleComponent, TileConfig, TilesComponent, TinSpaComponent, TinSpaModule, TinSpaService, TitleActionsComponent, TransactionTiming, UnitOfMeasure, User, UserModule, UsersComponent, ViewerComponent, WelcomeComponent, authGuard, dialogOptions, loginConfig, messageDialog, viewerDialog };
|
|
16277
16650
|
//# sourceMappingURL=tin-spa.mjs.map
|