@mj-biz-apps/orders-ng 5.2.0 → 5.2.1
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/dist/lib/custom/Product/widgets/product-accounting-widget.component.js +9 -3
- package/dist/lib/custom/Product/widgets/product-accounting-widget.component.js.map +1 -1
- package/dist/lib/custom/Product/widgets/product-gl-links.component.d.ts +460 -0
- package/dist/lib/custom/Product/widgets/product-gl-links.component.d.ts.map +1 -0
- package/dist/lib/custom/Product/widgets/product-gl-links.component.js +1229 -0
- package/dist/lib/custom/Product/widgets/product-gl-links.component.js.map +1 -0
- package/dist/lib/custom/custom-forms.module.d.ts +18 -17
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +5 -0
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
import * as i1 from "@memberjunction/ng-base-forms";
|
|
4
|
+
import * as i2 from "./product-gl-links.component.js";
|
|
4
5
|
/**
|
|
5
6
|
* Droppable Product Tax, Charges & Accounting GL Widget.
|
|
6
7
|
*/
|
|
@@ -10,7 +11,7 @@ export class BizAppsProductAccountingWidgetComponent {
|
|
|
10
11
|
FormContext;
|
|
11
12
|
Navigate = new EventEmitter();
|
|
12
13
|
static ɵfac = function BizAppsProductAccountingWidgetComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BizAppsProductAccountingWidgetComponent)(); };
|
|
13
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: BizAppsProductAccountingWidgetComponent, selectors: [["bizapps-product-accounting-widget"]], inputs: { Product: "Product", EditMode: "EditMode", FormContext: "FormContext" }, outputs: { Navigate: "Navigate" }, standalone: false, decls:
|
|
14
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: BizAppsProductAccountingWidgetComponent, selectors: [["bizapps-product-accounting-widget"]], inputs: { Product: "Product", EditMode: "EditMode", FormContext: "FormContext" }, outputs: { Navigate: "Navigate" }, standalone: false, decls: 14, vars: 19, consts: [[1, "mjo-acct-widget-wrap"], [1, "mjo-acct-card"], [1, "mjo-card-head"], [1, "fa-solid", "fa-scale-balanced"], [1, "mjo-card-body"], ["FieldName", "RevenueRecognitionTypeID", "Type", "textbox", "LinkType", "Record", 3, "Navigate", "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "IsTaxable", "Type", "checkbox", 3, "Navigate", "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "TaxCategory", "Type", "textbox", 3, "Navigate", "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "StandaloneSellingPrice", "Type", "number", 3, "Navigate", "Record", "ShowLabel", "EditMode", "FormContext"], [3, "Navigate", "Product", "EditMode", "FormContext"]], template: function BizAppsProductAccountingWidgetComponent_Template(rf, ctx) { if (rf & 1) {
|
|
14
15
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
|
|
15
16
|
i0.ɵɵelement(3, "i", 3);
|
|
16
17
|
i0.ɵɵelementStart(4, "span");
|
|
@@ -27,6 +28,9 @@ export class BizAppsProductAccountingWidgetComponent {
|
|
|
27
28
|
i0.ɵɵelementEnd();
|
|
28
29
|
i0.ɵɵelementStart(10, "mj-form-field", 8);
|
|
29
30
|
i0.ɵɵlistener("Navigate", function BizAppsProductAccountingWidgetComponent_Template_mj_form_field_Navigate_10_listener($event) { return ctx.Navigate.emit($event); });
|
|
31
|
+
i0.ɵɵelementEnd()()();
|
|
32
|
+
i0.ɵɵelementStart(11, "div", 1)(12, "div", 4)(13, "bizapps-product-gl-links", 9);
|
|
33
|
+
i0.ɵɵlistener("Navigate", function BizAppsProductAccountingWidgetComponent_Template_bizapps_product_gl_links_Navigate_13_listener($event) { return ctx.Navigate.emit($event); });
|
|
30
34
|
i0.ɵɵelementEnd()()()();
|
|
31
35
|
} if (rf & 2) {
|
|
32
36
|
i0.ɵɵadvance(7);
|
|
@@ -37,11 +41,13 @@ export class BizAppsProductAccountingWidgetComponent {
|
|
|
37
41
|
i0.ɵɵproperty("Record", ctx.Product)("ShowLabel", true)("EditMode", ctx.EditMode)("FormContext", ctx.FormContext);
|
|
38
42
|
i0.ɵɵadvance();
|
|
39
43
|
i0.ɵɵproperty("Record", ctx.Product)("ShowLabel", true)("EditMode", ctx.EditMode)("FormContext", ctx.FormContext);
|
|
40
|
-
|
|
44
|
+
i0.ɵɵadvance(3);
|
|
45
|
+
i0.ɵɵproperty("Product", ctx.Product)("EditMode", ctx.EditMode)("FormContext", ctx.FormContext);
|
|
46
|
+
} }, dependencies: [i1.MjFormFieldComponent, i2.BizAppsProductGLLinksComponent], styles: [".mjo-acct-widget-wrap[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4, 16px);\n width: 100%;\n}\n\n.mjo-acct-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card, rgba(255, 255, 255, 0.05));\n border: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.12));\n border-radius: var(--mj-radius-lg, 10px);\n overflow: hidden;\n}\n\n.mjo-card-head[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken, rgba(0, 0, 0, 0.1));\n border-bottom: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.1));\n font-size: 13.5px;\n font-weight: 700;\n color: var(--mj-text-primary, #0f172a);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mjo-card-head[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary, #0284c7);\n}\n\n.mjo-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n gap: 16px;\n}"] });
|
|
41
47
|
}
|
|
42
48
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BizAppsProductAccountingWidgetComponent, [{
|
|
43
49
|
type: Component,
|
|
44
|
-
args: [{ standalone: false, selector: 'bizapps-product-accounting-widget', template: "<div class=\"mjo-acct-widget-wrap\">\n <div class=\"mjo-acct-card\">\n <div class=\"mjo-card-head\">\n <i class=\"fa-solid fa-scale-balanced\"></i>\n <span>General Ledger & Revenue Recognition Classification</span>\n </div>\n <div class=\"mjo-card-body\">\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"RevenueRecognitionTypeID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n LinkType=\"Record\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"IsTaxable\"\n Type=\"checkbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"TaxCategory\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"StandaloneSellingPrice\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n </div>\n </div>\n</div>\n", styles: [".mjo-acct-widget-wrap {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4, 16px);\n width: 100%;\n}\n\n.mjo-acct-card {\n background: var(--mj-bg-surface-card, rgba(255, 255, 255, 0.05));\n border: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.12));\n border-radius: var(--mj-radius-lg, 10px);\n overflow: hidden;\n}\n\n.mjo-card-head {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken, rgba(0, 0, 0, 0.1));\n border-bottom: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.1));\n font-size: 13.5px;\n font-weight: 700;\n color: var(--mj-text-primary, #0f172a);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mjo-card-head i {\n color: var(--mj-brand-primary, #0284c7);\n}\n\n.mjo-card-body {\n padding: 16px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n gap: 16px;\n}\n"] }]
|
|
50
|
+
args: [{ standalone: false, selector: 'bizapps-product-accounting-widget', template: "<div class=\"mjo-acct-widget-wrap\">\n <div class=\"mjo-acct-card\">\n <div class=\"mjo-card-head\">\n <i class=\"fa-solid fa-scale-balanced\"></i>\n <span>General Ledger & Revenue Recognition Classification</span>\n </div>\n <div class=\"mjo-card-body\">\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"RevenueRecognitionTypeID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n LinkType=\"Record\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"IsTaxable\"\n Type=\"checkbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"TaxCategory\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"Product\"\n [ShowLabel]=\"true\"\n FieldName=\"StandaloneSellingPrice\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\"\n ></mj-form-field>\n </div>\n </div>\n\n <!--\n bizapps-orders#113 \u2014 the GL accounts this product books to.\n\n Andrew expected these HERE, under Accounting, and the section showed only the\n product's own columns. The links live in accounting, but they are polymorphic\n ((EntityID, RecordID)) and accounting must not depend on orders, so its own screen\n cannot even name a product. Rendering them from this side is what makes the pair\n something nobody has to type.\n -->\n <div class=\"mjo-acct-card\">\n <div class=\"mjo-card-body\">\n <bizapps-product-gl-links\n [Product]=\"Product\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"FormContext\"\n (Navigate)=\"Navigate.emit($event)\">\n </bizapps-product-gl-links>\n </div>\n </div>\n</div>\n", styles: [".mjo-acct-widget-wrap {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4, 16px);\n width: 100%;\n}\n\n.mjo-acct-card {\n background: var(--mj-bg-surface-card, rgba(255, 255, 255, 0.05));\n border: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.12));\n border-radius: var(--mj-radius-lg, 10px);\n overflow: hidden;\n}\n\n.mjo-card-head {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken, rgba(0, 0, 0, 0.1));\n border-bottom: 1px solid var(--mj-border-default, rgba(255, 255, 255, 0.1));\n font-size: 13.5px;\n font-weight: 700;\n color: var(--mj-text-primary, #0f172a);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mjo-card-head i {\n color: var(--mj-brand-primary, #0284c7);\n}\n\n.mjo-card-body {\n padding: 16px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n gap: 16px;\n}\n"] }]
|
|
45
51
|
}], null, { Product: [{
|
|
46
52
|
type: Input
|
|
47
53
|
}], EditMode: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-accounting-widget.component.js","sourceRoot":"","sources":["../../../../../src/lib/custom/Product/widgets/product-accounting-widget.component.ts","../../../../../src/lib/custom/Product/widgets/product-accounting-widget.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"product-accounting-widget.component.js","sourceRoot":"","sources":["../../../../../src/lib/custom/Product/widgets/product-accounting-widget.component.ts","../../../../../src/lib/custom/Product/widgets/product-accounting-widget.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;;;AAIvE;;GAEG;AAOH,MAAM,OAAO,uCAAuC;IAChC,OAAO,CAAgC;IACvC,QAAQ,GAAG,KAAK,CAAC;IACjB,WAAW,CAAe;IAEzB,QAAQ,GAAG,IAAI,YAAY,EAAuB,CAAC;iIAL3D,uCAAuC;6DAAvC,uCAAuC;YCX5C,AADJ,AADJ,8BAAkC,aACH,aACI;YACvB,uBAA0C;YAC1C,4BAAM;YAAA,mEAAuD;YACjE,AADiE,iBAAO,EAClE;YAEF,AADJ,8BAA2B,uBAUtB;YADG,uIAAY,yBAAqB,IAAC;YACrC,iBAAgB;YACjB,wCAQC;YADG,uIAAY,yBAAqB,IAAC;YACrC,iBAAgB;YACjB,wCAQC;YADG,uIAAY,yBAAqB,IAAC;YACrC,iBAAgB;YACjB,yCAQC;YADG,wIAAY,yBAAqB,IAAC;YAG9C,AADI,AADK,iBAAgB,EACf,EACJ;YAaE,AADJ,AADJ,+BAA2B,cACI,mCAKgB;YAAnC,mJAAY,yBAAqB,IAAC;YAIlD,AADI,AADI,AADI,iBAA2B,EACzB,EACJ,EACJ;;YA1DU,eAAkB;YAKlB,AADA,AAHA,AADA,oCAAkB,mBACA,0BAGG,gCACM;YAK3B,cAAkB;YAKlB,AADA,AAHA,AADA,oCAAkB,mBACA,0BAGG,gCACM;YAI3B,cAAkB;YAKlB,AADA,AAHA,AADA,oCAAkB,mBACA,0BAGG,gCACM;YAI3B,cAAkB;YAKlB,AADA,AAHA,AADA,oCAAkB,mBACA,0BAGG,gCACM;YAkB3B,eAAmB;YAEnB,AADA,AADA,qCAAmB,0BACE,gCACM;;;iFDhD9B,uCAAuC;cANnD,SAAS;6BACM,KAAK,YACP,mCAAmC;;kBAK5C,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAEL,MAAM;;kFALE,uCAAuC"}
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
import { ChangeDetectorRef, EventEmitter, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
+
import type { FormContext, FormNavigationEvent } from '@memberjunction/ng-base-forms';
|
|
3
|
+
import type { mjBizAppsOrdersProductEntity } from '@mj-biz-apps/orders-entities';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* The only fields the in-force resolver reads.
|
|
7
|
+
*
|
|
8
|
+
* Structural on purpose: the links arrive either as accounting's generated entity objects (from the
|
|
9
|
+
* engine cache) or as plain view rows (from the fallback read), and those are different types that
|
|
10
|
+
* happen to carry the same five fields. Naming the fields rather than either concrete type is what
|
|
11
|
+
* lets one resolver serve both without a cast at each call site.
|
|
12
|
+
*/
|
|
13
|
+
export interface GLLinkLike {
|
|
14
|
+
ID: unknown;
|
|
15
|
+
GLAccountID: unknown;
|
|
16
|
+
GLAccountRoleID: unknown;
|
|
17
|
+
Status: unknown;
|
|
18
|
+
StartedAt: unknown;
|
|
19
|
+
EndedAt: unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* May this GL account be offered for a product owned by `productCompanyID`?
|
|
23
|
+
*
|
|
24
|
+
* A named rule rather than an inline filter, because it decides whether a link the user creates will
|
|
25
|
+
* ever be reachable, and that deserves to be pinned by a test rather than reviewed by eye.
|
|
26
|
+
*
|
|
27
|
+
* An account belonging to another company is not offerable: `GLAccountResolver.Resolve` passes the
|
|
28
|
+
* order line's company down as `expectedCompanyID` and `AccountingBridge` filters candidates by the
|
|
29
|
+
* ACCOUNT's company before the window rules run, so such a link is silently SKIPPED at booking time
|
|
30
|
+
* rather than used. Dead configuration looks exactly like working configuration, which is why the
|
|
31
|
+
* panel must not be able to create it.
|
|
32
|
+
*
|
|
33
|
+
* A blank `productCompanyID` offers everything. `Product.CompanyID` is NOT NULL so this should not
|
|
34
|
+
* happen, but this runs in a browser against whatever the form holds; an empty picker would read as
|
|
35
|
+
* "no accounts exist" and give the user nothing to act on, where the unfiltered list is at worst what
|
|
36
|
+
* shipped before.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* The comparable form of an id.
|
|
40
|
+
*
|
|
41
|
+
* Ids reach this component from two sources that disagree on case: the engine cache lowercases, while
|
|
42
|
+
* a direct view read returns SQL Server's uppercase `uniqueidentifier` rendering. Accounting's own
|
|
43
|
+
* engine routes every id comparison through the same normalisation for exactly this reason, and the
|
|
44
|
+
* audit caught the one comparison here that did not — it rendered both edit pickers blank and warned
|
|
45
|
+
* that a correctly-configured account was "not offered".
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* One entry in the GL-account picker.
|
|
49
|
+
*
|
|
50
|
+
* `Disabled` exists for exactly one case: a link that already points at an account this product's
|
|
51
|
+
* company cannot use. That option must be VISIBLE, so the select never renders blank on a link that
|
|
52
|
+
* has an account, and UNSELECTABLE, so the repair path cannot re-create the unreachable link.
|
|
53
|
+
*/
|
|
54
|
+
export interface AccountOption {
|
|
55
|
+
ID: string;
|
|
56
|
+
Label: string;
|
|
57
|
+
Disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare function idKey(id: unknown): string;
|
|
60
|
+
export declare function AccountIsOfferable(accountCompanyID: string | null | undefined, productCompanyID: string | null | undefined): boolean;
|
|
61
|
+
/** One link, flattened for display. Nothing here is computed — every field is read off the row. */
|
|
62
|
+
export interface ProductGLLinkRow {
|
|
63
|
+
ID: string;
|
|
64
|
+
/**
|
|
65
|
+
* The role and account IDS, carried rather than re-derived.
|
|
66
|
+
*
|
|
67
|
+
* These used to be looked up when the Edit form opened — the role by matching `RoleName`, the
|
|
68
|
+
* account by finding the first picker label starting with the row's code. Both are wrong for the
|
|
69
|
+
* same reason: neither name nor code is unique. GL account codes REPEAT ACROSS COMPANIES by
|
|
70
|
+
* design — "40000 Sales" exists in every one of them — so the code search returned whichever
|
|
71
|
+
* company sorted first, and saving a not-yet-applied link wrote that arbitrary account.
|
|
72
|
+
*
|
|
73
|
+
* The ids are right here when the row is built. Carrying them removes the search, and with it the
|
|
74
|
+
* class of bug.
|
|
75
|
+
*/
|
|
76
|
+
RoleID: string;
|
|
77
|
+
AccountID: string;
|
|
78
|
+
RoleName: string;
|
|
79
|
+
AccountCode: string;
|
|
80
|
+
AccountName: string;
|
|
81
|
+
Status: string;
|
|
82
|
+
StartedAt: string | null;
|
|
83
|
+
EndedAt: string | null;
|
|
84
|
+
/** True when this is the link that would actually be used today for its role. */
|
|
85
|
+
Active: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The GL accounts a product books to — read from the product's own form (bizapps-orders#113).
|
|
89
|
+
*
|
|
90
|
+
* ── WHY THIS LIVES IN ORDERS AND NOT IN ACCOUNTING ──
|
|
91
|
+
*
|
|
92
|
+
* `GLAccountLink` is accounting's entity, so the instinct is to put its UI there. Accounting's own
|
|
93
|
+
* links screen explains why that cannot work for products, in its `LinkRow` comment:
|
|
94
|
+
*
|
|
95
|
+
* > These links are POLYMORPHIC — `(EntityID, RecordID)` can point at anything, including orders'
|
|
96
|
+
* > Products and Product Categories. Accounting must not depend on orders, so those stay unnamed
|
|
97
|
+
* > here BY DESIGN.
|
|
98
|
+
*
|
|
99
|
+
* So on accounting's screen a product-linked row shows a bare UUID and says so honestly. Andrew's
|
|
100
|
+
* report (#113) is that same boundary seen from the other side: he could not find a product's accounts,
|
|
101
|
+
* and creating a link by hand meant copying the Product's ID into a text box.
|
|
102
|
+
*
|
|
103
|
+
* Rendering it HERE inverts the dependency the right way round. Orders already depends on accounting
|
|
104
|
+
* — `AccountingBridge` calls the engine on both booking paths — and orders is the app that knows what
|
|
105
|
+
* a Product is. The polymorphic pair stops being something a human types: `EntityID` is this app's
|
|
106
|
+
* Products entity and `RecordID` is the record already on screen.
|
|
107
|
+
*
|
|
108
|
+
* ── WHY THE ENGINE AND NOT A QUERY ──
|
|
109
|
+
*
|
|
110
|
+
* `AccountingEngineBase` caches roles, accounts and links client-side and is the same primitive the
|
|
111
|
+
* booking pipeline resolves through (`ResolveLinkedAccount`). Reading from it means this panel cannot
|
|
112
|
+
* disagree with what an order will actually book — a re-implemented query could, and the first time it
|
|
113
|
+
* did, the screen would be lying about money.
|
|
114
|
+
*
|
|
115
|
+
* ── WHAT IS DELIBERATELY NOT HERE ──
|
|
116
|
+
*
|
|
117
|
+
* No fallback chain. A product with no direct link still books, through category and company defaults,
|
|
118
|
+
* and `GlResolutionPreviewComponent` in accounting-ng already renders that chain. Showing a resolved
|
|
119
|
+
* account here without saying it came from a category would read as "this product is linked" when it is
|
|
120
|
+
* not, which is the same confusion #112 caused one screen over.
|
|
121
|
+
*/
|
|
122
|
+
export declare class BizAppsProductGLLinksComponent implements OnInit, OnDestroy {
|
|
123
|
+
private readonly cdr;
|
|
124
|
+
Product: mjBizAppsOrdersProductEntity;
|
|
125
|
+
EditMode: boolean;
|
|
126
|
+
FormContext?: FormContext;
|
|
127
|
+
Navigate: EventEmitter<FormNavigationEvent>;
|
|
128
|
+
Rows: ProductGLLinkRow[];
|
|
129
|
+
Loading: boolean;
|
|
130
|
+
/** Set when the links cannot be read at all. Shown instead of an empty list, which would lie. */
|
|
131
|
+
LoadError: string | null;
|
|
132
|
+
constructor(cdr: ChangeDetectorRef);
|
|
133
|
+
ngOnInit(): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Re-reads the links.
|
|
136
|
+
*
|
|
137
|
+
* ── WHY A WRITE MUST PASS `true` ──
|
|
138
|
+
*
|
|
139
|
+
* `load()` prefers the engine's cached links and only falls back to a view read when the cache
|
|
140
|
+
* holds none for this product. That is right for a plain refresh and WRONG straight after a write:
|
|
141
|
+
* the cache is a snapshot taken at `Config()` time, so a product that already had one link would
|
|
142
|
+
* keep showing exactly that one — the row just added, or the retirement just applied, would be
|
|
143
|
+
* invisible until something else reloaded the engine.
|
|
144
|
+
*
|
|
145
|
+
* It survived the first browser test only because that test started from a product with NO links,
|
|
146
|
+
* where the cache is empty and the fallback runs anyway. Adding a second link is the case that
|
|
147
|
+
* would have shown nothing.
|
|
148
|
+
*
|
|
149
|
+
* @param reloadEngine - force the accounting engine to re-read before rendering. Every write path
|
|
150
|
+
* defaults TRUE. `ngOnInit` passes false, because a first mount is the one
|
|
151
|
+
* place a cached answer is the right one; the refresh button and every write
|
|
152
|
+
* take the default, because both are asking the panel to go and look.
|
|
153
|
+
*/
|
|
154
|
+
/**
|
|
155
|
+
* Set in `ngOnDestroy`, checked before every `detectChanges`.
|
|
156
|
+
*
|
|
157
|
+
* Every write ends with `finally { Saving = false; cdr.detectChanges(); }` AFTER an awaited save
|
|
158
|
+
* and engine reload. Navigate away mid-save and those resolve against a torn-down view, so
|
|
159
|
+
* `detectChanges` throws `ViewDestroyedError` — and because it throws from `finally`, the
|
|
160
|
+
* preceding `catch` cannot absorb it and it escapes as an unhandled rejection. This file's own
|
|
161
|
+
* comment elsewhere notes that a console error is treated as a broken screen by the Playwright
|
|
162
|
+
* keystone, so it would fail a suite rather than merely litter the console.
|
|
163
|
+
*/
|
|
164
|
+
private destroyed;
|
|
165
|
+
ngOnDestroy(): void;
|
|
166
|
+
/** `detectChanges`, unless the view is gone. */
|
|
167
|
+
private tick;
|
|
168
|
+
/**
|
|
169
|
+
* `reloadEngine` DEFAULTS TRUE, and the default is the whole point.
|
|
170
|
+
*
|
|
171
|
+
* It used to default false, so the refresh icon re-ran `load()` against a cache nobody had
|
|
172
|
+
* invalidated — and `load()`'s own `Config(false, …)` is a no-op once the engine is loaded. A
|
|
173
|
+
* colleague retiring a link from accounting's own screen was therefore invisible here: the button
|
|
174
|
+
* rendered the identical stale row, still chipped "In force", for the rest of the session.
|
|
175
|
+
*
|
|
176
|
+
* A user who presses refresh is asking the panel to go and look. Writes already passed `true`
|
|
177
|
+
* explicitly; making that the default means the only path that can serve a cached answer is the
|
|
178
|
+
* initial load, which is the one place a cache is what you want.
|
|
179
|
+
*/
|
|
180
|
+
Refresh(reloadEngine?: boolean): Promise<void>;
|
|
181
|
+
/**
|
|
182
|
+
* What the status chip says.
|
|
183
|
+
*
|
|
184
|
+
* The three states are NOT the two the `Status` column has. A link can be stored `Active` and still
|
|
185
|
+
* not be the one that books — superseded by a later link on the same role — and rendering the raw
|
|
186
|
+
* column would put the word "Active" on both rows. Saying SUPERSEDED is the whole reason this panel
|
|
187
|
+
* resolves through accounting's picker rather than reading a flag.
|
|
188
|
+
*/
|
|
189
|
+
/**
|
|
190
|
+
* Why a row is not the one in force.
|
|
191
|
+
*
|
|
192
|
+
* `Active === false` has three causes and this used to print "Superseded" for all of them. A link
|
|
193
|
+
* added to take over next quarter therefore rendered as "Superseded" — it supersedes something, it
|
|
194
|
+
* is not superseded — beside a Remove button saying it had not started. Two controls in one row
|
|
195
|
+
* telling opposite stories is how a user concludes the save was rejected and adds another link.
|
|
196
|
+
*/
|
|
197
|
+
StatusLabel(row: ProductGLLinkRow): string;
|
|
198
|
+
/**
|
|
199
|
+
* What Remove actually does to THIS row, said accurately.
|
|
200
|
+
*
|
|
201
|
+
* ── THE CONTROL USED TO ASSERT SOMETHING FALSE ────────────────────────────────────────────────
|
|
202
|
+
*
|
|
203
|
+
* Its title read "It has not started yet, so nothing has booked through it." That is true of a link
|
|
204
|
+
* dated in the future and FALSE of a link dated today, because `pickActiveLinkIndex` skips only
|
|
205
|
+
* when `t < started` — a link starting at today's UTC midnight is already the one resolution
|
|
206
|
+
* picks. `OpenDraft` defaults the start to today, so every link this panel creates spends its
|
|
207
|
+
* first UTC day in exactly that state: chip reading "In force", button promising nothing had
|
|
208
|
+
* booked, and `Delete()` behind it.
|
|
209
|
+
*
|
|
210
|
+
* The button stays, because it has to. `CK_GLAccountLink_Window` enforces `EndedAt > StartedAt`,
|
|
211
|
+
* so a link created today CANNOT be retired — Remove is the only way to undo a mistake made today.
|
|
212
|
+
* What was wrong was the sentence, not the affordance.
|
|
213
|
+
*/
|
|
214
|
+
RemoveWarning(row: ProductGLLinkRow): string;
|
|
215
|
+
/** Opens accounting's Account Links screen, which is where a link is created or retired. */
|
|
216
|
+
OpenLink(row: ProductGLLinkRow): void;
|
|
217
|
+
/** Roles and accounts to choose from, filled by {@link Refresh} off the same engine the reader uses. */
|
|
218
|
+
Roles: Array<{
|
|
219
|
+
ID: string;
|
|
220
|
+
Name: string;
|
|
221
|
+
}>;
|
|
222
|
+
Accounts: AccountOption[];
|
|
223
|
+
/** The add form. Null when closed — opening it is a deliberate act, not the default state. */
|
|
224
|
+
Draft: {
|
|
225
|
+
RoleID: string;
|
|
226
|
+
AccountID: string;
|
|
227
|
+
StartedAt: string;
|
|
228
|
+
} | null;
|
|
229
|
+
/** Set when a write is refused. The SERVER's message, verbatim — see {@link AddLink}. */
|
|
230
|
+
WriteError: string | null;
|
|
231
|
+
Saving: boolean;
|
|
232
|
+
/** A product must exist before anything can point at it: `RecordID` is its primary key. */
|
|
233
|
+
get CanWrite(): boolean;
|
|
234
|
+
OpenDraft(): void;
|
|
235
|
+
CancelDraft(): void;
|
|
236
|
+
/**
|
|
237
|
+
* The link being edited, or null. `Applied` decides how much of it may change — see {@link OpenEdit}.
|
|
238
|
+
*/
|
|
239
|
+
Editing: {
|
|
240
|
+
ID: string;
|
|
241
|
+
RoleID: string;
|
|
242
|
+
AccountID: string;
|
|
243
|
+
StartedAt: string;
|
|
244
|
+
EndedAt: string;
|
|
245
|
+
Applied: boolean;
|
|
246
|
+
} | null;
|
|
247
|
+
/**
|
|
248
|
+
* The options the EDIT picker shows: the company-scoped list, plus this link's CURRENT account when
|
|
249
|
+
* that account is not in it.
|
|
250
|
+
*
|
|
251
|
+
* ── WHY THE SCOPED LIST IS NOT ENOUGH ON ITS OWN ──────────────────────────────────────────────
|
|
252
|
+
*
|
|
253
|
+
* Scoping accounts to the product's company (PR #125 review) is right for CHOOSING, but a link that
|
|
254
|
+
* already points somewhere else still has to render. Such links exist: nothing stopped the panel
|
|
255
|
+
* creating them before this change, and nothing stops another tool creating one now. Showing only
|
|
256
|
+
* the scoped list would leave the select with no matching option — blank — on a link that plainly
|
|
257
|
+
* has an account.
|
|
258
|
+
*
|
|
259
|
+
* The template a few lines above already states the rule this would break: hiding a value "would
|
|
260
|
+
* read as 'this link has no account', which is the confusion #112 was". A filtered picker on an
|
|
261
|
+
* existing record must never hide that record's current value.
|
|
262
|
+
*
|
|
263
|
+
* The current account is labelled so the reader can tell it apart from the offerable ones, and the
|
|
264
|
+
* ordinary edit rules still apply — an applied link cannot change its account at all, and a
|
|
265
|
+
* not-yet-applied one can be moved onto a valid account, which is the repair path.
|
|
266
|
+
*/
|
|
267
|
+
get EditAccounts(): ReadonlyArray<AccountOption>;
|
|
268
|
+
/**
|
|
269
|
+
* Frozen when the edit opens, NOT derived from the live `ngModel` value.
|
|
270
|
+
*
|
|
271
|
+
* Deriving it was wrong twice. It allocated a fresh array and object on every change-detection
|
|
272
|
+
* pass — the hazard this codebase already documents with its frozen-empty constant elsewhere — and,
|
|
273
|
+
* worse, the option deleted itself: the moment a user picked a valid account to repair a
|
|
274
|
+
* cross-company link, `current` matched the scoped list and the original option vanished, so they
|
|
275
|
+
* could neither compare the two nor change their mind without cancelling the whole edit.
|
|
276
|
+
*/
|
|
277
|
+
private EditAccountOptions;
|
|
278
|
+
/**
|
|
279
|
+
* The role options for one edit, with the link's current role re-admitted when the engine has no
|
|
280
|
+
* such role.
|
|
281
|
+
*
|
|
282
|
+
* Accounts got this treatment and roles did not, which left the identical hole one field over. A
|
|
283
|
+
* link whose role is missing from the engine cache — deleted, or filtered out by row-level
|
|
284
|
+
* permissions — renders `(unknown role)` in the table, and the select then matched no option and
|
|
285
|
+
* rendered BLANK. Carrying `RoleID` on the row fixed the duplicate-name case only; it cannot put a
|
|
286
|
+
* matching `<option>` in a list that does not contain one.
|
|
287
|
+
*
|
|
288
|
+
* Disabled for the same reason as the account equivalent: visible so the picker never reads as
|
|
289
|
+
* "this link has no role", unselectable so a save cannot write an orphan id back.
|
|
290
|
+
*/
|
|
291
|
+
get EditRoles(): ReadonlyArray<AccountOption>;
|
|
292
|
+
private EditRoleOptions;
|
|
293
|
+
private roleOptionsForEditing;
|
|
294
|
+
/** The options for one edit, with the link's current account re-admitted when it is not offerable. */
|
|
295
|
+
private optionsForEditing;
|
|
296
|
+
/**
|
|
297
|
+
* Opens an edit for one link.
|
|
298
|
+
*
|
|
299
|
+
* ── WHAT MAY CHANGE DEPENDS ON WHETHER IT HAS BOOKED ──
|
|
300
|
+
*
|
|
301
|
+
* #113 asks for "adding/editing/deleting" and editing has to exist. But a link is not an ordinary
|
|
302
|
+
* record: while it is in force it is the reason journal entries name the account they name. Letting
|
|
303
|
+
* someone re-point the account or move the start date on such a link would silently rewrite the
|
|
304
|
+
* explanation for money that has already moved, and nothing else records what the mapping used to
|
|
305
|
+
* be.
|
|
306
|
+
*
|
|
307
|
+
* So the split follows {@link HasApplied}, the same boundary Remove uses:
|
|
308
|
+
*
|
|
309
|
+
* · NOT applied yet — nothing has booked through it, so role, account and start date are all
|
|
310
|
+
* editable. This is the "I picked the wrong account a minute ago" case.
|
|
311
|
+
* · ALREADY applied — only the END date may change. That is a correction to when the mapping
|
|
312
|
+
* stopped, which is a statement about the future of a window rather than a rewrite of its past.
|
|
313
|
+
* To change where an applied product books, add a link with a later start; superseding is the
|
|
314
|
+
* accounting-correct edit and `pickActiveLinkIndex` already understands it.
|
|
315
|
+
*/
|
|
316
|
+
OpenEdit(row: ProductGLLinkRow): void;
|
|
317
|
+
CancelEdit(): void;
|
|
318
|
+
/**
|
|
319
|
+
* Writes the edit.
|
|
320
|
+
*
|
|
321
|
+
* Only the fields the tier allows are assigned — the guard is here as well as in the template, so a
|
|
322
|
+
* stale render cannot rewrite an applied link's account by being clicked after the boundary moved.
|
|
323
|
+
* An empty end date clears it, which is how a retire applied by mistake is undone.
|
|
324
|
+
*/
|
|
325
|
+
/**
|
|
326
|
+
* Has this link applied AS OF NOW — read from the LIVE row, never from the edit snapshot.
|
|
327
|
+
*
|
|
328
|
+
* `Editing.Applied` is captured when the form opens and the template reads the same captured
|
|
329
|
+
* value. That is fine for deciding what to RENDER, and wrong for deciding what to WRITE: a form
|
|
330
|
+
* opened at 23:59 on a link starting tomorrow is still open at 00:01, when the link has come into
|
|
331
|
+
* force. Trusting the snapshot there let a save rewrite the role, account and start date of a link
|
|
332
|
+
* that was by then explaining journal entries.
|
|
333
|
+
*
|
|
334
|
+
* A row that has vanished counts as APPLIED. The safe direction is refusing an edit that might
|
|
335
|
+
* have been allowed, not permitting one that rewrites history because the row could not be found.
|
|
336
|
+
*/
|
|
337
|
+
private appliedNowFor;
|
|
338
|
+
SaveEdit(): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* `yyyy-MM-dd` for a date input, in UTC.
|
|
341
|
+
*
|
|
342
|
+
* The same conversion the sales workspace isolates in `deal-workspace.dates.ts`: an
|
|
343
|
+
* `<input type="date">` reads and writes strings while the field holds a Date, and handing an input
|
|
344
|
+
* a Date renders it BLANK with no error. UTC because the window is stored and displayed in UTC.
|
|
345
|
+
*/
|
|
346
|
+
private asDateInput;
|
|
347
|
+
/**
|
|
348
|
+
* Creates the link.
|
|
349
|
+
*
|
|
350
|
+
* The polymorphic pair is NOT typed by a human, and that is the entire point of doing this here:
|
|
351
|
+
* `EntityID` is orders' Products entity and `RecordID` is the record already on screen. On
|
|
352
|
+
* accounting's own screen a person would have to paste the product's UUID into a text box, which is
|
|
353
|
+
* what #113 is reporting.
|
|
354
|
+
*
|
|
355
|
+
* ── THE REFUSAL IS SURFACED, NOT RE-IMPLEMENTED ──
|
|
356
|
+
*
|
|
357
|
+
* `GLAccountLinkEntityServer` refuses two ACTIVE links for the same (record, role) whose accounts
|
|
358
|
+
* share a company AND share a `StartedAt`, because the tie-break is a strict `>` and resolution
|
|
359
|
+
* would otherwise pick arbitrarily between two accounts that both balance. This does not restate
|
|
360
|
+
* that rule client-side: a copy would drift from it, and the copy would be the one that silently
|
|
361
|
+
* disagreed. It saves, and shows the server's own message when the server says no — which is also
|
|
362
|
+
* how the human learns that superseding means a LATER start date rather than a duplicate.
|
|
363
|
+
*/
|
|
364
|
+
AddLink(): Promise<void>;
|
|
365
|
+
/**
|
|
366
|
+
* Whether a link can have explained any money yet.
|
|
367
|
+
*
|
|
368
|
+
* `pickActiveLinkIndex` treats a window as applying when `StartedAt <= now <= EndedAt`, so a link
|
|
369
|
+
* that starts TODAY OR LATER has not yet been the answer to any resolution. That is the boundary
|
|
370
|
+
* between the two destructive-looking actions below, and it is deliberately conservative: dated in
|
|
371
|
+
* the past means assume it booked something.
|
|
372
|
+
*/
|
|
373
|
+
HasApplied(row: ProductGLLinkRow): boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Ends a link's window, which is how accounting retires a mapping that has been in force.
|
|
376
|
+
*
|
|
377
|
+
* ── WHY THIS IS NOT A DELETE ──
|
|
378
|
+
*
|
|
379
|
+
* A GL link explains where money went. Deleting one that has already booked would remove the
|
|
380
|
+
* explanation for journal entries that still exist, and nothing else records which mapping was in
|
|
381
|
+
* force at the time. Ending the window keeps the history and stops the link applying.
|
|
382
|
+
*
|
|
383
|
+
* ── AND WHAT "TODAY" ACTUALLY MEANS HERE ──
|
|
384
|
+
*
|
|
385
|
+
* `EndedAt` is stored at MIDNIGHT UTC, and `pickActiveLinkIndex` excludes a link once `now > ended`.
|
|
386
|
+
* Midnight has already passed by the time anyone clicks, so retiring stops the link IMMEDIATELY
|
|
387
|
+
* rather than at the end of the day. Verified in the browser: a link dated 2020-01-01 retired on
|
|
388
|
+
* 2026-08-28 rendered as Superseded on the spot, not as still in force.
|
|
389
|
+
*
|
|
390
|
+
* This comment previously claimed the opposite — "applies for the whole of today and stops
|
|
391
|
+
* tomorrow" — and the button's tooltip said so too. The behaviour is the defensible one; the
|
|
392
|
+
* description was wrong, and it is the description that changed.
|
|
393
|
+
*/
|
|
394
|
+
/**
|
|
395
|
+
* Closes an edit form that is bound to `id`.
|
|
396
|
+
*
|
|
397
|
+
* Retire and Remove used to leave it open, and the template only hides a row's EDIT button while
|
|
398
|
+
* that row is being edited — Retire and Remove stayed live. So the two orderings both corrupted:
|
|
399
|
+
* Retire then Save wrote `EndedAt = null` from the stale form and silently UN-RETIRED the link;
|
|
400
|
+
* Remove then Save threw "could not be re-read" on a record that no longer existed, which reads as
|
|
401
|
+
* a broken screen rather than "that record is gone".
|
|
402
|
+
*/
|
|
403
|
+
private closeEditFor;
|
|
404
|
+
RetireLink(row: ProductGLLinkRow): Promise<void>;
|
|
405
|
+
/**
|
|
406
|
+
* Deletes a link that cannot have explained anything yet.
|
|
407
|
+
*
|
|
408
|
+
* ── WHY THIS EXISTS DESPITE THE ARGUMENT AGAINST DELETING ──
|
|
409
|
+
*
|
|
410
|
+
* Retiring is right for a mapping that has been in force. It is USELESS for one created by
|
|
411
|
+
* mistake a minute ago: the server refuses `EndedAt` on or before `StartedAt` ("The end date must
|
|
412
|
+
* be after the start date"), so a link mistyped today could be neither retired nor removed. That
|
|
413
|
+
* was a real hole — found by clicking Retire on a link the same test had just created.
|
|
414
|
+
*
|
|
415
|
+
* The boundary is {@link HasApplied}: a link starting today or later has never been the answer to
|
|
416
|
+
* a resolution, so deleting it destroys no explanation of anything. One that started earlier keeps
|
|
417
|
+
* the retire path and cannot be deleted from here at all.
|
|
418
|
+
*/
|
|
419
|
+
RemoveLink(row: ProductGLLinkRow): Promise<void>;
|
|
420
|
+
/**
|
|
421
|
+
* The sentence a human should read out of a refused save.
|
|
422
|
+
*
|
|
423
|
+
* `CompleteMessage` can be a JSON blob of validation results — the retire failure arrived as
|
|
424
|
+
* `{"Source":"EndedAt","Message":"The end date must be after the start date.",...}`, and showing
|
|
425
|
+
* that verbatim buries the one sentence that matters inside punctuation. This pulls the `Message`
|
|
426
|
+
* out when it is there and falls back to the raw text when it is not, so nothing is ever swallowed.
|
|
427
|
+
*/
|
|
428
|
+
private readableError;
|
|
429
|
+
/** Today in UTC as `yyyy-MM-dd` — the same zone the window is stored and rendered in. */
|
|
430
|
+
private today;
|
|
431
|
+
private load;
|
|
432
|
+
/** The view read, used only when the engine cache holds nothing for this product. */
|
|
433
|
+
private readDirect;
|
|
434
|
+
/**
|
|
435
|
+
* The ids of the links actually IN FORCE today — one per role at most, decided by accounting.
|
|
436
|
+
*
|
|
437
|
+
* ── WHY THIS IS NOT A WINDOW TEST ──
|
|
438
|
+
*
|
|
439
|
+
* The obvious implementation, and the one this replaced, asks of each link "is it Active and does
|
|
440
|
+
* today fall inside its window?" and marks every link that passes. That is wrong whenever a role
|
|
441
|
+
* has more than one qualifying link — a mapping being superseded while the old row is still open,
|
|
442
|
+
* which is exactly what an accountant does when they re-point a product mid-year. Both rows pass
|
|
443
|
+
* the window test, so the panel would show TWO active accounts for one role while an order books
|
|
444
|
+
* through exactly one of them. A screen that disagrees with the booking about where money lands is
|
|
445
|
+
* worse than no screen.
|
|
446
|
+
*
|
|
447
|
+
* `pickActiveLinkIndex` is accounting's own picker — the pure function behind
|
|
448
|
+
* `ResolveLinkedAccount`, exported by that package for precisely this kind of reuse. It applies the
|
|
449
|
+
* window AND the tie-break this panel has no business restating: latest `StartedAt` wins, and a
|
|
450
|
+
* null `StartedAt` loses to any dated one. Calling it means "active" here can only ever mean what
|
|
451
|
+
* the booking pipeline means.
|
|
452
|
+
*
|
|
453
|
+
* Grouped by ROLE because that is the unit the picker resolves: a product legitimately has a
|
|
454
|
+
* revenue link and a deferred-revenue link at once, and they do not compete.
|
|
455
|
+
*/
|
|
456
|
+
private inForceIDs;
|
|
457
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BizAppsProductGLLinksComponent, never>;
|
|
458
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BizAppsProductGLLinksComponent, "bizapps-product-gl-links", never, { "Product": { "alias": "Product"; "required": false; }; "EditMode": { "alias": "EditMode"; "required": false; }; "FormContext": { "alias": "FormContext"; "required": false; }; }, { "Navigate": "Navigate"; }, never, never, false, never>;
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=product-gl-links.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-gl-links.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/custom/Product/widgets/product-gl-links.component.ts"],"names":[],"mappings":"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"}
|