tango-app-ui-manage-billing 3.3.19 → 3.3.21

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.
Files changed (31) hide show
  1. package/esm2022/lib/components/billing-summary/billing-summary.component.mjs +25 -17
  2. package/esm2022/lib/components/brand-invoices/brand-invoices.component.mjs +13 -5
  3. package/esm2022/lib/components/daily-pricing/daily-pricing.component.mjs +71 -7
  4. package/esm2022/lib/components/daily-pricing/generate-invoice-modal/generate-invoice-modal.component.mjs +3 -3
  5. package/esm2022/lib/components/daily-pricing/new-stores-modal/new-stores-modal.component.mjs +25 -0
  6. package/esm2022/lib/components/invoice-preview/invoice-preview.component.mjs +3 -3
  7. package/esm2022/lib/components/plans-subscription/payments-subscription.component.mjs +184 -13
  8. package/esm2022/lib/components/plans-subscription/subscription-popups/upload-document/upload-document.component.mjs +82 -0
  9. package/esm2022/lib/components/purchase-order/purchase-order-details/purchase-order-details.component.mjs +62 -0
  10. package/esm2022/lib/components/purchase-order/purchase-order-form/purchase-order-form.component.mjs +87 -0
  11. package/esm2022/lib/components/purchase-order/purchase-order.component.mjs +104 -0
  12. package/esm2022/lib/components/services/billing.service.mjs +15 -1
  13. package/esm2022/lib/components/tango-manage-billing/edit-invoice/edit-invoice.component.mjs +25 -3
  14. package/esm2022/lib/services/payment-subscription.service.mjs +17 -6
  15. package/esm2022/lib/tango-manage-billing.module.mjs +16 -1
  16. package/fesm2022/tango-app-ui-manage-billing.mjs +724 -96
  17. package/fesm2022/tango-app-ui-manage-billing.mjs.map +1 -1
  18. package/lib/components/billing-summary/billing-summary.component.d.ts +1 -0
  19. package/lib/components/brand-invoices/brand-invoices.component.d.ts +3 -0
  20. package/lib/components/daily-pricing/daily-pricing.component.d.ts +6 -0
  21. package/lib/components/daily-pricing/new-stores-modal/new-stores-modal.component.d.ts +10 -0
  22. package/lib/components/plans-subscription/payments-subscription.component.d.ts +15 -0
  23. package/lib/components/plans-subscription/subscription-popups/upload-document/upload-document.component.d.ts +23 -0
  24. package/lib/components/purchase-order/purchase-order-details/purchase-order-details.component.d.ts +18 -0
  25. package/lib/components/purchase-order/purchase-order-form/purchase-order-form.component.d.ts +25 -0
  26. package/lib/components/purchase-order/purchase-order.component.d.ts +28 -0
  27. package/lib/components/services/billing.service.d.ts +3 -0
  28. package/lib/components/tango-manage-billing/edit-invoice/edit-invoice.component.d.ts +2 -0
  29. package/lib/services/payment-subscription.service.d.ts +4 -0
  30. package/lib/tango-manage-billing.module.d.ts +42 -37
  31. package/package.json +1 -1
@@ -0,0 +1,82 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { Subject, takeUntil } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@ng-bootstrap/ng-bootstrap";
5
+ import * as i2 from "../../../../services/payment-subscription.service";
6
+ import * as i3 from "tango-app-ui-shared";
7
+ import * as i4 from "@angular/common";
8
+ import * as i5 from "@angular/forms";
9
+ export class UploadDocumentComponent {
10
+ activeModal;
11
+ paymentSubscriptionService;
12
+ toast;
13
+ clientId = '';
14
+ documentName = '';
15
+ expiryDate = '';
16
+ selectedFile = null;
17
+ fileError = '';
18
+ uploading = false;
19
+ destroy$ = new Subject();
20
+ constructor(activeModal, paymentSubscriptionService, toast) {
21
+ this.activeModal = activeModal;
22
+ this.paymentSubscriptionService = paymentSubscriptionService;
23
+ this.toast = toast;
24
+ }
25
+ onFileSelected(event) {
26
+ this.fileError = '';
27
+ const file = event?.target?.files?.[0];
28
+ if (!file) {
29
+ this.selectedFile = null;
30
+ return;
31
+ }
32
+ // PDF only.
33
+ if (file.type !== 'application/pdf') {
34
+ this.fileError = 'Only PDF files are allowed';
35
+ this.selectedFile = null;
36
+ return;
37
+ }
38
+ this.selectedFile = file;
39
+ }
40
+ get canSubmit() {
41
+ return !!this.documentName.trim() && !!this.selectedFile && !this.uploading;
42
+ }
43
+ upload() {
44
+ if (!this.canSubmit || !this.selectedFile) {
45
+ return;
46
+ }
47
+ this.uploading = true;
48
+ const formData = new FormData();
49
+ formData.append('clientId', this.clientId);
50
+ formData.append('documentName', this.documentName.trim());
51
+ if (this.expiryDate) {
52
+ formData.append('expiryDate', this.expiryDate);
53
+ }
54
+ formData.append('file', this.selectedFile);
55
+ this.paymentSubscriptionService.uploadClientDocument(formData)
56
+ .pipe(takeUntil(this.destroy$))
57
+ .subscribe({
58
+ next: (res) => {
59
+ this.uploading = false;
60
+ this.toast.getSuccessToast('Document uploaded successfully');
61
+ this.activeModal.close('uploaded');
62
+ },
63
+ error: (err) => {
64
+ this.uploading = false;
65
+ this.toast.getErrorToast(err?.error?.message || 'Upload failed');
66
+ },
67
+ });
68
+ }
69
+ ngOnDestroy() {
70
+ this.destroy$.next();
71
+ this.destroy$.complete();
72
+ }
73
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UploadDocumentComponent, deps: [{ token: i1.NgbActiveModal }, { token: i2.PaymentSubscriptionService }, { token: i3.ToastService }], target: i0.ɵɵFactoryTarget.Component });
74
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: UploadDocumentComponent, selector: "lib-upload-document", inputs: { clientId: "clientId" }, ngImport: i0, template: "<div class=\"modal-content\">\n <div class=\"p-6\">\n <div class=\"heading mt-2 ms-1\">Upload Document</div>\n <div class=\"text-sub\">PDF only</div>\n </div>\n <div class=\"modal-body\">\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Document Name</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"documentName\"\n placeholder=\"Enter document name\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Expiry Date</label>\n <input type=\"date\" class=\"form-control border-val\" [(ngModel)]=\"expiryDate\" />\n </div>\n <div class=\"mb-2\">\n <label class=\"producttext mb-2\">Document File (PDF)</label>\n <input type=\"file\" class=\"form-control border-val\" accept=\"application/pdf\"\n (change)=\"onFileSelected($event)\" />\n <div *ngIf=\"fileError\" class=\"text-danger producttext mt-2\">{{ fileError }}</div>\n </div>\n\n <div class=\"d-flex mt-7 py-3\">\n <button type=\"button\" (click)=\"activeModal.dismiss()\"\n class=\"btn-outline btn cancel me-4 w-50\">Cancel</button>\n <button type=\"button\" (click)=\"upload()\" [disabled]=\"!canSubmit\"\n class=\"btn btn-primary px-4 w-50\">\n <span class=\"submit\">{{ uploading ? 'Uploading...' : 'Upload' }}</span>\n </button>\n </div>\n </div>\n</div>", styles: [".heading{font-size:18px;font-weight:700;color:#101828}.text-sub{font-size:13px;color:#667085}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
75
+ }
76
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UploadDocumentComponent, decorators: [{
77
+ type: Component,
78
+ args: [{ selector: 'lib-upload-document', template: "<div class=\"modal-content\">\n <div class=\"p-6\">\n <div class=\"heading mt-2 ms-1\">Upload Document</div>\n <div class=\"text-sub\">PDF only</div>\n </div>\n <div class=\"modal-body\">\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Document Name</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"documentName\"\n placeholder=\"Enter document name\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Expiry Date</label>\n <input type=\"date\" class=\"form-control border-val\" [(ngModel)]=\"expiryDate\" />\n </div>\n <div class=\"mb-2\">\n <label class=\"producttext mb-2\">Document File (PDF)</label>\n <input type=\"file\" class=\"form-control border-val\" accept=\"application/pdf\"\n (change)=\"onFileSelected($event)\" />\n <div *ngIf=\"fileError\" class=\"text-danger producttext mt-2\">{{ fileError }}</div>\n </div>\n\n <div class=\"d-flex mt-7 py-3\">\n <button type=\"button\" (click)=\"activeModal.dismiss()\"\n class=\"btn-outline btn cancel me-4 w-50\">Cancel</button>\n <button type=\"button\" (click)=\"upload()\" [disabled]=\"!canSubmit\"\n class=\"btn btn-primary px-4 w-50\">\n <span class=\"submit\">{{ uploading ? 'Uploading...' : 'Upload' }}</span>\n </button>\n </div>\n </div>\n</div>", styles: [".heading{font-size:18px;font-weight:700;color:#101828}.text-sub{font-size:13px;color:#667085}\n"] }]
79
+ }], ctorParameters: () => [{ type: i1.NgbActiveModal }, { type: i2.PaymentSubscriptionService }, { type: i3.ToastService }], propDecorators: { clientId: [{
80
+ type: Input
81
+ }] } });
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWRvY3VtZW50LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9wbGFucy1zdWJzY3JpcHRpb24vc3Vic2NyaXB0aW9uLXBvcHVwcy91cGxvYWQtZG9jdW1lbnQvdXBsb2FkLWRvY3VtZW50LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9wbGFucy1zdWJzY3JpcHRpb24vc3Vic2NyaXB0aW9uLXBvcHVwcy91cGxvYWQtZG9jdW1lbnQvdXBsb2FkLWRvY3VtZW50LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWpELE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7Ozs7O0FBUzFDLE1BQU0sT0FBTyx1QkFBdUI7SUFZekI7SUFDQztJQUNBO0lBYkQsUUFBUSxHQUFXLEVBQUUsQ0FBQztJQUUvQixZQUFZLEdBQVcsRUFBRSxDQUFDO0lBQzFCLFVBQVUsR0FBVyxFQUFFLENBQUM7SUFDeEIsWUFBWSxHQUFnQixJQUFJLENBQUM7SUFDakMsU0FBUyxHQUFXLEVBQUUsQ0FBQztJQUN2QixTQUFTLEdBQVksS0FBSyxDQUFDO0lBRVYsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFFaEQsWUFDUyxXQUEyQixFQUMxQiwwQkFBc0QsRUFDdEQsS0FBbUI7UUFGcEIsZ0JBQVcsR0FBWCxXQUFXLENBQWdCO1FBQzFCLCtCQUEwQixHQUExQiwwQkFBMEIsQ0FBNEI7UUFDdEQsVUFBSyxHQUFMLEtBQUssQ0FBYztJQUMxQixDQUFDO0lBRUosY0FBYyxDQUFDLEtBQVU7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFJLEdBQVMsS0FBSyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1QsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7WUFDekIsT0FBTztTQUNSO1FBQ0QsWUFBWTtRQUNaLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxpQkFBaUIsRUFBRTtZQUNuQyxJQUFJLENBQUMsU0FBUyxHQUFHLDRCQUE0QixDQUFDO1lBQzlDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1lBQ3pCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFDWCxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUM5RSxDQUFDO0lBRUQsTUFBTTtRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN6QyxPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ2hDLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQyxRQUFRLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDMUQsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLFFBQVEsQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUNoRDtRQUNELFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDO2FBQzNELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzlCLFNBQVMsQ0FBQztZQUNULElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNaLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUN2QixJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO2dCQUM3RCxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNyQyxDQUFDO1lBQ0QsS0FBSyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ2IsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTyxJQUFJLGVBQWUsQ0FBQyxDQUFDO1lBQ25FLENBQUM7U0FDRixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO3dHQXBFVSx1QkFBdUI7NEZBQXZCLHVCQUF1Qiw2RkNYcEMscWdEQStCTTs7NEZEcEJPLHVCQUF1QjtrQkFMbkMsU0FBUzsrQkFDRSxxQkFBcUI7dUpBS3RCLFFBQVE7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ2JBY3RpdmVNb2RhbCB9IGZyb20gJ0BuZy1ib290c3RyYXAvbmctYm9vdHN0cmFwJztcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLXNoYXJlZCc7XG5pbXBvcnQgeyBQYXltZW50U3Vic2NyaXB0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uL3NlcnZpY2VzL3BheW1lbnQtc3Vic2NyaXB0aW9uLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItdXBsb2FkLWRvY3VtZW50JyxcbiAgdGVtcGxhdGVVcmw6ICcuL3VwbG9hZC1kb2N1bWVudC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi91cGxvYWQtZG9jdW1lbnQuY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIFVwbG9hZERvY3VtZW50Q29tcG9uZW50IHtcbiAgQElucHV0KCkgY2xpZW50SWQ6IHN0cmluZyA9ICcnO1xuXG4gIGRvY3VtZW50TmFtZTogc3RyaW5nID0gJyc7XG4gIGV4cGlyeURhdGU6IHN0cmluZyA9ICcnO1xuICBzZWxlY3RlZEZpbGU6IEZpbGUgfCBudWxsID0gbnVsbDtcbiAgZmlsZUVycm9yOiBzdHJpbmcgPSAnJztcbiAgdXBsb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGFjdGl2ZU1vZGFsOiBOZ2JBY3RpdmVNb2RhbCxcbiAgICBwcml2YXRlIHBheW1lbnRTdWJzY3JpcHRpb25TZXJ2aWNlOiBQYXltZW50U3Vic2NyaXB0aW9uU2VydmljZSxcbiAgICBwcml2YXRlIHRvYXN0OiBUb2FzdFNlcnZpY2UsXG4gICkge31cblxuICBvbkZpbGVTZWxlY3RlZChldmVudDogYW55KSB7XG4gICAgdGhpcy5maWxlRXJyb3IgPSAnJztcbiAgICBjb25zdCBmaWxlOiBGaWxlID0gZXZlbnQ/LnRhcmdldD8uZmlsZXM/LlswXTtcbiAgICBpZiAoIWZpbGUpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlID0gbnVsbDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gUERGIG9ubHkuXG4gICAgaWYgKGZpbGUudHlwZSAhPT0gJ2FwcGxpY2F0aW9uL3BkZicpIHtcbiAgICAgIHRoaXMuZmlsZUVycm9yID0gJ09ubHkgUERGIGZpbGVzIGFyZSBhbGxvd2VkJztcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlID0gbnVsbDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBmaWxlO1xuICB9XG5cbiAgZ2V0IGNhblN1Ym1pdCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmRvY3VtZW50TmFtZS50cmltKCkgJiYgISF0aGlzLnNlbGVjdGVkRmlsZSAmJiAhdGhpcy51cGxvYWRpbmc7XG4gIH1cblxuICB1cGxvYWQoKSB7XG4gICAgaWYgKCF0aGlzLmNhblN1Ym1pdCB8fCAhdGhpcy5zZWxlY3RlZEZpbGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy51cGxvYWRpbmcgPSB0cnVlO1xuICAgIGNvbnN0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9ybURhdGEuYXBwZW5kKCdjbGllbnRJZCcsIHRoaXMuY2xpZW50SWQpO1xuICAgIGZvcm1EYXRhLmFwcGVuZCgnZG9jdW1lbnROYW1lJywgdGhpcy5kb2N1bWVudE5hbWUudHJpbSgpKTtcbiAgICBpZiAodGhpcy5leHBpcnlEYXRlKSB7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoJ2V4cGlyeURhdGUnLCB0aGlzLmV4cGlyeURhdGUpO1xuICAgIH1cbiAgICBmb3JtRGF0YS5hcHBlbmQoJ2ZpbGUnLCB0aGlzLnNlbGVjdGVkRmlsZSk7XG5cbiAgICB0aGlzLnBheW1lbnRTdWJzY3JpcHRpb25TZXJ2aWNlLnVwbG9hZENsaWVudERvY3VtZW50KGZvcm1EYXRhKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgICB0aGlzLnVwbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMudG9hc3QuZ2V0U3VjY2Vzc1RvYXN0KCdEb2N1bWVudCB1cGxvYWRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgICAgICB0aGlzLmFjdGl2ZU1vZGFsLmNsb3NlKCd1cGxvYWRlZCcpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycikgPT4ge1xuICAgICAgICAgIHRoaXMudXBsb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KGVycj8uZXJyb3I/Lm1lc3NhZ2UgfHwgJ1VwbG9hZCBmYWlsZWQnKTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG59IiwiPGRpdiBjbGFzcz1cIm1vZGFsLWNvbnRlbnRcIj5cbiAgICA8ZGl2IGNsYXNzPVwicC02XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkaW5nIG10LTIgbXMtMVwiPlVwbG9hZCBEb2N1bWVudDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1zdWJcIj5QREYgb25seTwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtYi01XCI+XG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJwcm9kdWN0dGV4dCBtYi0yXCI+RG9jdW1lbnQgTmFtZTwvbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbCBib3JkZXItdmFsXCIgWyhuZ01vZGVsKV09XCJkb2N1bWVudE5hbWVcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRW50ZXIgZG9jdW1lbnQgbmFtZVwiIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNVwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwicHJvZHVjdHRleHQgbWItMlwiPkV4cGlyeSBEYXRlPC9sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZGF0ZVwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGJvcmRlci12YWxcIiBbKG5nTW9kZWwpXT1cImV4cGlyeURhdGVcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInByb2R1Y3R0ZXh0IG1iLTJcIj5Eb2N1bWVudCBGaWxlIChQREYpPC9sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGJvcmRlci12YWxcIiBhY2NlcHQ9XCJhcHBsaWNhdGlvbi9wZGZcIlxuICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiIC8+XG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZmlsZUVycm9yXCIgY2xhc3M9XCJ0ZXh0LWRhbmdlciBwcm9kdWN0dGV4dCBtdC0yXCI+e3sgZmlsZUVycm9yIH19PC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggbXQtNyBweS0zXCI+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiYWN0aXZlTW9kYWwuZGlzbWlzcygpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1vdXRsaW5lIGJ0biBjYW5jZWwgbWUtNCB3LTUwXCI+Q2FuY2VsPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwidXBsb2FkKClcIiBbZGlzYWJsZWRdPVwiIWNhblN1Ym1pdFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcHgtNCB3LTUwXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzdWJtaXRcIj57eyB1cGxvYWRpbmcgPyAnVXBsb2FkaW5nLi4uJyA6ICdVcGxvYWQnIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC9kaXY+Il19
@@ -0,0 +1,62 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { Subject, takeUntil } from 'rxjs';
3
+ import { InvoicePreviewComponent } from '../../invoice-preview/invoice-preview.component';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@ng-bootstrap/ng-bootstrap";
6
+ import * as i2 from "../../services/billing.service";
7
+ import * as i3 from "tango-app-ui-shared";
8
+ import * as i4 from "@angular/common";
9
+ export class PurchaseOrderDetailsComponent {
10
+ activeModal;
11
+ modalService;
12
+ billingService;
13
+ toast;
14
+ order;
15
+ destroy$ = new Subject();
16
+ constructor(activeModal, modalService, billingService, toast) {
17
+ this.activeModal = activeModal;
18
+ this.modalService = modalService;
19
+ this.billingService = billingService;
20
+ this.toast = toast;
21
+ }
22
+ statusLabel(status) {
23
+ if (status === 'fullyUsed')
24
+ return 'Fully Used';
25
+ if (status === 'partiallyUsed')
26
+ return 'Partially Used';
27
+ return 'Open';
28
+ }
29
+ // Click an invoice number → fetch that invoice (by number) and preview it.
30
+ previewInvoice(invoiceNumber) {
31
+ if (!invoiceNumber) {
32
+ return;
33
+ }
34
+ this.billingService.getInvoiceById(invoiceNumber).pipe(takeUntil(this.destroy$)).subscribe({
35
+ next: (res) => {
36
+ const invoiceData = res?.data;
37
+ if (!invoiceData) {
38
+ this.toast.getErrorToast('Invoice not found');
39
+ return;
40
+ }
41
+ const modalRef = this.modalService.open(InvoicePreviewComponent, {
42
+ centered: true, size: 'xl', scrollable: true,
43
+ });
44
+ modalRef.componentInstance.invoiceData = invoiceData;
45
+ },
46
+ error: () => this.toast.getErrorToast('Failed to load invoice'),
47
+ });
48
+ }
49
+ ngOnDestroy() {
50
+ this.destroy$.next(true);
51
+ this.destroy$.complete();
52
+ }
53
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderDetailsComponent, deps: [{ token: i1.NgbActiveModal }, { token: i1.NgbModal }, { token: i2.BillingService }, { token: i3.ToastService }], target: i0.ɵɵFactoryTarget.Component });
54
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PurchaseOrderDetailsComponent, selector: "lib-purchase-order-details", inputs: { order: "order" }, ngImport: i0, template: "<div class=\"modal-header\">\n <div>\n <h5 class=\"modal-title mb-0\">Purchase Order \u2014 {{ order?.purchaseOrderNumber }}</h5>\n <div class=\"text-muted small\">{{ order?.companyName }}</div>\n </div>\n <button type=\"button\" class=\"btn-close\" aria-label=\"Close\" (click)=\"activeModal.dismiss()\"></button>\n</div>\n<div class=\"modal-body\">\n <!-- Summary -->\n <div class=\"row mb-4\">\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Total Amount</div>\n <div class=\"fw-bold\">\u20B9{{ order?.totalAmount | number:'1.2-2':'en-IN' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Remaining</div>\n <div class=\"fw-bold\">\u20B9{{ order?.remainingAmount | number:'1.2-2':'en-IN' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Date</div>\n <div class=\"fw-bold\">{{ order?.date | date:'dd MMM yyyy' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Status</div>\n <div class=\"fw-bold\">{{ statusLabel(order?.status) }}</div>\n </div>\n </div>\n\n <div class=\"mb-4\" *ngIf=\"order?.pdfUrl\">\n <a class=\"text-primary cursor-pointer\" [href]=\"order.pdfUrl\" target=\"_blank\" rel=\"noopener\">View PO Document (PDF)</a>\n </div>\n\n <div class=\"fw-bold mb-2\">Usage / Invoices Used</div>\n <div class=\"table-responsive\" style=\"max-height:360px;overflow-y:auto;\">\n <table class=\"table table-row-bordered align-middle mb-0\">\n <thead class=\"sticky-top bg-white\">\n <tr class=\"fw-bold fs-8 text-gray-600\">\n <th class=\"ps-0\">Invoice #</th>\n <th class=\"text-end\">Amount</th>\n <th>Mapped On</th>\n <th>Mapped By</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let u of order?.usage\">\n <td class=\"ps-0\">\n <a class=\"text-primary cursor-pointer\" (click)=\"previewInvoice(u.invoice)\">{{ u.invoice }}</a>\n </td>\n <td class=\"text-end\">\u20B9{{ u.amount | number:'1.2-2':'en-IN' }}</td>\n <td>{{ u.mappedAt | date:'dd MMM yyyy, hh:mm a' }}</td>\n <td>{{ u.mappedBy || '\u2014' }}</td>\n </tr>\n <tr *ngIf=\"!order?.usage?.length\">\n <td colspan=\"4\" class=\"text-center text-muted py-5\">No invoices mapped to this PO yet.</td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-light\" (click)=\"activeModal.dismiss()\">Close</button>\n</div>", styles: [".modal-title{font-weight:700;color:#101828}\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: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
55
+ }
56
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderDetailsComponent, decorators: [{
57
+ type: Component,
58
+ args: [{ selector: 'lib-purchase-order-details', template: "<div class=\"modal-header\">\n <div>\n <h5 class=\"modal-title mb-0\">Purchase Order \u2014 {{ order?.purchaseOrderNumber }}</h5>\n <div class=\"text-muted small\">{{ order?.companyName }}</div>\n </div>\n <button type=\"button\" class=\"btn-close\" aria-label=\"Close\" (click)=\"activeModal.dismiss()\"></button>\n</div>\n<div class=\"modal-body\">\n <!-- Summary -->\n <div class=\"row mb-4\">\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Total Amount</div>\n <div class=\"fw-bold\">\u20B9{{ order?.totalAmount | number:'1.2-2':'en-IN' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Remaining</div>\n <div class=\"fw-bold\">\u20B9{{ order?.remainingAmount | number:'1.2-2':'en-IN' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Date</div>\n <div class=\"fw-bold\">{{ order?.date | date:'dd MMM yyyy' }}</div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"text-muted small\">Status</div>\n <div class=\"fw-bold\">{{ statusLabel(order?.status) }}</div>\n </div>\n </div>\n\n <div class=\"mb-4\" *ngIf=\"order?.pdfUrl\">\n <a class=\"text-primary cursor-pointer\" [href]=\"order.pdfUrl\" target=\"_blank\" rel=\"noopener\">View PO Document (PDF)</a>\n </div>\n\n <div class=\"fw-bold mb-2\">Usage / Invoices Used</div>\n <div class=\"table-responsive\" style=\"max-height:360px;overflow-y:auto;\">\n <table class=\"table table-row-bordered align-middle mb-0\">\n <thead class=\"sticky-top bg-white\">\n <tr class=\"fw-bold fs-8 text-gray-600\">\n <th class=\"ps-0\">Invoice #</th>\n <th class=\"text-end\">Amount</th>\n <th>Mapped On</th>\n <th>Mapped By</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let u of order?.usage\">\n <td class=\"ps-0\">\n <a class=\"text-primary cursor-pointer\" (click)=\"previewInvoice(u.invoice)\">{{ u.invoice }}</a>\n </td>\n <td class=\"text-end\">\u20B9{{ u.amount | number:'1.2-2':'en-IN' }}</td>\n <td>{{ u.mappedAt | date:'dd MMM yyyy, hh:mm a' }}</td>\n <td>{{ u.mappedBy || '\u2014' }}</td>\n </tr>\n <tr *ngIf=\"!order?.usage?.length\">\n <td colspan=\"4\" class=\"text-center text-muted py-5\">No invoices mapped to this PO yet.</td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n<div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-light\" (click)=\"activeModal.dismiss()\">Close</button>\n</div>", styles: [".modal-title{font-weight:700;color:#101828}\n"] }]
59
+ }], ctorParameters: () => [{ type: i1.NgbActiveModal }, { type: i1.NgbModal }, { type: i2.BillingService }, { type: i3.ToastService }], propDecorators: { order: [{
60
+ type: Input
61
+ }] } });
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVyY2hhc2Utb3JkZXItZGV0YWlscy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1tYW5hZ2UtYmlsbGluZy9zcmMvbGliL2NvbXBvbmVudHMvcHVyY2hhc2Utb3JkZXIvcHVyY2hhc2Utb3JkZXItZGV0YWlscy9wdXJjaGFzZS1vcmRlci1kZXRhaWxzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9wdXJjaGFzZS1vcmRlci9wdXJjaGFzZS1vcmRlci1kZXRhaWxzL3B1cmNoYXNlLW9yZGVyLWRldGFpbHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHMUMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0saURBQWlELENBQUM7Ozs7OztBQU8xRixNQUFNLE9BQU8sNkJBQTZCO0lBTS9CO0lBQ0M7SUFDQTtJQUNBO0lBUkQsS0FBSyxDQUFNO0lBRUgsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7SUFFMUMsWUFDUyxXQUEyQixFQUMxQixZQUFzQixFQUN0QixjQUE4QixFQUM5QixLQUFtQjtRQUhwQixnQkFBVyxHQUFYLFdBQVcsQ0FBZ0I7UUFDMUIsaUJBQVksR0FBWixZQUFZLENBQVU7UUFDdEIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLFVBQUssR0FBTCxLQUFLLENBQWM7SUFDMUIsQ0FBQztJQUVKLFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLElBQUksTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLFlBQVksQ0FBQztRQUNoRCxJQUFJLE1BQU0sS0FBSyxlQUFlO1lBQUUsT0FBTyxnQkFBZ0IsQ0FBQztRQUN4RCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLGNBQWMsQ0FBQyxhQUFxQjtRQUNsQyxJQUFJLENBQUMsYUFBYSxFQUFFO1lBQ2xCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQ3pGLElBQUksRUFBRSxDQUFDLEdBQVEsRUFBRSxFQUFFO2dCQUNqQixNQUFNLFdBQVcsR0FBRyxHQUFHLEVBQUUsSUFBSSxDQUFDO2dCQUM5QixJQUFJLENBQUMsV0FBVyxFQUFFO29CQUNoQixJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO29CQUM5QyxPQUFPO2lCQUNSO2dCQUNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLHVCQUF1QixFQUFFO29CQUMvRCxRQUFRLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUk7aUJBQzdDLENBQUMsQ0FBQztnQkFDSCxRQUFRLENBQUMsaUJBQWlCLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztZQUN2RCxDQUFDO1lBQ0QsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDO1NBQ2hFLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO3dHQTFDVSw2QkFBNkI7NEZBQTdCLDZCQUE2Qiw4RkNaMUMsKzFGQTZETTs7NEZEakRPLDZCQUE2QjtrQkFMekMsU0FBUzsrQkFDRSw0QkFBNEI7a0tBSzdCLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5nYkFjdGl2ZU1vZGFsLCBOZ2JNb2RhbCB9IGZyb20gJ0BuZy1ib290c3RyYXAvbmctYm9vdHN0cmFwJztcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLXNoYXJlZCc7XG5pbXBvcnQgeyBCaWxsaW5nU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2JpbGxpbmcuc2VydmljZSc7XG5pbXBvcnQgeyBJbnZvaWNlUHJldmlld0NvbXBvbmVudCB9IGZyb20gJy4uLy4uL2ludm9pY2UtcHJldmlldy9pbnZvaWNlLXByZXZpZXcuY29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLXB1cmNoYXNlLW9yZGVyLWRldGFpbHMnLFxuICB0ZW1wbGF0ZVVybDogJy4vcHVyY2hhc2Utb3JkZXItZGV0YWlscy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9wdXJjaGFzZS1vcmRlci1kZXRhaWxzLmNvbXBvbmVudC5zY3NzJ1xufSlcbmV4cG9ydCBjbGFzcyBQdXJjaGFzZU9yZGVyRGV0YWlsc0NvbXBvbmVudCB7XG4gIEBJbnB1dCgpIG9yZGVyOiBhbnk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGFjdGl2ZU1vZGFsOiBOZ2JBY3RpdmVNb2RhbCxcbiAgICBwcml2YXRlIG1vZGFsU2VydmljZTogTmdiTW9kYWwsXG4gICAgcHJpdmF0ZSBiaWxsaW5nU2VydmljZTogQmlsbGluZ1NlcnZpY2UsXG4gICAgcHJpdmF0ZSB0b2FzdDogVG9hc3RTZXJ2aWNlLFxuICApIHt9XG5cbiAgc3RhdHVzTGFiZWwoc3RhdHVzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChzdGF0dXMgPT09ICdmdWxseVVzZWQnKSByZXR1cm4gJ0Z1bGx5IFVzZWQnO1xuICAgIGlmIChzdGF0dXMgPT09ICdwYXJ0aWFsbHlVc2VkJykgcmV0dXJuICdQYXJ0aWFsbHkgVXNlZCc7XG4gICAgcmV0dXJuICdPcGVuJztcbiAgfVxuXG4gIC8vIENsaWNrIGFuIGludm9pY2UgbnVtYmVyIOKGkiBmZXRjaCB0aGF0IGludm9pY2UgKGJ5IG51bWJlcikgYW5kIHByZXZpZXcgaXQuXG4gIHByZXZpZXdJbnZvaWNlKGludm9pY2VOdW1iZXI6IHN0cmluZykge1xuICAgIGlmICghaW52b2ljZU51bWJlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmJpbGxpbmdTZXJ2aWNlLmdldEludm9pY2VCeUlkKGludm9pY2VOdW1iZXIpLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGludm9pY2VEYXRhID0gcmVzPy5kYXRhO1xuICAgICAgICBpZiAoIWludm9pY2VEYXRhKSB7XG4gICAgICAgICAgdGhpcy50b2FzdC5nZXRFcnJvclRvYXN0KCdJbnZvaWNlIG5vdCBmb3VuZCcpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oSW52b2ljZVByZXZpZXdDb21wb25lbnQsIHtcbiAgICAgICAgICBjZW50ZXJlZDogdHJ1ZSwgc2l6ZTogJ3hsJywgc2Nyb2xsYWJsZTogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIG1vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLmludm9pY2VEYXRhID0gaW52b2ljZURhdGE7XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+IHRoaXMudG9hc3QuZ2V0RXJyb3JUb2FzdCgnRmFpbGVkIHRvIGxvYWQgaW52b2ljZScpLFxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxufSIsIjxkaXYgY2xhc3M9XCJtb2RhbC1oZWFkZXJcIj5cbiAgICA8ZGl2PlxuICAgICAgICA8aDUgY2xhc3M9XCJtb2RhbC10aXRsZSBtYi0wXCI+UHVyY2hhc2UgT3JkZXIg4oCUIHt7IG9yZGVyPy5wdXJjaGFzZU9yZGVyTnVtYmVyIH19PC9oNT5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj57eyBvcmRlcj8uY29tcGFueU5hbWUgfX08L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbG9zZVwiIGFyaWEtbGFiZWw9XCJDbG9zZVwiIChjbGljayk9XCJhY3RpdmVNb2RhbC5kaXNtaXNzKClcIj48L2J1dHRvbj5cbjwvZGl2PlxuPGRpdiBjbGFzcz1cIm1vZGFsLWJvZHlcIj5cbiAgICA8IS0tIFN1bW1hcnkgLS0+XG4gICAgPGRpdiBjbGFzcz1cInJvdyBtYi00XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtM1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj5Ub3RhbCBBbW91bnQ8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmdy1ib2xkXCI+4oK5e3sgb3JkZXI/LnRvdGFsQW1vdW50IHwgbnVtYmVyOicxLjItMic6J2VuLUlOJyB9fTwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0zXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiPlJlbWFpbmluZzwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZ3LWJvbGRcIj7igrl7eyBvcmRlcj8ucmVtYWluaW5nQW1vdW50IHwgbnVtYmVyOicxLjItMic6J2VuLUlOJyB9fTwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0zXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiPkRhdGU8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmdy1ib2xkXCI+e3sgb3JkZXI/LmRhdGUgfCBkYXRlOidkZCBNTU0geXl5eScgfX08L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtM1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj5TdGF0dXM8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmdy1ib2xkXCI+e3sgc3RhdHVzTGFiZWwob3JkZXI/LnN0YXR1cykgfX08L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwibWItNFwiICpuZ0lmPVwib3JkZXI/LnBkZlVybFwiPlxuICAgICAgICA8YSBjbGFzcz1cInRleHQtcHJpbWFyeSBjdXJzb3ItcG9pbnRlclwiIFtocmVmXT1cIm9yZGVyLnBkZlVybFwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyXCI+VmlldyBQTyBEb2N1bWVudCAoUERGKTwvYT5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJmdy1ib2xkIG1iLTJcIj5Vc2FnZSAvIEludm9pY2VzIFVzZWQ8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwidGFibGUtcmVzcG9uc2l2ZVwiIHN0eWxlPVwibWF4LWhlaWdodDozNjBweDtvdmVyZmxvdy15OmF1dG87XCI+XG4gICAgICAgIDx0YWJsZSBjbGFzcz1cInRhYmxlIHRhYmxlLXJvdy1ib3JkZXJlZCBhbGlnbi1taWRkbGUgbWItMFwiPlxuICAgICAgICAgICAgPHRoZWFkIGNsYXNzPVwic3RpY2t5LXRvcCBiZy13aGl0ZVwiPlxuICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cImZ3LWJvbGQgZnMtOCB0ZXh0LWdyYXktNjAwXCI+XG4gICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cInBzLTBcIj5JbnZvaWNlICM8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJ0ZXh0LWVuZFwiPkFtb3VudDwvdGg+XG4gICAgICAgICAgICAgICAgICAgIDx0aD5NYXBwZWQgT248L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGg+TWFwcGVkIEJ5PC90aD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgICAgICA8dHIgKm5nRm9yPVwibGV0IHUgb2Ygb3JkZXI/LnVzYWdlXCI+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInBzLTBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxhIGNsYXNzPVwidGV4dC1wcmltYXJ5IGN1cnNvci1wb2ludGVyXCIgKGNsaWNrKT1cInByZXZpZXdJbnZvaWNlKHUuaW52b2ljZSlcIj57eyB1Lmludm9pY2UgfX08L2E+XG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInRleHQtZW5kXCI+4oK5e3sgdS5hbW91bnQgfCBudW1iZXI6JzEuMi0yJzonZW4tSU4nIH19PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPHRkPnt7IHUubWFwcGVkQXQgfCBkYXRlOidkZCBNTU0geXl5eSwgaGg6bW0gYScgfX08L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQ+e3sgdS5tYXBwZWRCeSB8fCAn4oCUJyB9fTwvdGQ+XG4gICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICA8dHIgKm5nSWY9XCIhb3JkZXI/LnVzYWdlPy5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49XCI0XCIgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIHB5LTVcIj5ObyBpbnZvaWNlcyBtYXBwZWQgdG8gdGhpcyBQTyB5ZXQuPC90ZD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgPC90YWJsZT5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuPGRpdiBjbGFzcz1cIm1vZGFsLWZvb3RlclwiPlxuICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1saWdodFwiIChjbGljayk9XCJhY3RpdmVNb2RhbC5kaXNtaXNzKClcIj5DbG9zZTwvYnV0dG9uPlxuPC9kaXY+Il19
@@ -0,0 +1,87 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { Subject, takeUntil } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@ng-bootstrap/ng-bootstrap";
5
+ import * as i2 from "../../services/billing.service";
6
+ import * as i3 from "tango-app-ui-shared";
7
+ import * as i4 from "@angular/common";
8
+ import * as i5 from "@angular/forms";
9
+ export class PurchaseOrderFormComponent {
10
+ activeModal;
11
+ billingService;
12
+ toast;
13
+ clientId = '';
14
+ companyName = '';
15
+ purchaseOrderNumber = '';
16
+ totalAmount = null;
17
+ date = '';
18
+ selectedFile = null;
19
+ fileError = '';
20
+ saving = false;
21
+ destroy$ = new Subject();
22
+ constructor(activeModal, billingService, toast) {
23
+ this.activeModal = activeModal;
24
+ this.billingService = billingService;
25
+ this.toast = toast;
26
+ }
27
+ get canSubmit() {
28
+ return !!this.purchaseOrderNumber.trim()
29
+ && this.totalAmount != null && Number(this.totalAmount) > 0
30
+ && !this.saving;
31
+ }
32
+ onFileSelected(event) {
33
+ this.fileError = '';
34
+ const file = event?.target?.files?.[0];
35
+ if (!file) {
36
+ this.selectedFile = null;
37
+ return;
38
+ }
39
+ if (file.type !== 'application/pdf') {
40
+ this.fileError = 'Only PDF files are allowed';
41
+ this.selectedFile = null;
42
+ return;
43
+ }
44
+ this.selectedFile = file;
45
+ }
46
+ save() {
47
+ if (!this.canSubmit) {
48
+ return;
49
+ }
50
+ this.saving = true;
51
+ const formData = new FormData();
52
+ formData.append('clientId', this.clientId);
53
+ formData.append('companyName', this.companyName.trim());
54
+ formData.append('purchaseOrderNumber', this.purchaseOrderNumber.trim());
55
+ formData.append('totalAmount', String(Number(this.totalAmount)));
56
+ if (this.date) {
57
+ formData.append('date', this.date);
58
+ }
59
+ if (this.selectedFile) {
60
+ formData.append('file', this.selectedFile);
61
+ }
62
+ this.billingService.createPurchaseOrder(formData).pipe(takeUntil(this.destroy$)).subscribe({
63
+ next: () => {
64
+ this.saving = false;
65
+ this.toast.getSuccessToast('Purchase order created');
66
+ this.activeModal.close('success');
67
+ },
68
+ error: (err) => {
69
+ this.saving = false;
70
+ this.toast.getErrorToast(err?.error?.message || 'Failed to create purchase order');
71
+ },
72
+ });
73
+ }
74
+ ngOnDestroy() {
75
+ this.destroy$.next(true);
76
+ this.destroy$.complete();
77
+ }
78
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderFormComponent, deps: [{ token: i1.NgbActiveModal }, { token: i2.BillingService }, { token: i3.ToastService }], target: i0.ɵɵFactoryTarget.Component });
79
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PurchaseOrderFormComponent, selector: "lib-purchase-order-form", inputs: { clientId: "clientId" }, ngImport: i0, template: "<div class=\"modal-content\">\n <div class=\"p-6\">\n <div class=\"heading mt-2 ms-1\">Add Purchase Order</div>\n </div>\n <div class=\"modal-body\">\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Company Name</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"companyName\"\n placeholder=\"Enter company name\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Purchase Order Number</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"purchaseOrderNumber\"\n placeholder=\"Enter PO number\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Total Amount</label>\n <input type=\"number\" min=\"0\" class=\"form-control border-val\" [(ngModel)]=\"totalAmount\"\n placeholder=\"0\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Date</label>\n <input type=\"date\" class=\"form-control border-val\" [(ngModel)]=\"date\" />\n </div>\n <div class=\"mb-2\">\n <label class=\"producttext mb-2\">PO Document (PDF)</label>\n <input type=\"file\" class=\"form-control border-val\" accept=\"application/pdf\"\n (change)=\"onFileSelected($event)\" />\n <div *ngIf=\"fileError\" class=\"text-danger producttext mt-2\">{{ fileError }}</div>\n </div>\n\n <div class=\"d-flex mt-7 py-3\">\n <button type=\"button\" (click)=\"activeModal.dismiss()\"\n class=\"btn-outline btn cancel me-4 w-50\">Cancel</button>\n <button type=\"button\" (click)=\"save()\" [disabled]=\"!canSubmit\"\n class=\"btn btn-primary px-4 w-50\">\n <span class=\"submit\">{{ saving ? 'Saving...' : 'Save' }}</span>\n </button>\n </div>\n </div>\n</div>", styles: [".heading{font-size:18px;font-weight:700;color:#101828}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.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: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
80
+ }
81
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderFormComponent, decorators: [{
82
+ type: Component,
83
+ args: [{ selector: 'lib-purchase-order-form', template: "<div class=\"modal-content\">\n <div class=\"p-6\">\n <div class=\"heading mt-2 ms-1\">Add Purchase Order</div>\n </div>\n <div class=\"modal-body\">\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Company Name</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"companyName\"\n placeholder=\"Enter company name\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Purchase Order Number</label>\n <input type=\"text\" class=\"form-control border-val\" [(ngModel)]=\"purchaseOrderNumber\"\n placeholder=\"Enter PO number\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Total Amount</label>\n <input type=\"number\" min=\"0\" class=\"form-control border-val\" [(ngModel)]=\"totalAmount\"\n placeholder=\"0\" />\n </div>\n <div class=\"mb-5\">\n <label class=\"producttext mb-2\">Date</label>\n <input type=\"date\" class=\"form-control border-val\" [(ngModel)]=\"date\" />\n </div>\n <div class=\"mb-2\">\n <label class=\"producttext mb-2\">PO Document (PDF)</label>\n <input type=\"file\" class=\"form-control border-val\" accept=\"application/pdf\"\n (change)=\"onFileSelected($event)\" />\n <div *ngIf=\"fileError\" class=\"text-danger producttext mt-2\">{{ fileError }}</div>\n </div>\n\n <div class=\"d-flex mt-7 py-3\">\n <button type=\"button\" (click)=\"activeModal.dismiss()\"\n class=\"btn-outline btn cancel me-4 w-50\">Cancel</button>\n <button type=\"button\" (click)=\"save()\" [disabled]=\"!canSubmit\"\n class=\"btn btn-primary px-4 w-50\">\n <span class=\"submit\">{{ saving ? 'Saving...' : 'Save' }}</span>\n </button>\n </div>\n </div>\n</div>", styles: [".heading{font-size:18px;font-weight:700;color:#101828}\n"] }]
84
+ }], ctorParameters: () => [{ type: i1.NgbActiveModal }, { type: i2.BillingService }, { type: i3.ToastService }], propDecorators: { clientId: [{
85
+ type: Input
86
+ }] } });
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVyY2hhc2Utb3JkZXItZm9ybS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1tYW5hZ2UtYmlsbGluZy9zcmMvbGliL2NvbXBvbmVudHMvcHVyY2hhc2Utb3JkZXIvcHVyY2hhc2Utb3JkZXItZm9ybS9wdXJjaGFzZS1vcmRlci1mb3JtLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9wdXJjaGFzZS1vcmRlci9wdXJjaGFzZS1vcmRlci1mb3JtL3B1cmNoYXNlLW9yZGVyLWZvcm0uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7QUFTMUMsTUFBTSxPQUFPLDBCQUEwQjtJQWM1QjtJQUNDO0lBQ0E7SUFmRCxRQUFRLEdBQVcsRUFBRSxDQUFDO0lBRS9CLFdBQVcsR0FBVyxFQUFFLENBQUM7SUFDekIsbUJBQW1CLEdBQVcsRUFBRSxDQUFDO0lBQ2pDLFdBQVcsR0FBa0IsSUFBSSxDQUFDO0lBQ2xDLElBQUksR0FBVyxFQUFFLENBQUM7SUFDbEIsWUFBWSxHQUFnQixJQUFJLENBQUM7SUFDakMsU0FBUyxHQUFXLEVBQUUsQ0FBQztJQUN2QixNQUFNLEdBQVksS0FBSyxDQUFDO0lBRVAsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7SUFFMUMsWUFDUyxXQUEyQixFQUMxQixjQUE4QixFQUM5QixLQUFtQjtRQUZwQixnQkFBVyxHQUFYLFdBQVcsQ0FBZ0I7UUFDMUIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLFVBQUssR0FBTCxLQUFLLENB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QUM7SUFDM0IsQ0FBQzt3R0F4RVUsMEJBQTBCOzRGQUExQiwwQkFBMEIsaUdDWHZDLHU5REF3Q007OzRGRDdCTywwQkFBMEI7a0JBTHRDLFNBQVM7K0JBQ0UseUJBQXlCOzJJQUsxQixRQUFRO3NCQUFoQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmdiQWN0aXZlTW9kYWwgfSBmcm9tICdAbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcCc7XG5pbXBvcnQgeyBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRvYXN0U2VydmljZSB9IGZyb20gJ3RhbmdvLWFwcC11aS1zaGFyZWQnO1xuaW1wb3J0IHsgQmlsbGluZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9iaWxsaW5nLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItcHVyY2hhc2Utb3JkZXItZm9ybScsXG4gIHRlbXBsYXRlVXJsOiAnLi9wdXJjaGFzZS1vcmRlci1mb3JtLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL3B1cmNoYXNlLW9yZGVyLWZvcm0uY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIFB1cmNoYXNlT3JkZXJGb3JtQ29tcG9uZW50IHtcbiAgQElucHV0KCkgY2xpZW50SWQ6IHN0cmluZyA9ICcnO1xuXG4gIGNvbXBhbnlOYW1lOiBzdHJpbmcgPSAnJztcbiAgcHVyY2hhc2VPcmRlck51bWJlcjogc3RyaW5nID0gJyc7XG4gIHRvdGFsQW1vdW50OiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgZGF0ZTogc3RyaW5nID0gJyc7XG4gIHNlbGVjdGVkRmlsZTogRmlsZSB8IG51bGwgPSBudWxsO1xuICBmaWxlRXJyb3I6IHN0cmluZyA9ICcnO1xuICBzYXZpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgYWN0aXZlTW9kYWw6IE5nYkFjdGl2ZU1vZGFsLFxuICAgIHByaXZhdGUgYmlsbGluZ1NlcnZpY2U6IEJpbGxpbmdTZXJ2aWNlLFxuICAgIHByaXZhdGUgdG9hc3Q6IFRvYXN0U2VydmljZSxcbiAgKSB7fVxuXG4gIGdldCBjYW5TdWJtaXQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5wdXJjaGFzZU9yZGVyTnVtYmVyLnRyaW0oKVxuICAgICAgJiYgdGhpcy50b3RhbEFtb3VudCAhPSBudWxsICYmIE51bWJlcih0aGlzLnRvdGFsQW1vdW50KSA+IDBcbiAgICAgICYmICF0aGlzLnNhdmluZztcbiAgfVxuXG4gIG9uRmlsZVNlbGVjdGVkKGV2ZW50OiBhbnkpIHtcbiAgICB0aGlzLmZpbGVFcnJvciA9ICcnO1xuICAgIGNvbnN0IGZpbGU6IEZpbGUgPSBldmVudD8udGFyZ2V0Py5maWxlcz8uWzBdO1xuICAgIGlmICghZmlsZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZmlsZS50eXBlICE9PSAnYXBwbGljYXRpb24vcGRmJykge1xuICAgICAgdGhpcy5maWxlRXJyb3IgPSAnT25seSBQREYgZmlsZXMgYXJlIGFsbG93ZWQnO1xuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnNlbGVjdGVkRmlsZSA9IGZpbGU7XG4gIH1cblxuICBzYXZlKCkge1xuICAgIGlmICghdGhpcy5jYW5TdWJtaXQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zYXZpbmcgPSB0cnVlO1xuICAgIGNvbnN0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9ybURhdGEuYXBwZW5kKCdjbGllbnRJZCcsIHRoaXMuY2xpZW50SWQpO1xuICAgIGZvcm1EYXRhLmFwcGVuZCgnY29tcGFueU5hbWUnLCB0aGlzLmNvbXBhbnlOYW1lLnRyaW0oKSk7XG4gICAgZm9ybURhdGEuYXBwZW5kKCdwdXJjaGFzZU9yZGVyTnVtYmVyJywgdGhpcy5wdXJjaGFzZU9yZGVyTnVtYmVyLnRyaW0oKSk7XG4gICAgZm9ybURhdGEuYXBwZW5kKCd0b3RhbEFtb3VudCcsIFN0cmluZyhOdW1iZXIodGhpcy50b3RhbEFtb3VudCkpKTtcbiAgICBpZiAodGhpcy5kYXRlKSB7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoJ2RhdGUnLCB0aGlzLmRhdGUpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zZWxlY3RlZEZpbGUpIHtcbiAgICAgIGZvcm1EYXRhLmFwcGVuZCgnZmlsZScsIHRoaXMuc2VsZWN0ZWRGaWxlKTtcbiAgICB9XG4gICAgdGhpcy5iaWxsaW5nU2VydmljZS5jcmVhdGVQdXJjaGFzZU9yZGVyKGZvcm1EYXRhKS5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6ICgpID0+IHtcbiAgICAgICAgdGhpcy5zYXZpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy50b2FzdC5nZXRTdWNjZXNzVG9hc3QoJ1B1cmNoYXNlIG9yZGVyIGNyZWF0ZWQnKTtcbiAgICAgICAgdGhpcy5hY3RpdmVNb2RhbC5jbG9zZSgnc3VjY2VzcycpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoZXJyKSA9PiB7XG4gICAgICAgIHRoaXMuc2F2aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMudG9hc3QuZ2V0RXJyb3JUb2FzdChlcnI/LmVycm9yPy5tZXNzYWdlIHx8ICdGYWlsZWQgdG8gY3JlYXRlIHB1cmNoYXNlIG9yZGVyJyk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxufSIsIjxkaXYgY2xhc3M9XCJtb2RhbC1jb250ZW50XCI+XG4gICAgPGRpdiBjbGFzcz1cInAtNlwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGluZyBtdC0yIG1zLTFcIj5BZGQgUHVyY2hhc2UgT3JkZXI8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtYm9keVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNVwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwicHJvZHVjdHRleHQgbWItMlwiPkNvbXBhbnkgTmFtZTwvbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbCBib3JkZXItdmFsXCIgWyhuZ01vZGVsKV09XCJjb21wYW55TmFtZVwiXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciBjb21wYW55IG5hbWVcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTVcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInByb2R1Y3R0ZXh0IG1iLTJcIj5QdXJjaGFzZSBPcmRlciBOdW1iZXI8L2xhYmVsPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgYm9yZGVyLXZhbFwiIFsobmdNb2RlbCldPVwicHVyY2hhc2VPcmRlck51bWJlclwiXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciBQTyBudW1iZXJcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTVcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInByb2R1Y3R0ZXh0IG1iLTJcIj5Ub3RhbCBBbW91bnQ8L2xhYmVsPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIiBtaW49XCIwXCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgYm9yZGVyLXZhbFwiIFsobmdNb2RlbCldPVwidG90YWxBbW91bnRcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiMFwiIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNVwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwicHJvZHVjdHRleHQgbWItMlwiPkRhdGU8L2xhYmVsPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJkYXRlXCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgYm9yZGVyLXZhbFwiIFsobmdNb2RlbCldPVwiZGF0ZVwiIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItMlwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwicHJvZHVjdHRleHQgbWItMlwiPlBPIERvY3VtZW50IChQREYpPC9sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGJvcmRlci12YWxcIiBhY2NlcHQ9XCJhcHBsaWNhdGlvbi9wZGZcIlxuICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiIC8+XG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZmlsZUVycm9yXCIgY2xhc3M9XCJ0ZXh0LWRhbmdlciBwcm9kdWN0dGV4dCBtdC0yXCI+e3sgZmlsZUVycm9yIH19PC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggbXQtNyBweS0zXCI+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiYWN0aXZlTW9kYWwuZGlzbWlzcygpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1vdXRsaW5lIGJ0biBjYW5jZWwgbWUtNCB3LTUwXCI+Q2FuY2VsPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwic2F2ZSgpXCIgW2Rpc2FibGVkXT1cIiFjYW5TdWJtaXRcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHB4LTQgdy01MFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3VibWl0XCI+e3sgc2F2aW5nID8gJ1NhdmluZy4uLicgOiAnU2F2ZScgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj4iXX0=
@@ -0,0 +1,104 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { Subject, takeUntil } from 'rxjs';
3
+ import { PurchaseOrderFormComponent } from './purchase-order-form/purchase-order-form.component';
4
+ import { PurchaseOrderDetailsComponent } from './purchase-order-details/purchase-order-details.component';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "../services/billing.service";
7
+ import * as i2 from "@ng-bootstrap/ng-bootstrap";
8
+ import * as i3 from "tango-app-ui-shared";
9
+ import * as i4 from "@angular/common";
10
+ export class PurchaseOrderComponent {
11
+ billingService;
12
+ modalService;
13
+ toast;
14
+ changeDetector;
15
+ clientId = '';
16
+ orders = [];
17
+ loading = true;
18
+ noData = false;
19
+ destroy$ = new Subject();
20
+ constructor(billingService, modalService, toast, changeDetector) {
21
+ this.billingService = billingService;
22
+ this.modalService = modalService;
23
+ this.toast = toast;
24
+ this.changeDetector = changeDetector;
25
+ }
26
+ ngOnInit() {
27
+ if (this.clientId) {
28
+ this.loadOrders();
29
+ }
30
+ }
31
+ ngOnChanges(changes) {
32
+ if (changes['clientId'] && !changes['clientId'].firstChange && this.clientId) {
33
+ this.loadOrders();
34
+ }
35
+ }
36
+ ngOnDestroy() {
37
+ this.destroy$.next(true);
38
+ this.destroy$.complete();
39
+ }
40
+ loadOrders() {
41
+ this.loading = true;
42
+ this.noData = false;
43
+ this.billingService.getPurchaseOrders(this.clientId).pipe(takeUntil(this.destroy$)).subscribe({
44
+ next: (res) => {
45
+ this.orders = res?.data?.purchaseOrders || [];
46
+ this.noData = this.orders.length === 0;
47
+ this.loading = false;
48
+ this.changeDetector.detectChanges();
49
+ },
50
+ error: () => {
51
+ this.orders = [];
52
+ this.noData = true;
53
+ this.loading = false;
54
+ this.changeDetector.detectChanges();
55
+ },
56
+ });
57
+ }
58
+ addPurchaseOrder() {
59
+ const modalRef = this.modalService.open(PurchaseOrderFormComponent, {
60
+ centered: true, scrollable: true,
61
+ });
62
+ modalRef.componentInstance.clientId = this.clientId;
63
+ modalRef.result.then((result) => {
64
+ if (result === 'success') {
65
+ this.loadOrders();
66
+ }
67
+ }, () => { });
68
+ }
69
+ // Human-readable status label.
70
+ statusLabel(status) {
71
+ if (status === 'fullyUsed')
72
+ return 'Fully Used';
73
+ if (status === 'partiallyUsed')
74
+ return 'Partially Used';
75
+ return 'Open';
76
+ }
77
+ statusClass(status) {
78
+ if (status === 'fullyUsed')
79
+ return 'badge badge-light-danger';
80
+ if (status === 'partiallyUsed')
81
+ return 'badge badge-light-warning';
82
+ return 'badge badge-light-success';
83
+ }
84
+ // Invoice numbers that consumed this PO (for the "invoices used" column).
85
+ usedInvoices(order) {
86
+ return (order?.usage || []).map((u) => u.invoice).filter(Boolean).join(', ');
87
+ }
88
+ // Open the usage-details popup (usage rows + clickable invoice previews).
89
+ viewDetails(order) {
90
+ const modalRef = this.modalService.open(PurchaseOrderDetailsComponent, {
91
+ centered: true, size: 'lg', scrollable: true,
92
+ });
93
+ modalRef.componentInstance.order = order;
94
+ }
95
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderComponent, deps: [{ token: i1.BillingService }, { token: i2.NgbModal }, { token: i3.ToastService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
96
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PurchaseOrderComponent, selector: "lib-purchase-order", inputs: { clientId: "clientId" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"invoices-section\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center gap-2\">\n <span class=\"billingheader\">Purchase Orders</span>\n <span class=\"badge bg-light text-dark ms-1\">{{ orders.length }} total</span>\n </div>\n <button type=\"button\" (click)=\"addPurchaseOrder()\" class=\"btn btn-primary text-nowrap\">\n <span class=\"ms-1\">Add Purchase Order</span>\n </button>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-muted py-4\">Loading\u2026</div>\n\n <div *ngIf=\"!loading\" class=\"table-responsive\">\n <table class=\"table accordion table bottom-border text-nowrap\">\n <thead>\n <tr>\n <th>Company Name</th>\n <th>PO Number</th>\n <th class=\"text-end\">Total Amount</th>\n <th class=\"text-end\">Remaining</th>\n <th>Date</th>\n <th>Status</th>\n <th>Invoices Used</th>\n <th class=\"text-center\">Action</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let o of orders\">\n <td>{{ o.companyName || '\u2014' }}</td>\n <td><strong>{{ o.purchaseOrderNumber }}</strong></td>\n <td class=\"text-end\">\u20B9{{ o.totalAmount | number:'1.2-2':'en-IN' }}</td>\n <td class=\"text-end\">\u20B9{{ o.remainingAmount | number:'1.2-2':'en-IN' }}</td>\n <td>{{ o.date | date: 'dd MMM yyyy' }}</td>\n <td><span [ngClass]=\"statusClass(o.status)\">{{ statusLabel(o.status) }}</span></td>\n <td>\n <span *ngIf=\"usedInvoices(o)\">{{ usedInvoices(o) }}</span>\n <span *ngIf=\"!usedInvoices(o)\" class=\"text-muted\">\u2014</span>\n </td>\n <td class=\"text-center\">\n <span class=\"cursor-pointer\" (click)=\"viewDetails(o)\" title=\"View details\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\" stroke=\"#667085\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"#667085\" stroke-width=\"1.6\"/>\n </svg>\n </span>\n </td>\n </tr>\n <tr *ngIf=\"noData\">\n <td colspan=\"8\" class=\"text-center text-muted py-5\">No purchase orders yet.</td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", styles: [".billingheader{font-size:16px;font-weight:700;color:#101828}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
97
+ }
98
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PurchaseOrderComponent, decorators: [{
99
+ type: Component,
100
+ args: [{ selector: 'lib-purchase-order', template: "<div class=\"invoices-section\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center gap-2\">\n <span class=\"billingheader\">Purchase Orders</span>\n <span class=\"badge bg-light text-dark ms-1\">{{ orders.length }} total</span>\n </div>\n <button type=\"button\" (click)=\"addPurchaseOrder()\" class=\"btn btn-primary text-nowrap\">\n <span class=\"ms-1\">Add Purchase Order</span>\n </button>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-muted py-4\">Loading\u2026</div>\n\n <div *ngIf=\"!loading\" class=\"table-responsive\">\n <table class=\"table accordion table bottom-border text-nowrap\">\n <thead>\n <tr>\n <th>Company Name</th>\n <th>PO Number</th>\n <th class=\"text-end\">Total Amount</th>\n <th class=\"text-end\">Remaining</th>\n <th>Date</th>\n <th>Status</th>\n <th>Invoices Used</th>\n <th class=\"text-center\">Action</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let o of orders\">\n <td>{{ o.companyName || '\u2014' }}</td>\n <td><strong>{{ o.purchaseOrderNumber }}</strong></td>\n <td class=\"text-end\">\u20B9{{ o.totalAmount | number:'1.2-2':'en-IN' }}</td>\n <td class=\"text-end\">\u20B9{{ o.remainingAmount | number:'1.2-2':'en-IN' }}</td>\n <td>{{ o.date | date: 'dd MMM yyyy' }}</td>\n <td><span [ngClass]=\"statusClass(o.status)\">{{ statusLabel(o.status) }}</span></td>\n <td>\n <span *ngIf=\"usedInvoices(o)\">{{ usedInvoices(o) }}</span>\n <span *ngIf=\"!usedInvoices(o)\" class=\"text-muted\">\u2014</span>\n </td>\n <td class=\"text-center\">\n <span class=\"cursor-pointer\" (click)=\"viewDetails(o)\" title=\"View details\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\" stroke=\"#667085\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"#667085\" stroke-width=\"1.6\"/>\n </svg>\n </span>\n </td>\n </tr>\n <tr *ngIf=\"noData\">\n <td colspan=\"8\" class=\"text-center text-muted py-5\">No purchase orders yet.</td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", styles: [".billingheader{font-size:16px;font-weight:700;color:#101828}\n"] }]
101
+ }], ctorParameters: () => [{ type: i1.BillingService }, { type: i2.NgbModal }, { type: i3.ToastService }, { type: i0.ChangeDetectorRef }], propDecorators: { clientId: [{
102
+ type: Input
103
+ }] } });
104
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVyY2hhc2Utb3JkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tbWFuYWdlLWJpbGxpbmcvc3JjL2xpYi9jb21wb25lbnRzL3B1cmNoYXNlLW9yZGVyL3B1cmNoYXNlLW9yZGVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS1iaWxsaW5nL3NyYy9saWIvY29tcG9uZW50cy9wdXJjaGFzZS1vcmRlci9wdXJjaGFzZS1vcmRlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXFCLFNBQVMsRUFBRSxLQUFLLEVBQStDLE1BQU0sZUFBZSxDQUFDO0FBRWpILE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRzFDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHFEQUFxRCxDQUFDO0FBQ2pHLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLDJEQUEyRCxDQUFDOzs7Ozs7QUFPMUcsTUFBTSxPQUFPLHNCQUFzQjtJQVV2QjtJQUNBO0lBQ0E7SUFDQTtJQVpELFFBQVEsR0FBVyxFQUFFLENBQUM7SUFFL0IsTUFBTSxHQUFVLEVBQUUsQ0FBQztJQUNuQixPQUFPLEdBQVksSUFBSSxDQUFDO0lBQ3hCLE1BQU0sR0FBWSxLQUFLLENBQUM7SUFFUCxRQUFRLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQUUxQyxZQUNVLGNBQThCLEVBQzlCLFlBQXNCLEVBQ3RCLEtBQW1CLEVBQ25CLGNBQWlDO1FBSGpDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixpQkFBWSxHQUFaLFlBQVksQ0FBVTtRQUN0QixVQUFLLEdBQUwsS0FBSyxDQUFjO1FBQ25CLG1CQUFjLEdBQWQsY0FBYyxDQUFtQjtJQUN4QyxDQUFDO0lBRUosUUFBUTtRQUNOLElBQUks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LEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BGLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsV0FBVyxDQUFDLEtBQVU7UUFDcEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsNkJBQTZCLEVBQUU7WUFDckUsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJO1NBQzdDLENBQUMsQ0FBQztRQUNILFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQzNDLENBQUM7d0dBeEZVLHNCQUFzQjs0RkFBdEIsc0JBQXNCLGlIQ2JuQyxrNUZBc0RNOzs0RkR6Q08sc0JBQXNCO2tCQUxsQyxTQUFTOytCQUNFLG9CQUFvQjtxS0FLckIsUUFBUTtzQkFBaEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ2JNb2RhbCB9IGZyb20gJ0BuZy1ib290c3RyYXAvbmctYm9vdHN0cmFwJztcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLXNoYXJlZCc7XG5pbXBvcnQgeyBCaWxsaW5nU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2JpbGxpbmcuc2VydmljZSc7XG5pbXBvcnQgeyBQdXJjaGFzZU9yZGVyRm9ybUNvbXBvbmVudCB9IGZyb20gJy4vcHVyY2hhc2Utb3JkZXItZm9ybS9wdXJjaGFzZS1vcmRlci1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBQdXJjaGFzZU9yZGVyRGV0YWlsc0NvbXBvbmVudCB9IGZyb20gJy4vcHVyY2hhc2Utb3JkZXItZGV0YWlscy9wdXJjaGFzZS1vcmRlci1kZXRhaWxzLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1wdXJjaGFzZS1vcmRlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9wdXJjaGFzZS1vcmRlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9wdXJjaGFzZS1vcmRlci5jb21wb25lbnQuc2Nzcydcbn0pXG5leHBvcnQgY2xhc3MgUHVyY2hhc2VPcmRlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSBjbGllbnRJZDogc3RyaW5nID0gJyc7XG5cbiAgb3JkZXJzOiBhbnlbXSA9IFtdO1xuICBsb2FkaW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgbm9EYXRhOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBiaWxsaW5nU2VydmljZTogQmlsbGluZ1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBtb2RhbFNlcnZpY2U6IE5nYk1vZGFsLFxuICAgIHByaXZhdGUgdG9hc3Q6IFRvYXN0U2VydmljZSxcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNsaWVudElkKSB7XG4gICAgICB0aGlzLmxvYWRPcmRlcnMoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2NsaWVudElkJ10gJiYgIWNoYW5nZXNbJ2NsaWVudElkJ10uZmlyc3RDaGFuZ2UgJiYgdGhpcy5jbGllbnRJZCkge1xuICAgICAgdGhpcy5sb2FkT3JkZXJzKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIGxvYWRPcmRlcnMoKSB7XG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcbiAgICB0aGlzLm5vRGF0YSA9IGZhbHNlO1xuICAgIHRoaXMuYmlsbGluZ1NlcnZpY2UuZ2V0UHVyY2hhc2VPcmRlcnModGhpcy5jbGllbnRJZCkucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5vcmRlcnMgPSByZXM/LmRhdGE/LnB1cmNoYXNlT3JkZXJzIHx8IFtdO1xuICAgICAgICB0aGlzLm5vRGF0YSA9IHRoaXMub3JkZXJzLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgIHRoaXMub3JkZXJzID0gW107XG4gICAgICAgIHRoaXMubm9EYXRhID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGFkZFB1cmNoYXNlT3JkZXIoKSB7XG4gICAgY29uc3QgbW9kYWxSZWYgPSB0aGlzLm1vZGFsU2VydmljZS5vcGVuKFB1cmNoYXNlT3JkZXJGb3JtQ29tcG9uZW50LCB7XG4gICAgICBjZW50ZXJlZDogdHJ1ZSwgc2Nyb2xsYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBtb2RhbFJlZi5jb21wb25lbnRJbnN0YW5jZS5jbGllbnRJZCA9IHRoaXMuY2xpZW50SWQ7XG4gICAgbW9kYWxSZWYucmVzdWx0LnRoZW4oKHJlc3VsdDogYW55KSA9PiB7XG4gICAgICBpZiAocmVzdWx0ID09PSAnc3VjY2VzcycpIHtcbiAgICAgICAgdGhpcy5sb2FkT3JkZXJzKCk7XG4gICAgICB9XG4gICAgfSwgKCkgPT4ge30pO1xuICB9XG5cbiAgLy8gSHVtYW4tcmVhZGFibGUgc3RhdHVzIGxhYmVsLlxuICBzdGF0dXNMYWJlbChzdGF0dXM6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKHN0YXR1cyA9PT0gJ2Z1bGx5VXNlZCcpIHJldHVybiAnRnVsbHkgVXNlZCc7XG4gICAgaWYgKHN0YXR1cyA9PT0gJ3BhcnRpYWxseVVzZWQnKSByZXR1cm4gJ1BhcnRpYWxseSBVc2VkJztcbiAgICByZXR1cm4gJ09wZW4nO1xuICB9XG5cbiAgc3RhdHVzQ2xhc3Moc3RhdHVzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChzdGF0dXMgPT09ICdmdWxseVVzZWQnKSByZXR1cm4gJ2JhZGdlIGJhZGdlLWxpZ2h0LWRhbmdlcic7XG4gICAgaWYgKHN0YXR1cyA9PT0gJ3BhcnRpYWxseVVzZWQnKSByZXR1cm4gJ2JhZGdlIGJhZGdlLWxpZ2h0LXdhcm5pbmcnO1xuICAgIHJldHVybiAnYmFkZ2UgYmFkZ2UtbGlnaHQtc3VjY2Vzcyc7XG4gIH1cblxuICAvLyBJbnZvaWNlIG51bWJlcnMgdGhhdCBjb25zdW1lZCB0aGlzIFBPIChmb3IgdGhlIFwiaW52b2ljZXMgdXNlZFwiIGNvbHVtbikuXG4gIHVzZWRJbnZvaWNlcyhvcmRlcjogYW55KTogc3RyaW5nIHtcbiAgICByZXR1cm4gKG9yZGVyPy51c2FnZSB8fCBbXSkubWFwKCh1OiBhbnkpID0+IHUuaW52b2ljZSkuZmlsdGVyKEJvb2xlYW4pLmpvaW4oJywgJyk7XG4gIH1cblxuICAvLyBPcGVuIHRoZSB1c2FnZS1kZXRhaWxzIHBvcHVwICh1c2FnZSByb3dzICsgY2xpY2thYmxlIGludm9pY2UgcHJldmlld3MpLlxuICB2aWV3RGV0YWlscyhvcmRlcjogYW55KSB7XG4gICAgY29uc3QgbW9kYWxSZWYgPSB0aGlzLm1vZGFsU2VydmljZS5vcGVuKFB1cmNoYXNlT3JkZXJEZXRhaWxzQ29tcG9uZW50LCB7XG4gICAgICBjZW50ZXJlZDogdHJ1ZSwgc2l6ZTogJ2xnJywgc2Nyb2xsYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBtb2RhbFJlZi5jb21wb25lbnRJbnN0YW5jZS5vcmRlciA9IG9yZGVyO1xuICB9XG59IiwiPGRpdiBjbGFzcz1cImludm9pY2VzLXNlY3Rpb25cIj5cbiAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlciBtYi0zXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJpbGxpbmdoZWFkZXJcIj5QdXJjaGFzZSBPcmRlcnM8L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJnLWxpZ2h0IHRleHQtZGFyayBtcy0xXCI+e3sgb3JkZXJzLmxlbmd0aCB9fSB0b3RhbDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJhZGRQdXJjaGFzZU9yZGVyKClcIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSB0ZXh0LW5vd3JhcFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtcy0xXCI+QWRkIFB1cmNoYXNlIE9yZGVyPC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nSWY9XCJsb2FkaW5nXCIgY2xhc3M9XCJ0ZXh0LW11dGVkIHB5LTRcIj5Mb2FkaW5n4oCmPC9kaXY+XG5cbiAgICA8ZGl2ICpuZ0lmPVwiIWxvYWRpbmdcIiBjbGFzcz1cInRhYmxlLXJlc3BvbnNpdmVcIj5cbiAgICAgICAgPHRhYmxlIGNsYXNzPVwidGFibGUgYWNjb3JkaW9uIHRhYmxlIGJvdHRvbS1ib3JkZXIgdGV4dC1ub3dyYXBcIj5cbiAgICAgICAgICAgIDx0aGVhZD5cbiAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgIDx0aD5Db21wYW55IE5hbWU8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGg+UE8gTnVtYmVyPC90aD5cbiAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwidGV4dC1lbmRcIj5Ub3RhbCBBbW91bnQ8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJ0ZXh0LWVuZFwiPlJlbWFpbmluZzwvdGg+XG4gICAgICAgICAgICAgICAgICAgIDx0aD5EYXRlPC90aD5cbiAgICAgICAgICAgICAgICAgICAgPHRoPlN0YXR1czwvdGg+XG4gICAgICAgICAgICAgICAgICAgIDx0aD5JbnZvaWNlcyBVc2VkPC90aD5cbiAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwidGV4dC1jZW50ZXJcIj5BY3Rpb248L3RoPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgbyBvZiBvcmRlcnNcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkPnt7IG8uY29tcGFueU5hbWUgfHwgJ+KAlCcgfX08L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQ+PHN0cm9uZz57eyBvLnB1cmNoYXNlT3JkZXJOdW1iZXIgfX08L3N0cm9uZz48L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJ0ZXh0LWVuZFwiPuKCuXt7IG8udG90YWxBbW91bnQgfCBudW1iZXI6JzEuMi0yJzonZW4tSU4nIH19PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwidGV4dC1lbmRcIj7igrl7eyBvLnJlbWFpbmluZ0Ftb3VudCB8IG51bWJlcjonMS4yLTInOidlbi1JTicgfX08L3RkPlxuICAgICAgICAgICAgICAgICAgICA8dGQ+e3sgby5kYXRlIHwgZGF0ZTogJ2RkIE1NTSB5eXl5JyB9fTwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDx0ZD48c3BhbiBbbmdDbGFzc109XCJzdGF0dXNDbGFzcyhvLnN0YXR1cylcIj57eyBzdGF0dXNMYWJlbChvLnN0YXR1cykgfX08L3NwYW4+PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJ1c2VkSW52b2ljZXMobylcIj57eyB1c2VkSW52b2ljZXMobykgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiF1c2VkSW52b2ljZXMobylcIiBjbGFzcz1cInRleHQtbXV0ZWRcIj7igJQ8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInRleHQtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImN1cnNvci1wb2ludGVyXCIgKGNsaWNrKT1cInZpZXdEZXRhaWxzKG8pXCIgdGl0bGU9XCJWaWV3IGRldGFpbHNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjE4XCIgaGVpZ2h0PVwiMThcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0yIDEyczMuNS03IDEwLTcgMTAgNyAxMCA3LTMuNSA3LTEwIDctMTAtNy0xMC03WlwiIHN0cm9rZT1cIiM2NjcwODVcIiBzdHJva2Utd2lkdGg9XCIxLjZcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCIxMlwiIGN5PVwiMTJcIiByPVwiM1wiIHN0cm9rZT1cIiM2NjcwODVcIiBzdHJva2Utd2lkdGg9XCIxLjZcIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICA8dHIgKm5nSWY9XCJub0RhdGFcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49XCI4XCIgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIHB5LTVcIj5ObyBwdXJjaGFzZSBvcmRlcnMgeWV0LjwvdGQ+XG4gICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgIDwvdGFibGU+XG4gICAgPC9kaXY+XG48L2Rpdj4iXX0=