@voplus/morpho-csp 11.2.9 → 11.3.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/LegalContactSelect/index.d.ts +7 -0
- package/es/components/LegalContactSelect/index.js +127 -12
- package/es/components/LegalContactSelect/index.js.map +1 -1
- package/es/data/clda-form/conversion.d.ts +9 -6
- package/es/data/clda-form/conversion.js +11 -18
- package/es/data/clda-form/conversion.js.map +1 -1
- package/es/data/clda-form/identityAdapter.d.ts +60 -0
- package/es/data/clda-form/identityAdapter.js +196 -0
- package/es/data/clda-form/identityAdapter.js.map +1 -0
- package/es/data/clda-form/interfaces.d.ts +20 -1
- package/es/data/clda-form/saveFormDraft.d.ts +4 -0
- package/es/data/clda-form/saveFormDraft.js +21 -0
- package/es/data/clda-form/saveFormDraft.js.map +1 -0
- package/es/data/clda-form/types.d.ts +31 -2
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/IdentityShapeFields.d.ts +35 -0
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/IdentityShapeFields.js +53 -0
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/IdentityShapeFields.js.map +1 -0
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/index.js +41 -15
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/index.js.map +1 -1
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/state.d.ts +59 -1
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/state.js +244 -15
- package/es/modules/corporate/background-investigation/risk-profile/components/IdentityProperties/state.js.map +1 -1
- package/es/modules/corporate/company/components/CorporateOfficerSelect/index.d.ts +5 -0
- package/es/modules/corporate/company/components/CorporateOfficerSelect/index.js +13 -7
- package/es/modules/corporate/company/components/CorporateOfficerSelect/index.js.map +1 -1
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step3.d.ts +2 -2
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step3.js +20 -24
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step3.js.map +1 -1
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step4.d.ts +2 -2
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step4.js +38 -11
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/Step4.js.map +1 -1
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/index.d.ts +3 -3
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/index.js.map +1 -1
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/state.d.ts +25 -4
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/state.js +88 -5
- package/es/modules/corporate/company/identity/components/NewLegalContactDialog/state.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/DialogShell.d.ts +13 -0
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/DialogShell.js +20 -0
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/DialogShell.js.map +1 -0
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page1.js +28 -28
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page1.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page2.js +3 -4
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page2.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page3.js +16 -9
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page3.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page4.d.ts +2 -2
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page4.js +128 -61
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page4.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page5.d.ts +2 -2
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page5.js +119 -24
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/Page5.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/index.d.ts +0 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/index.js +16 -8
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/index.js.map +1 -1
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/state.d.ts +274 -23
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/state.js +560 -210
- package/es/modules/corporate/company/identity/components/SelectLegalContactDialog/state.js.map +1 -1
- package/es/modules/corporate/components/CorporateSelect/index.d.ts +12 -1
- package/es/modules/corporate/components/CorporateSelect/index.js +19 -5
- package/es/modules/corporate/components/CorporateSelect/index.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/AppointOfficer/index.d.ts +6 -1
- package/es/modules/corporate/legal-generation/components/AppointOfficer/index.js +3 -2
- package/es/modules/corporate/legal-generation/components/AppointOfficer/index.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/CorporateRepresentative/index.d.ts +6 -1
- package/es/modules/corporate/legal-generation/components/CorporateRepresentative/index.js +3 -2
- package/es/modules/corporate/legal-generation/components/CorporateRepresentative/index.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/IssueShares/Fields.js +3 -3
- package/es/modules/corporate/legal-generation/components/IssueShares/Fields.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/IssueShares/interface.d.ts +1 -1
- package/es/modules/corporate/legal-generation/components/PowerOfAttroney/Fields.d.ts +16 -1
- package/es/modules/corporate/legal-generation/components/PowerOfAttroney/Fields.js +27 -9
- package/es/modules/corporate/legal-generation/components/PowerOfAttroney/Fields.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/PowerOfAttroney/interface.d.ts +5 -2
- package/es/modules/corporate/legal-generation/components/ResignationLetter/Fields.js +1 -1
- package/es/modules/corporate/legal-generation/components/ResignationLetter/Fields.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/ShareTransfer/Fields.d.ts +13 -1
- package/es/modules/corporate/legal-generation/components/ShareTransfer/Fields.js +24 -6
- package/es/modules/corporate/legal-generation/components/ShareTransfer/Fields.js.map +1 -1
- package/es/modules/corporate/legal-generation/components/ShareTransfer/interface.d.ts +5 -2
- package/es/modules/corporate/legal-generation/components/SubmitButton/index.d.ts +11 -3
- package/es/modules/corporate/legal-generation/components/SubmitButton/index.js +9 -3
- package/es/modules/corporate/legal-generation/components/SubmitButton/index.js.map +1 -1
- package/es/modules/corporate/legal-generation/fields/AppointOfficerFields.d.ts +31 -2
- package/es/modules/corporate/legal-generation/fields/AppointOfficerFields.js +52 -37
- package/es/modules/corporate/legal-generation/fields/AppointOfficerFields.js.map +1 -1
- package/es/modules/corporate/legal-generation/fields/CorporateRepresentativeFields.d.ts +27 -2
- package/es/modules/corporate/legal-generation/fields/CorporateRepresentativeFields.js +78 -21
- package/es/modules/corporate/legal-generation/fields/CorporateRepresentativeFields.js.map +1 -1
- package/es/modules/corporate/legal-generation/fields/ParentCompanyDetailsFields.d.ts +17 -0
- package/es/modules/corporate/legal-generation/fields/ParentCompanyDetailsFields.js +36 -0
- package/es/modules/corporate/legal-generation/fields/ParentCompanyDetailsFields.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/renderCapturedIdentityColumn.d.ts +11 -0
- package/es/modules/corporate/legal-generation/fields/renderCapturedIdentityColumn.js +25 -0
- package/es/modules/corporate/legal-generation/fields/renderCapturedIdentityColumn.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/index.d.ts +7 -0
- package/es/modules/corporate/legal-generation/fields/state/index.js +5 -0
- package/es/modules/corporate/legal-generation/fields/state/index.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/types.d.ts +37 -0
- package/es/modules/corporate/legal-generation/fields/state/types.js +27 -0
- package/es/modules/corporate/legal-generation/fields/state/types.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/useCapturedIdentityField.d.ts +28 -0
- package/es/modules/corporate/legal-generation/fields/state/useCapturedIdentityField.js +45 -0
- package/es/modules/corporate/legal-generation/fields/state/useCapturedIdentityField.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/useIdentityShapeCapture.d.ts +31 -0
- package/es/modules/corporate/legal-generation/fields/state/useIdentityShapeCapture.js +47 -0
- package/es/modules/corporate/legal-generation/fields/state/useIdentityShapeCapture.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/useLegalGenerationIdentityCapture.d.ts +35 -0
- package/es/modules/corporate/legal-generation/fields/state/useLegalGenerationIdentityCapture.js +36 -0
- package/es/modules/corporate/legal-generation/fields/state/useLegalGenerationIdentityCapture.js.map +1 -0
- package/es/modules/corporate/legal-generation/fields/state/useOperateField.d.ts +15 -0
- package/es/modules/corporate/legal-generation/fields/state/useOperateField.js +27 -0
- package/es/modules/corporate/legal-generation/fields/state/useOperateField.js.map +1 -0
- package/es/modules/corporate/legal-generation/form/AppointOfficerForm.d.ts +18 -9
- package/es/modules/corporate/legal-generation/form/AppointOfficerForm.js +130 -28
- package/es/modules/corporate/legal-generation/form/AppointOfficerForm.js.map +1 -1
- package/es/modules/corporate/legal-generation/form/CorporateRepresentativeForm.d.ts +27 -17
- package/es/modules/corporate/legal-generation/form/CorporateRepresentativeForm.js +112 -24
- package/es/modules/corporate/legal-generation/form/CorporateRepresentativeForm.js.map +1 -1
- package/es/modules/corporate/legal-generation/form/legalGenerationSubmit.d.ts +637 -0
- package/es/modules/corporate/legal-generation/form/legalGenerationSubmit.js +840 -0
- package/es/modules/corporate/legal-generation/form/legalGenerationSubmit.js.map +1 -0
- package/es/modules/corporate/legal-generation/form/useLegalGenerationDocument.d.ts +23 -0
- package/es/modules/corporate/legal-generation/form/useLegalGenerationDocument.js +55 -0
- package/es/modules/corporate/legal-generation/form/useLegalGenerationDocument.js.map +1 -0
- package/es/modules/corporate/legal-generation/pages/CorporateLegalGeneration/index.js +38 -8
- package/es/modules/corporate/legal-generation/pages/CorporateLegalGeneration/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/CLDAContactList/index.js +50 -33
- package/es/modules/self-registration/clda-form/components/CLDAContactList/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/ContactFields/index.d.ts +5 -2
- package/es/modules/self-registration/clda-form/components/ContactFields/index.js +6 -3
- package/es/modules/self-registration/clda-form/components/ContactFields/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/DataProtectionOfficer/NewDPODialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/components/DataProtectionOfficer/NewDPODialog/index.js +7 -18
- package/es/modules/self-registration/clda-form/components/DataProtectionOfficer/NewDPODialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/NewDirectorDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/components/NewDirectorDialog/index.js +7 -18
- package/es/modules/self-registration/clda-form/components/NewDirectorDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/NewSecretaryDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/components/NewSecretaryDialog/index.js +7 -18
- package/es/modules/self-registration/clda-form/components/NewSecretaryDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/NewShareholderDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/components/NewShareholderDialog/index.js +7 -18
- package/es/modules/self-registration/clda-form/components/NewShareholderDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/components/useContactEditSession.d.ts +35 -0
- package/es/modules/self-registration/clda-form/components/useContactEditSession.js +51 -0
- package/es/modules/self-registration/clda-form/components/useContactEditSession.js.map +1 -0
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailItem/index.d.ts +2 -3
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailItem/index.js +60 -12
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailItem/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailList/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailList/index.js +3 -5
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/components/NewOfficerDetailList/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/index.js +7 -21
- package/es/modules/self-registration/clda-form/incorporation/appoint-representative/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/CompanyGeneralForm.js +6 -5
- package/es/modules/self-registration/clda-form/incorporation/company-general/CompanyGeneralForm.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddAllotmentDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddAllotmentDialog/index.js +23 -28
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddAllotmentDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddBankOpeningDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddBankOpeningDialog/index.js +11 -24
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddBankOpeningDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddDivideDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddDivideDialog/index.js +13 -8
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddDivideDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddOfficerDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddOfficerDialog/index.js +11 -24
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddOfficerDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRedonminationDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRedonminationDialog/index.js +18 -9
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRedonminationDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRemoveOfficerDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRemoveOfficerDialog/index.js +11 -24
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddRemoveOfficerDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddTransferDialog/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddTransferDialog/index.js +23 -28
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AddTransferDialog/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentItem/index.d.ts +2 -3
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentItem/index.js +81 -14
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentItem/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentList/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentList/index.js +11 -15
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/AllotmentList/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningContactItem/index.d.ts +2 -3
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningContactItem/index.js +34 -5
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningContactItem/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningList/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningList/index.js +4 -5
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/BankOpeningList/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/CapitalReceiptSelect/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/CapitalReceiptSelect/index.js +5 -4
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/CapitalReceiptSelect/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/OfficerDetailItem/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/OfficerDetailItem/index.js +32 -12
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/OfficerDetailItem/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferItem/index.d.ts +2 -3
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferItem/index.js +80 -13
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferItem/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferList/index.d.ts +1 -2
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferList/index.js +7 -9
- package/es/modules/self-registration/clda-form/incorporation/company-general/components/TransferList/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/incorporation/components/FormContactEditor/index.d.ts +3 -0
- package/es/modules/self-registration/clda-form/incorporation/components/FormContactEditor/index.js +4 -2
- package/es/modules/self-registration/clda-form/incorporation/components/FormContactEditor/index.js.map +1 -1
- package/es/modules/self-registration/clda-form/pages/CLDAFormDefaultView/Content.js +16 -1
- package/es/modules/self-registration/clda-form/pages/CLDAFormDefaultView/Content.js.map +1 -1
- package/es/routes.d.ts +1 -1
- package/es/routes.js +4 -2
- package/es/routes.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
import { ApiError, RequestBuilder } from "@voplus/api";
|
|
2
|
+
import { CAPTURED_FIELD_LABEL } from "@voplus/morpho-compliance/es/data/identityShape/constants";
|
|
3
|
+
import { utcdayjs } from "@voplus/morpho-ui/es/controls/UTCDatePicker/state";
|
|
4
|
+
import { message } from "antd";
|
|
5
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
6
|
+
/** The route a legal-generation form's composed payload is posted to (spec:3850). */
|
|
7
|
+
export const LEGAL_GENERATION_SUBMIT_ROUTE = "/api/document-assistants/legal-generation/submit";
|
|
8
|
+
/** The existing gallery templates support exactly these appointment positions. */
|
|
9
|
+
export const SUPPORTED_OFFICER_POSITIONS = ["Director", "Secretary"];
|
|
10
|
+
/** Reports whether an input position is supported by the existing gallery templates. */
|
|
11
|
+
export function isSupportedOfficerPosition(position) {
|
|
12
|
+
return SUPPORTED_OFFICER_POSITIONS.includes(position);
|
|
13
|
+
}
|
|
14
|
+
/** 检查服务端副本的显示类型,允许 legacy 缺项与明确空值。 */
|
|
15
|
+
function readParentCompanyDetails(value) {
|
|
16
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17
|
+
return undefined;
|
|
18
|
+
const data = value;
|
|
19
|
+
for (const key of ["name", "address", "email", "phone"])
|
|
20
|
+
if (data[key] != null && typeof data[key] !== "string")
|
|
21
|
+
return undefined;
|
|
22
|
+
if (data.identity != null && (typeof data.identity !== "object" || Array.isArray(data.identity)))
|
|
23
|
+
return undefined;
|
|
24
|
+
const identity = data.identity;
|
|
25
|
+
if (identity?.number != null && typeof identity.number !== "string")
|
|
26
|
+
return undefined;
|
|
27
|
+
return { name: data.name, address: data.address,
|
|
28
|
+
email: data.email, phone: data.phone,
|
|
29
|
+
number: identity?.number };
|
|
30
|
+
}
|
|
31
|
+
/** The CLDA meta key every legal-generation submission persists under (contract §1). */
|
|
32
|
+
export const LEGAL_GENERATION_META_KEY = "CHO";
|
|
33
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
34
|
+
/**
|
|
35
|
+
* The frozen snapshot of `shape` as the payload carries it (spec:3848): a copy of the members a
|
|
36
|
+
* snapshot owns, taken from the capture's own shape and never resolved against the shared catalog.
|
|
37
|
+
*
|
|
38
|
+
* @param shape the capture's frozen shape.
|
|
39
|
+
* @returns the snapshot the submit body and the form-content JSON column carry.
|
|
40
|
+
*/
|
|
41
|
+
export function toIdentityShapeSnapshot(shape) {
|
|
42
|
+
return {
|
|
43
|
+
sourceNumber: shape.source,
|
|
44
|
+
name: shape.name,
|
|
45
|
+
family: shape.family,
|
|
46
|
+
subject: shape.subject,
|
|
47
|
+
aliasPolicy: shape.policies.alias,
|
|
48
|
+
issuingCountryPolicy: shape.policies.issuingCountry,
|
|
49
|
+
expiryPolicy: shape.policies.expiryDate,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The identity values of one manual branch. The captured alias / issuing country / expiry date
|
|
54
|
+
* travel only where the captured shape's policy does not omit them (spec:3713), so a field the
|
|
55
|
+
* shape hides can never reach the payload even if its control once held a value.
|
|
56
|
+
*/
|
|
57
|
+
function toSubmitIdentity(branch, name) {
|
|
58
|
+
const capture = branch.Identity;
|
|
59
|
+
const policies = capture?.shape.policies;
|
|
60
|
+
return {
|
|
61
|
+
fullName: name,
|
|
62
|
+
number: branch.IdentityNumber === undefined ? undefined : String(branch.IdentityNumber),
|
|
63
|
+
country: branch.Country,
|
|
64
|
+
...(policies?.alias !== "omitted" ? { alias: capture?.values.alias } : {}),
|
|
65
|
+
...(policies?.issuingCountry !== "omitted"
|
|
66
|
+
? { issuingCountry: capture?.values.issuingCountry }
|
|
67
|
+
: {}),
|
|
68
|
+
...(policies?.expiryDate !== "omitted" ? { expiryDate: capture?.values.expiryDate } : {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The manual branch's person. The full name is typed as `FullName` by the AppointOfficer branch and
|
|
73
|
+
* as `IdentityName` by the CorporateRepresentative branch; both name the same person field.
|
|
74
|
+
*/
|
|
75
|
+
function toSubmitPerson(branch, documentName) {
|
|
76
|
+
const name = branch.FullName ?? branch.IdentityName;
|
|
77
|
+
const capture = branch.Identity;
|
|
78
|
+
return {
|
|
79
|
+
name,
|
|
80
|
+
...(documentName === "Corporate Representative"
|
|
81
|
+
? {
|
|
82
|
+
representative: name,
|
|
83
|
+
representativePassport: branch.IdentityNumber === undefined ? undefined : String(branch.IdentityNumber),
|
|
84
|
+
}
|
|
85
|
+
: {}),
|
|
86
|
+
email: branch.Email,
|
|
87
|
+
phone: branch.Contact,
|
|
88
|
+
type: "Person",
|
|
89
|
+
types: branch.OfficerType ? [branch.OfficerType] : undefined,
|
|
90
|
+
address: branch.Address,
|
|
91
|
+
identity: toSubmitIdentity(branch, name),
|
|
92
|
+
identityShape: capture ? toIdentityShapeSnapshot(capture.shape) : undefined,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// spec:1930 — CSP: 使用“Select existing”模式时,表单发送所选实体的 id;手动模式发送用户键入的字段
|
|
96
|
+
/**
|
|
97
|
+
* The `YYYY-MM-DD` date a submit body carries, or `null` when its control held no formattable date
|
|
98
|
+
* (spec:1928). The forms normalise their controls with `dayjs(value).format("YYYY-MM-DD")`, which
|
|
99
|
+
* answers the literal `"Invalid Date"` for an empty one, and the endpoint's `DateTime?` binding
|
|
100
|
+
* rejects that value with an opaque 400 — so an absent date is what the body must carry instead.
|
|
101
|
+
*
|
|
102
|
+
* @param date the date a form normalised.
|
|
103
|
+
* @returns the date the body carries, or null when there is none.
|
|
104
|
+
*/
|
|
105
|
+
function toSubmitDate(date) {
|
|
106
|
+
return date && /^\d{4}-\d{2}-\d{2}$/.test(date) ? date : null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Builds the submit request body from one form's composed submission (spec:1930): select-existing
|
|
110
|
+
* carries the picked entity's id and omits every typed person field, manual carries the typed
|
|
111
|
+
* person with its captured snapshot and omits the id.
|
|
112
|
+
*
|
|
113
|
+
* @param submission the document name plus the branch the form composed.
|
|
114
|
+
* @returns the body the conversion endpoint reads.
|
|
115
|
+
*/
|
|
116
|
+
export function buildLegalGenerationSubmitBody(submission) {
|
|
117
|
+
const { documentName, mode, branch, company, parentCompany, parentCompanyCountry, parentCompanyDetails, documentDate, effectiveDate, } = submission;
|
|
118
|
+
const entityId = branch.OfficerId ?? branch.IdentityId;
|
|
119
|
+
return {
|
|
120
|
+
documentName,
|
|
121
|
+
mode,
|
|
122
|
+
entityId: mode === "select-existing" ? entityId ?? null : null,
|
|
123
|
+
// The Company picker hands over the corporate's own camelCase read model, while a reopened
|
|
124
|
+
// document's restore seeds the PascalCase pair; both are read so the body never carries the
|
|
125
|
+
// empty id a PascalCase-only extraction produced.
|
|
126
|
+
company: company
|
|
127
|
+
? { id: company.id ?? company.Id ?? "", name: company.name ?? company.Name ?? "" }
|
|
128
|
+
: undefined,
|
|
129
|
+
...(documentName === "Corporate Representative"
|
|
130
|
+
? {
|
|
131
|
+
parentCompany: parentCompany
|
|
132
|
+
? {
|
|
133
|
+
id: parentCompany.id ?? parentCompany.Id ?? "",
|
|
134
|
+
name: parentCompany.name ?? parentCompany.Name ?? "",
|
|
135
|
+
}
|
|
136
|
+
: undefined,
|
|
137
|
+
parentCompanyCountry,
|
|
138
|
+
...(parentCompanyDetails !== undefined ? { parentCompanyDetails } : {}),
|
|
139
|
+
}
|
|
140
|
+
: {}),
|
|
141
|
+
documentDate: toSubmitDate(documentDate),
|
|
142
|
+
effectiveDate: toSubmitDate(effectiveDate),
|
|
143
|
+
person: mode === "manual" ? toSubmitPerson(branch, documentName) : undefined,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The message a failed submit carries (spec:3850). `ApiEndPoint` rejects with
|
|
148
|
+
* `` `${status} - ${bodyText}` `` and the conversion endpoint answers its failure message as a JSON
|
|
149
|
+
* string literal, so the body is unwrapped and anything else falls back to the raw text.
|
|
150
|
+
*
|
|
151
|
+
* @param error the rejection the endpoint raised.
|
|
152
|
+
* @returns the message the form shows.
|
|
153
|
+
*/
|
|
154
|
+
export function legalGenerationFailureMessage(error) {
|
|
155
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
156
|
+
const separator = text.indexOf(" - ");
|
|
157
|
+
const body = separator < 0 ? text : text.slice(separator + 3);
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(body);
|
|
160
|
+
if (typeof parsed === "string" && parsed.length > 0) {
|
|
161
|
+
return parsed;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// The body was not a JSON string literal.
|
|
166
|
+
}
|
|
167
|
+
return body || text;
|
|
168
|
+
}
|
|
169
|
+
/** Validate required and omitted values against the immutable policies before create or same-id save. */
|
|
170
|
+
export function validateLegalGenerationCapture(capture) {
|
|
171
|
+
const errors = {};
|
|
172
|
+
if (!capture)
|
|
173
|
+
return errors;
|
|
174
|
+
for (const field of ["alias", "issuingCountry", "expiryDate"]) {
|
|
175
|
+
const populated = typeof capture.values[field] === "string" && !!capture.values[field]?.trim();
|
|
176
|
+
if (capture.shape.policies[field] === "mandatory" && !populated)
|
|
177
|
+
errors[field] = `${CAPTURED_FIELD_LABEL[field]} is required for ${capture.shape.name}.`;
|
|
178
|
+
if (capture.shape.policies[field] === "omitted" && populated)
|
|
179
|
+
errors[field] = `${CAPTURED_FIELD_LABEL[field]} is not captured by ${capture.shape.name}.`;
|
|
180
|
+
}
|
|
181
|
+
return errors;
|
|
182
|
+
}
|
|
183
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
184
|
+
/** Fetch the ZIP with a bearer header and open a short-lived local URL, keeping credentials out of browser URLs. */
|
|
185
|
+
export async function downloadLegalGenerationDocument(document, accessToken, endpoint, open = (url) => {
|
|
186
|
+
const link = window.document.createElement("a");
|
|
187
|
+
link.href = url;
|
|
188
|
+
link.download = `${document.name || document.id}.zip`;
|
|
189
|
+
link.hidden = true;
|
|
190
|
+
window.document.body.appendChild(link);
|
|
191
|
+
try {
|
|
192
|
+
link.click();
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
link.remove();
|
|
196
|
+
}
|
|
197
|
+
}) {
|
|
198
|
+
const response = await endpoint.get(document.downloadUrl, new RequestBuilder().bearer(accessToken));
|
|
199
|
+
if (response.headers.get("Content-Type")?.split(";")[0].trim() !== "application/zip")
|
|
200
|
+
throw new Error("The document download did not return a ZIP archive.");
|
|
201
|
+
const url = URL.createObjectURL(await response.blob());
|
|
202
|
+
try {
|
|
203
|
+
open(url);
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
window.setTimeout(() => URL.revokeObjectURL(url), 60_000);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
210
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
211
|
+
/** Report delivery failures separately from persistence so the caller can retain the canonical saved id for retry. */
|
|
212
|
+
async function deliverLegalGeneration(result, endpoint, accessToken, open) {
|
|
213
|
+
try {
|
|
214
|
+
await downloadLegalGenerationDocument(result.document, accessToken, endpoint, open);
|
|
215
|
+
return { ok: true, result, document: result.document };
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
const failure = `The document was saved, but download failed: ${legalGenerationFailureMessage(error)}. Please retry.`;
|
|
219
|
+
message.error(failure);
|
|
220
|
+
return { ok: false, message: failure, result, document: result.document };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
224
|
+
/**
|
|
225
|
+
* Submits a legal-generation form's composed payload to the document conversion and delivers both
|
|
226
|
+
* continuations (spec:3850): on success the generated document is opened for download, and on
|
|
227
|
+
* failure the endpoint's message is shown and nothing is downloaded or reset — the caller's entered
|
|
228
|
+
* values and captured snapshot stay exactly as they were, so the form stays open for a correction
|
|
229
|
+
* and a retry.
|
|
230
|
+
*
|
|
231
|
+
* @param options the endpoint, the caller's access token and the composed submission.
|
|
232
|
+
* @returns the handoff outcome.
|
|
233
|
+
*/
|
|
234
|
+
export async function submitLegalGeneration(options) {
|
|
235
|
+
const { endpoint, accessToken, submission, open } = options;
|
|
236
|
+
let result;
|
|
237
|
+
try {
|
|
238
|
+
const response = await endpoint.post(LEGAL_GENERATION_SUBMIT_ROUTE, new RequestBuilder().json(buildLegalGenerationSubmitBody(submission)));
|
|
239
|
+
const body = await response.json();
|
|
240
|
+
if (!isSubmitResult(body))
|
|
241
|
+
throw new Error("The generated document response is invalid. Please retry.");
|
|
242
|
+
result = body;
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
const failure = legalGenerationFailureMessage(error);
|
|
246
|
+
message.error(failure);
|
|
247
|
+
return { ok: false, message: failure };
|
|
248
|
+
}
|
|
249
|
+
return deliverLegalGeneration(result, endpoint, accessToken, open);
|
|
250
|
+
}
|
|
251
|
+
/** The highest `source` the built-in shapes occupy; custom shapes are numbered above it. */
|
|
252
|
+
const LAST_BUILT_IN_SOURCE = 3;
|
|
253
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
254
|
+
/**
|
|
255
|
+
* Restores the capture a saved form value holds, from the frozen snapshot alone: no catalog lookup
|
|
256
|
+
* runs, so a source shape later renamed, re-policied or deleted still restores exactly what was
|
|
257
|
+
* captured (spec:3848). The snapshot omits the catalog's `builtIn` flag and its concurrency token,
|
|
258
|
+
* so the restored shape marks itself built-in from its `source` — built-ins are 1-3 (spec:3712).
|
|
259
|
+
*
|
|
260
|
+
* @param person the form person a load route returned.
|
|
261
|
+
* @returns the capture the manual-entry block reopens on, or undefined for a legacy value.
|
|
262
|
+
*/
|
|
263
|
+
export function toIdentityCapture(person) {
|
|
264
|
+
const snapshot = person.identityShape;
|
|
265
|
+
if (!snapshot) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
shape: {
|
|
270
|
+
source: snapshot.sourceNumber,
|
|
271
|
+
name: snapshot.name,
|
|
272
|
+
family: snapshot.family,
|
|
273
|
+
subject: snapshot.subject,
|
|
274
|
+
builtIn: snapshot.sourceNumber <= LAST_BUILT_IN_SOURCE,
|
|
275
|
+
policies: {
|
|
276
|
+
alias: snapshot.aliasPolicy,
|
|
277
|
+
issuingCountry: snapshot.issuingCountryPolicy,
|
|
278
|
+
expiryDate: snapshot.expiryPolicy,
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
values: {
|
|
282
|
+
// A save writes `null` for a captured field the frozen shape omits (spec:3713); the
|
|
283
|
+
// capture itself reads that as "no value", which is what its controls render.
|
|
284
|
+
alias: person.identity?.alias ?? undefined,
|
|
285
|
+
issuingCountry: person.identity?.issuingCountry ?? undefined,
|
|
286
|
+
expiryDate: person.identity?.expiryDate ?? undefined,
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/** The route a persisted form document is loaded from and written back to (contract §4). */
|
|
291
|
+
export function legalGenerationFormRoute(id) {
|
|
292
|
+
return `/api/document-assistants/forms/${id}`;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* The appointed person of an Appoint Officer document: the contact the officer appointments name,
|
|
296
|
+
* falling back to the composed contact when the appointments name none.
|
|
297
|
+
*/
|
|
298
|
+
function appointedPerson(content, contacts) {
|
|
299
|
+
const officerIds = (content.newOfficerAppointments?.officers ?? [])
|
|
300
|
+
.map((officer) => officer.officerId)
|
|
301
|
+
.filter((id) => !!id);
|
|
302
|
+
return (officerIds
|
|
303
|
+
.map((id) => contacts.find((contact) => contact.id === id))
|
|
304
|
+
.find((contact) => !!contact) ??
|
|
305
|
+
contacts.find((contact) => contact.idType === "NewId") ??
|
|
306
|
+
contacts[0]);
|
|
307
|
+
}
|
|
308
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
309
|
+
/** Completes a restored address before Ant Form can inject it into the eager Address control. */
|
|
310
|
+
function completeRestoredAddress(address) {
|
|
311
|
+
return {
|
|
312
|
+
line1: address?.line1 ?? "",
|
|
313
|
+
line2: address?.line2 ?? "",
|
|
314
|
+
city: address?.city ?? "",
|
|
315
|
+
state: address?.state ?? "",
|
|
316
|
+
postalCode: address?.postalCode ?? "",
|
|
317
|
+
country: address?.country ?? "",
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
321
|
+
/**
|
|
322
|
+
* Maps a supported named gallery document onto its first relevant captured person (spec:3848).
|
|
323
|
+
* The frozen snapshot restores its shape and values verbatim without a catalog lookup.
|
|
324
|
+
* The foreign parent remains separate from the Singapore company and representative identity.
|
|
325
|
+
*
|
|
326
|
+
* @param content the camelCase content a loaded Company General document carries.
|
|
327
|
+
* @returns what the gallery form reopens with, or undefined when no section of this endpoint's two
|
|
328
|
+
* is populated (a document another surface composed).
|
|
329
|
+
*/
|
|
330
|
+
export function toLegalGenerationRestore(content, documentName) {
|
|
331
|
+
const contacts = content.contacts ?? [];
|
|
332
|
+
const company = content.corporate?.id
|
|
333
|
+
? { Id: content.corporate.id, Name: content.corporate.name ?? "" }
|
|
334
|
+
: undefined;
|
|
335
|
+
// The persisted date is a C# `DateTime?` string, and both forms seed their `UTCDatePicker` with
|
|
336
|
+
// it, so it is converted here — at the restore boundary — with the same helper the platform's
|
|
337
|
+
// own company-general form reads the very same member with. An absent date stays undefined
|
|
338
|
+
// rather than becoming an `Invalid Date` the control would render as a broken value (spec:1928).
|
|
339
|
+
const date = content.date ? utcdayjs(content.date) : undefined;
|
|
340
|
+
if (documentName === "Appoint Officer" &&
|
|
341
|
+
(content.newOfficerAppointments?.officers ?? []).length > 0) {
|
|
342
|
+
const person = appointedPerson(content, contacts);
|
|
343
|
+
if (!person) {
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
documentName: "Appoint Officer",
|
|
348
|
+
mode: person.idType === "ExistingContactId" ? "select-existing" : "manual",
|
|
349
|
+
person,
|
|
350
|
+
identity: toIdentityCapture(person),
|
|
351
|
+
values: {
|
|
352
|
+
FullName: person.name,
|
|
353
|
+
Country: person.identity?.country,
|
|
354
|
+
OfficerType: person.types?.[0],
|
|
355
|
+
Email: person.email,
|
|
356
|
+
Contact: person.phone,
|
|
357
|
+
IdentityNumber: person.identity?.number,
|
|
358
|
+
Address: completeRestoredAddress(person.address),
|
|
359
|
+
Company: company,
|
|
360
|
+
DocumentDate: date,
|
|
361
|
+
EffectiveDate: content.effectiveDate ? utcdayjs(content.effectiveDate) : undefined,
|
|
362
|
+
Officer: person.selectedEntityId
|
|
363
|
+
? { id: person.selectedEntityId, name: person.name ?? "" }
|
|
364
|
+
: undefined,
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (documentName !== "Corporate Representative")
|
|
369
|
+
return undefined;
|
|
370
|
+
// A representative the endpoint resolved, or a snapshot the composition captured: either is the
|
|
371
|
+
// Corporate Representative section, the only other section this endpoint composes (contract §1/§3).
|
|
372
|
+
const person = contacts.find((contact) => !!contact.representative || !!contact.identityShape || !!contact.selectedIdentityId);
|
|
373
|
+
if (!person) {
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
const parentDetails = readParentCompanyDetails(content.parentCompanyData);
|
|
377
|
+
return {
|
|
378
|
+
documentName: "Corporate Representative",
|
|
379
|
+
parentCompanyBaseline: content.parentCompany?.id && parentDetails ? { parentId: content.parentCompany.id, details: parentDetails } : undefined,
|
|
380
|
+
mode: person.idType === "ExistingContactId" ? "select-existing" : "manual",
|
|
381
|
+
person,
|
|
382
|
+
identity: toIdentityCapture(person),
|
|
383
|
+
values: {
|
|
384
|
+
ParentCompany: content.parentCompany?.id
|
|
385
|
+
? { Id: content.parentCompany.id, Name: content.parentCompany.name ?? "" }
|
|
386
|
+
: undefined,
|
|
387
|
+
// spec:3848 — 代表身份国家与母公司国家分别恢复;签发国家仍由快照字段恢复。
|
|
388
|
+
Country: content.parentCompanyCountry ?? undefined,
|
|
389
|
+
RepresentativeCountry: person.identity?.country ?? undefined,
|
|
390
|
+
IdentityName: person.identity?.fullName ?? person.name,
|
|
391
|
+
IdentityNumber: person.identity?.number,
|
|
392
|
+
Company: company,
|
|
393
|
+
Date: date,
|
|
394
|
+
LegalContact: person.selectedEntityId || person.selectedIdentityId
|
|
395
|
+
? {
|
|
396
|
+
id: person.selectedEntityId ?? person.selectedIdentityId,
|
|
397
|
+
name: person.name ?? "",
|
|
398
|
+
}
|
|
399
|
+
: undefined,
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/** Whether a section differs from the empty default CHO payload. */
|
|
404
|
+
function hasPopulatedSection(value) {
|
|
405
|
+
if (Array.isArray(value))
|
|
406
|
+
return value.length > 0;
|
|
407
|
+
if (value && typeof value === "object")
|
|
408
|
+
return Object.values(value).some(hasPopulatedSection);
|
|
409
|
+
return value !== null && value !== undefined && value !== "" && value !== false && value !== 0;
|
|
410
|
+
}
|
|
411
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
412
|
+
/** 用规范模板识别逻辑类型;未标记旧文书仍需原有名称及独立内容证据。 */
|
|
413
|
+
export function resolveGalleryDocumentKind(document) {
|
|
414
|
+
if (document.metaKey !== LEGAL_GENERATION_META_KEY || document.country !== "SGP")
|
|
415
|
+
return undefined;
|
|
416
|
+
const keys = document.content?.generationTemplateKeys;
|
|
417
|
+
const kind = keys == null ? document.name : Array.isArray(keys) && keys.length === 1 && keys[0] === "RepresentativeCert" ? "Corporate Representative" : "Appoint Officer";
|
|
418
|
+
if (kind !== "Appoint Officer" && kind !== "Corporate Representative")
|
|
419
|
+
return undefined;
|
|
420
|
+
const content = document.content;
|
|
421
|
+
if (!content)
|
|
422
|
+
return undefined;
|
|
423
|
+
const contacts = content.contacts ?? [];
|
|
424
|
+
const appointments = content.newOfficerAppointments?.officers ?? [];
|
|
425
|
+
if (!Array.isArray(contacts) || !Array.isArray(appointments))
|
|
426
|
+
return undefined;
|
|
427
|
+
if (contacts.some((contact) => !contact || typeof contact !== "object") ||
|
|
428
|
+
appointments.some((position) => !position || typeof position !== "object"))
|
|
429
|
+
return undefined;
|
|
430
|
+
const people = kind === "Appoint Officer"
|
|
431
|
+
? appointments
|
|
432
|
+
.map((position) => contacts.find((contact) => contact.id === position.officerId))
|
|
433
|
+
.filter(Boolean)
|
|
434
|
+
: contacts.filter((contact) => typeof contact.representative === "string" && !!contact.representative.trim());
|
|
435
|
+
if (!people.length || (kind === "Appoint Officer" && !contacts.some((contact) => contact.id === appointments[0]?.officerId)))
|
|
436
|
+
return undefined;
|
|
437
|
+
if (appointments[0]?.positions != null && !Array.isArray(appointments[0].positions))
|
|
438
|
+
return undefined;
|
|
439
|
+
const positions = [...new Set(appointments[0]?.positions ?? [])];
|
|
440
|
+
if (kind === "Appoint Officer" &&
|
|
441
|
+
(!positions.length ||
|
|
442
|
+
positions.some((position) => !isSupportedOfficerPosition(position))))
|
|
443
|
+
return undefined;
|
|
444
|
+
const expected = kind === "Corporate Representative"
|
|
445
|
+
? ["RepresentativeCert"]
|
|
446
|
+
: [
|
|
447
|
+
"BoardResolution",
|
|
448
|
+
...(positions.includes("Director") ? ["Form45"] : []),
|
|
449
|
+
...(positions.includes("Secretary") ? ["Form45B"] : []),
|
|
450
|
+
];
|
|
451
|
+
if (content.generationTemplateKeys != null)
|
|
452
|
+
return (Array.isArray(content.generationTemplateKeys) &&
|
|
453
|
+
JSON.stringify(content.generationTemplateKeys) === JSON.stringify(expected)) ? kind : undefined;
|
|
454
|
+
if (document.parentNode != null ||
|
|
455
|
+
!!document.parentNodeId ||
|
|
456
|
+
contacts.length !== 1 ||
|
|
457
|
+
people.length !== 1)
|
|
458
|
+
return undefined;
|
|
459
|
+
const allowed = [
|
|
460
|
+
"corporate",
|
|
461
|
+
"date",
|
|
462
|
+
"effectiveDate",
|
|
463
|
+
"contacts",
|
|
464
|
+
"newOfficerAppointments",
|
|
465
|
+
"generationTemplateKeys",
|
|
466
|
+
"parentCompany",
|
|
467
|
+
"parentCompanyCountry",
|
|
468
|
+
"parentCompanyData",
|
|
469
|
+
];
|
|
470
|
+
return Object.entries(content).every(([key, value]) => allowed.includes(key) || !hasPopulatedSection(value)) ? kind : undefined;
|
|
471
|
+
}
|
|
472
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
473
|
+
/**
|
|
474
|
+
* The document a legal-generation page was opened on, when the id it carries names a persisted
|
|
475
|
+
* Company General document this endpoint composed (contract §1/§4). Anything else — another id, a
|
|
476
|
+
* document family this gallery does not compose, a content whose sections are both empty — answers
|
|
477
|
+
* undefined; the saved-id load gate treats unsupported responses as a failure.
|
|
478
|
+
*
|
|
479
|
+
* @param document the document a load returned, when one was loaded at all.
|
|
480
|
+
* @returns the reopened document, or undefined when the page composes a new one.
|
|
481
|
+
*/
|
|
482
|
+
export function toReopenedLegalGeneration(document) {
|
|
483
|
+
if (!document ||
|
|
484
|
+
document.metaKey !== LEGAL_GENERATION_META_KEY ||
|
|
485
|
+
!resolveGalleryDocumentKind(document)) {
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
const content = document.content ?? {};
|
|
489
|
+
const restore = toLegalGenerationRestore(content, resolveGalleryDocumentKind(document));
|
|
490
|
+
if (!restore) {
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
return { id: document.id, content, ...restore };
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Maps the camelCase address a load route returns onto the PascalCase one the save route reads.
|
|
497
|
+
*/
|
|
498
|
+
function toAddressEdit(address) {
|
|
499
|
+
return {
|
|
500
|
+
Line1: address.line1,
|
|
501
|
+
Line2: address.line2 ?? null,
|
|
502
|
+
City: address.city ?? null,
|
|
503
|
+
State: address.state ?? null,
|
|
504
|
+
PostalCode: address.postalCode ?? null,
|
|
505
|
+
Country: address.country,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Fixture/legacy helper mapping a loaded person onto the generic PascalCase edit contract, copying
|
|
510
|
+
* every value verbatim — including the captured snapshot, whose frozen `Name` and three policies
|
|
511
|
+
* are written back exactly as they were read (spec:3848).
|
|
512
|
+
*/
|
|
513
|
+
function toFormPersonEdit(person) {
|
|
514
|
+
return {
|
|
515
|
+
Id: person.id ?? "",
|
|
516
|
+
IdType: person.idType ?? "NewId",
|
|
517
|
+
// spec:3848 — Preserve selected provenance alongside the frozen values on unchanged save.
|
|
518
|
+
SelectedEntityId: person.selectedEntityId ?? null,
|
|
519
|
+
SelectedIdentityId: person.selectedIdentityId ?? null,
|
|
520
|
+
Name: person.name ?? "",
|
|
521
|
+
Email: person.email ?? null,
|
|
522
|
+
Phone: person.phone ?? null,
|
|
523
|
+
Type: person.type ?? null,
|
|
524
|
+
Types: person.types ?? null,
|
|
525
|
+
Representative: person.representative ?? null,
|
|
526
|
+
RepresentativePassport: person.representativePassport ?? null,
|
|
527
|
+
Address: person.address ? toAddressEdit(person.address) : null,
|
|
528
|
+
Identity: person.identity
|
|
529
|
+
? {
|
|
530
|
+
FullName: person.identity.fullName ?? null,
|
|
531
|
+
Number: person.identity.number ?? null,
|
|
532
|
+
Country: person.identity.country ?? null,
|
|
533
|
+
Alias: person.identity.alias ?? null,
|
|
534
|
+
IssuingCountry: person.identity.issuingCountry ?? null,
|
|
535
|
+
ExpiryDate: person.identity.expiryDate ?? null,
|
|
536
|
+
}
|
|
537
|
+
: null,
|
|
538
|
+
IdentityShape: person.identityShape
|
|
539
|
+
? {
|
|
540
|
+
SourceNumber: person.identityShape.sourceNumber,
|
|
541
|
+
Name: person.identityShape.name,
|
|
542
|
+
Family: person.identityShape.family,
|
|
543
|
+
Subject: person.identityShape.subject,
|
|
544
|
+
AliasPolicy: person.identityShape.aliasPolicy,
|
|
545
|
+
IssuingCountryPolicy: person.identityShape.issuingCountryPolicy,
|
|
546
|
+
ExpiryPolicy: person.identityShape.expiryPolicy,
|
|
547
|
+
}
|
|
548
|
+
: null,
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
552
|
+
/**
|
|
553
|
+
* Maps the form content a load route returned onto the PascalCase
|
|
554
|
+
* `CompanyGeneral.SGP.FormEditOptions` the platform save route reads (contract §4). Every value is
|
|
555
|
+
* copied unchanged — in particular the frozen `IdentityShape` snapshot — so save → reopen → resubmit
|
|
556
|
+
* round-trips the snapshot byte-identically, with no catalog resolution and no dependence on the
|
|
557
|
+
* source shape still existing (spec:3848).
|
|
558
|
+
*
|
|
559
|
+
* Two members are deliberately shaped by the route's own semantics: `Corporate` is never sent,
|
|
560
|
+
* because a company whose id differs from the stored one reads as "the document moved company" and
|
|
561
|
+
* unions the whole roster into `Contacts`; and `Contacts` carries the **complete** list, because a
|
|
562
|
+
* sent list replaces the stored one wholesale — omitting an entry would delete it.
|
|
563
|
+
*
|
|
564
|
+
* @param content the camelCase content a loaded legal-generation form carries.
|
|
565
|
+
* @returns the payload the double-encoded save body carries.
|
|
566
|
+
*/
|
|
567
|
+
export function toFormContentEditPayload(content) {
|
|
568
|
+
const contacts = content.contacts;
|
|
569
|
+
const officers = content.newOfficerAppointments?.officers;
|
|
570
|
+
return {
|
|
571
|
+
Date: content.date ?? null,
|
|
572
|
+
...(contacts ? { Contacts: contacts.map(toFormPersonEdit) } : {}),
|
|
573
|
+
...(officers && officers.length > 0
|
|
574
|
+
? {
|
|
575
|
+
// The route binds this body with case-SENSITIVE `System.Text.Json`, so the
|
|
576
|
+
// read model's camelCase members have to be mapped onto the contract's
|
|
577
|
+
// PascalCase ones — sent verbatim they bind to nothing and wipe the link.
|
|
578
|
+
NewOfficerAppointments: {
|
|
579
|
+
Officers: officers.map((officer) => ({
|
|
580
|
+
Positions: officer.positions ?? [],
|
|
581
|
+
OfficerId: officer.officerId,
|
|
582
|
+
})),
|
|
583
|
+
},
|
|
584
|
+
}
|
|
585
|
+
: {}),
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* One captured identity field of a reopened person's save, decided from the **frozen snapshot's own
|
|
590
|
+
* policy** rather than from what the capture happens to hold (spec:3713): the replacement shape's
|
|
591
|
+
* `omitted` policy clears the persisted value to `null` — the capture has already dropped the key,
|
|
592
|
+
* and spreading it would leave the forbidden value in place, where no control can clear it — while a
|
|
593
|
+
* captured policy emits the value the user left there, or `null` when the capture holds none. A
|
|
594
|
+
* person with no capture at all has no policy to consult, so the persisted value it carries is kept.
|
|
595
|
+
*
|
|
596
|
+
* @param person the loaded person whose persisted identity the save writes back.
|
|
597
|
+
* @param capture the capture the re-composed branch holds, when it holds one.
|
|
598
|
+
* @param field the captured identity field to decide.
|
|
599
|
+
* @returns the value the saved identity carries for that field.
|
|
600
|
+
*/
|
|
601
|
+
function toEditedIdentityValue(person, capture, field) {
|
|
602
|
+
if (!capture) {
|
|
603
|
+
return person.identity?.[field];
|
|
604
|
+
}
|
|
605
|
+
return capture.shape.policies[field] === "omitted" ? null : capture.values[field] ?? null;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* The person a reopened document's save writes back: the contact the load returned, with the values
|
|
609
|
+
* the form re-composed folded into it. The contact's own identity — its id, the type the endpoint
|
|
610
|
+
* resolved and the members this form does not edit — is copied unchanged, so the save can never
|
|
611
|
+
* drop a value the document carries (contract §4).
|
|
612
|
+
*/
|
|
613
|
+
function toLegalGenerationEditedPerson(person, branch) {
|
|
614
|
+
const capture = branch.Identity;
|
|
615
|
+
const name = branch.FullName ?? branch.IdentityName ?? person.name;
|
|
616
|
+
return {
|
|
617
|
+
...person,
|
|
618
|
+
name,
|
|
619
|
+
email: branch.Email ?? person.email,
|
|
620
|
+
phone: branch.Contact ?? person.phone,
|
|
621
|
+
address: branch.Address ?? person.address,
|
|
622
|
+
identity: {
|
|
623
|
+
...person.identity,
|
|
624
|
+
fullName: name,
|
|
625
|
+
number: branch.IdentityNumber === undefined
|
|
626
|
+
? person.identity?.number
|
|
627
|
+
: String(branch.IdentityNumber),
|
|
628
|
+
country: branch.Country ?? person.identity?.country,
|
|
629
|
+
// Each captured field is decided by the frozen snapshot's own policy rather than by what
|
|
630
|
+
// the capture happens to hold, so a field the shape omits can never survive into the
|
|
631
|
+
// saved document (spec:3713).
|
|
632
|
+
alias: toEditedIdentityValue(person, capture, "alias"),
|
|
633
|
+
issuingCountry: toEditedIdentityValue(person, capture, "issuingCountry"),
|
|
634
|
+
expiryDate: toEditedIdentityValue(person, capture, "expiryDate"),
|
|
635
|
+
},
|
|
636
|
+
identityShape: capture ? toIdentityShapeSnapshot(capture.shape) : person.identityShape,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
640
|
+
/**
|
|
641
|
+
* The content a reopened form's save writes back (contract §4): the document's own content with the
|
|
642
|
+
* branch the user re-composed folded into the section's contact, and every other contact, the officer
|
|
643
|
+
* appointments and the document date copied unchanged — so the list the save replaces wholesale is
|
|
644
|
+
* still the complete one (spec:3848).
|
|
645
|
+
*
|
|
646
|
+
* Only a manual branch folds. A select-existing save keeps the contact the endpoint resolved when it
|
|
647
|
+
* composed the document: the id the picker posts is an officer / legal-contact id, and only the
|
|
648
|
+
* server can resolve it to the contact id the document addresses its people by (contract §3.1).
|
|
649
|
+
*
|
|
650
|
+
* @param reopened the document the form was reopened on.
|
|
651
|
+
* @param branch the branch the form re-composed.
|
|
652
|
+
* @param documentDate the date the form carries, already normalised to `YYYY-MM-DD`.
|
|
653
|
+
* @returns the content {@link toFormContentEditPayload} writes back.
|
|
654
|
+
*/
|
|
655
|
+
export function toLegalGenerationSavedContent(reopened, branch, documentDate) {
|
|
656
|
+
const date = documentDate && /^\d{4}-\d{2}-\d{2}$/.test(documentDate) ? documentDate : reopened.content.date;
|
|
657
|
+
if (reopened.mode !== "manual") {
|
|
658
|
+
return { ...reopened.content, date };
|
|
659
|
+
}
|
|
660
|
+
const edited = toLegalGenerationEditedPerson(reopened.person, branch);
|
|
661
|
+
const contacts = (reopened.content.contacts ?? []).map((contact) => contact.id === edited.id ? edited : contact);
|
|
662
|
+
// An Appoint Officer document records the appointment on its own section, addressed by the
|
|
663
|
+
// contact's id, so the position follows the officer type the form re-composed (contract §3).
|
|
664
|
+
const officers = reopened.content.newOfficerAppointments?.officers?.map((officer) => officer.officerId === edited.id && branch.OfficerType
|
|
665
|
+
? { ...officer, positions: [branch.OfficerType] }
|
|
666
|
+
: officer);
|
|
667
|
+
return {
|
|
668
|
+
...reopened.content,
|
|
669
|
+
date,
|
|
670
|
+
contacts,
|
|
671
|
+
...(officers ? { newOfficerAppointments: { officers } } : {}),
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
675
|
+
/** The message a load failure other than a missing document surfaces (spec:3848). */
|
|
676
|
+
export const LEGAL_GENERATION_LOAD_FAILURE_MESSAGE = "Failed to load the saved document. Please reopen it from the document list and try again.";
|
|
677
|
+
/** Reject malformed or unsupported saved documents before controls can consume them. */
|
|
678
|
+
function isSavedDocument(value, id) {
|
|
679
|
+
if (!value || typeof value !== "object")
|
|
680
|
+
return false;
|
|
681
|
+
const document = value;
|
|
682
|
+
if (document.id !== id ||
|
|
683
|
+
document.metaKey !== LEGAL_GENERATION_META_KEY ||
|
|
684
|
+
document.country !== "SGP" ||
|
|
685
|
+
!document.content ||
|
|
686
|
+
typeof document.content !== "object")
|
|
687
|
+
return false;
|
|
688
|
+
const content = document.content;
|
|
689
|
+
const company = content.corporate;
|
|
690
|
+
if (!company || typeof company.id !== "string" || !company.id || typeof company.name !== "string")
|
|
691
|
+
return false;
|
|
692
|
+
if (content.parentCompany != null) {
|
|
693
|
+
if (typeof content.parentCompany !== "object" || Array.isArray(content.parentCompany))
|
|
694
|
+
return false;
|
|
695
|
+
const parent = content.parentCompany;
|
|
696
|
+
if (typeof parent.id !== "string" || !parent.id || typeof parent.name !== "string")
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
if (content.parentCompanyCountry != null && typeof content.parentCompanyCountry !== "string")
|
|
700
|
+
return false;
|
|
701
|
+
if (content.parentCompanyData != null && !readParentCompanyDetails(content.parentCompanyData))
|
|
702
|
+
return false;
|
|
703
|
+
if (!Array.isArray(content.contacts) ||
|
|
704
|
+
content.contacts.some((person) => !person ||
|
|
705
|
+
typeof person !== "object" ||
|
|
706
|
+
typeof person.id !== "string"))
|
|
707
|
+
return false;
|
|
708
|
+
for (const person of content.contacts) {
|
|
709
|
+
if (person.representative != null && typeof person.representative !== "string")
|
|
710
|
+
return false;
|
|
711
|
+
if (person.identity &&
|
|
712
|
+
(typeof person.identity !== "object" ||
|
|
713
|
+
Array.isArray(person.identity) ||
|
|
714
|
+
["fullName", "number", "country", "alias", "issuingCountry", "expiryDate"].some((key) => {
|
|
715
|
+
const field = person.identity?.[key];
|
|
716
|
+
return field != null && typeof field !== "string";
|
|
717
|
+
})))
|
|
718
|
+
return false;
|
|
719
|
+
const shape = person.identityShape;
|
|
720
|
+
if (shape &&
|
|
721
|
+
(typeof shape !== "object" ||
|
|
722
|
+
!Number.isInteger(shape.sourceNumber) ||
|
|
723
|
+
shape.sourceNumber < 1 ||
|
|
724
|
+
typeof shape.name !== "string" ||
|
|
725
|
+
!["Passport", "NationalIdentity", "BusinessRegistration", "Other"].includes(shape.family) ||
|
|
726
|
+
!["Person", "Organization", "Both"].includes(shape.subject) ||
|
|
727
|
+
[shape.aliasPolicy, shape.issuingCountryPolicy, shape.expiryPolicy].some((policy) => !["omitted", "available", "mandatory"].includes(policy))))
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
if (content.newOfficerAppointments != null) {
|
|
731
|
+
if (typeof content.newOfficerAppointments !== "object")
|
|
732
|
+
return false;
|
|
733
|
+
const officers = content.newOfficerAppointments.officers;
|
|
734
|
+
if (!Array.isArray(officers) ||
|
|
735
|
+
officers.some((officer) => !officer ||
|
|
736
|
+
typeof officer !== "object" ||
|
|
737
|
+
typeof officer.officerId !== "string" ||
|
|
738
|
+
!Array.isArray(officer.positions) ||
|
|
739
|
+
officer.positions.some((position) => typeof position !== "string") ||
|
|
740
|
+
!content.contacts.some((contact) => contact.id === officer.officerId)))
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
for (const field of ["date", "effectiveDate"]) {
|
|
744
|
+
if (content[field] != null &&
|
|
745
|
+
(typeof content[field] !== "string" || !utcdayjs(content[field]).isValid()))
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
return !!toReopenedLegalGeneration(value);
|
|
749
|
+
}
|
|
750
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
751
|
+
/** Load a saved CHO composition; only 404 is missing, other failures remain failures. */
|
|
752
|
+
export async function loadLegalGenerationForm(options) {
|
|
753
|
+
try {
|
|
754
|
+
const builder = new RequestBuilder();
|
|
755
|
+
builder.FetchRequest({ signal: options.signal });
|
|
756
|
+
const response = await options.endpoint.get(legalGenerationFormRoute(options.id), builder);
|
|
757
|
+
const document = await response.json();
|
|
758
|
+
if (!isSavedDocument(document, options.id))
|
|
759
|
+
throw new Error(LEGAL_GENERATION_LOAD_FAILURE_MESSAGE);
|
|
760
|
+
return document;
|
|
761
|
+
}
|
|
762
|
+
catch (error) {
|
|
763
|
+
if (error instanceof ApiError && error.status === 404)
|
|
764
|
+
return undefined;
|
|
765
|
+
throw error;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
769
|
+
/**
|
|
770
|
+
* Fixture/legacy generic-save helper writing re-composed content to its existing document
|
|
771
|
+
* (contract §4): the PascalCase payload of {@link toFormContentEditPayload}, sent as the JSON **text**
|
|
772
|
+
* the platform save route binds with case-sensitive `System.Text.Json`.
|
|
773
|
+
*
|
|
774
|
+
* This generic route remains for fixture/legacy callers. Production gallery editors call
|
|
775
|
+
* saveLegalGeneration, whose dedicated /save route owns selected composition and regeneration.
|
|
776
|
+
*
|
|
777
|
+
* @param options the endpoint, the persisted document's id and the content to write back.
|
|
778
|
+
* @returns the save outcome; a failure is surfaced through the same channel the submit uses.
|
|
779
|
+
*/
|
|
780
|
+
export async function saveLegalGenerationContent(options) {
|
|
781
|
+
const { endpoint, id, content } = options;
|
|
782
|
+
try {
|
|
783
|
+
// The payload is the JSON TEXT of the edit options, exactly as the platform's own form save
|
|
784
|
+
// posts it (`new RequestBuilder().json(JSON.stringify(data))`), not the object itself.
|
|
785
|
+
await endpoint.post(legalGenerationFormRoute(id), new RequestBuilder().json(JSON.stringify(toFormContentEditPayload(content))));
|
|
786
|
+
return { ok: true };
|
|
787
|
+
}
|
|
788
|
+
catch (error) {
|
|
789
|
+
const failure = legalGenerationFailureMessage(error);
|
|
790
|
+
message.error(failure);
|
|
791
|
+
return { ok: false, message: failure };
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
// spec:1930 — CSP: 使用“Select existing”模式时,表单发送所选实体的 id;手动模式发送用户键入的字段
|
|
795
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
796
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
797
|
+
/** Production gallery save: resolve the complete edited branch through the dedicated /save route, then download the regenerated existing ZIP. */
|
|
798
|
+
export async function saveLegalGeneration(options) {
|
|
799
|
+
let saved;
|
|
800
|
+
try {
|
|
801
|
+
const response = await options.endpoint.post(`/api/document-assistants/legal-generation/${encodeURIComponent(options.id)}/save`, new RequestBuilder().json(buildLegalGenerationSubmitBody(options.submission)));
|
|
802
|
+
const result = await response.json();
|
|
803
|
+
if (!isSubmitResult(result, options.id))
|
|
804
|
+
throw new Error("The saved document response is invalid. Please retry.");
|
|
805
|
+
saved = result;
|
|
806
|
+
}
|
|
807
|
+
catch (error) {
|
|
808
|
+
const failure = legalGenerationFailureMessage(error);
|
|
809
|
+
message.error(failure);
|
|
810
|
+
return { ok: false, message: failure };
|
|
811
|
+
}
|
|
812
|
+
return deliverLegalGeneration(saved, options.endpoint, options.accessToken, options.open);
|
|
813
|
+
}
|
|
814
|
+
// spec:3848 — CSP form identities retain their selected shape snapshot
|
|
815
|
+
// spec:3850 — CSP: 法律文书生成表单提交时把组合后的载荷送交转换
|
|
816
|
+
/** Validate canonical returned content and the same-id ZIP reference before reseeding or downloading. */
|
|
817
|
+
function isSubmitResult(value, savedId) {
|
|
818
|
+
if (!value || typeof value !== "object")
|
|
819
|
+
return false;
|
|
820
|
+
const result = value;
|
|
821
|
+
if (typeof result.id !== "string" ||
|
|
822
|
+
!result.id ||
|
|
823
|
+
(savedId && result.id !== savedId) ||
|
|
824
|
+
!["Appoint Officer", "Corporate Representative"].includes(result.documentName) ||
|
|
825
|
+
!["manual", "select-existing"].includes(result.mode))
|
|
826
|
+
return false;
|
|
827
|
+
return (isSavedDocument({
|
|
828
|
+
id: result.id,
|
|
829
|
+
metaKey: result.metaKey,
|
|
830
|
+
country: "SGP",
|
|
831
|
+
name: result.documentName,
|
|
832
|
+
content: result.content,
|
|
833
|
+
}, result.id) &&
|
|
834
|
+
resolveGalleryDocumentKind({ id: result.id, metaKey: result.metaKey, country: "SGP", name: result.documentName, content: result.content }) === result.documentName &&
|
|
835
|
+
result.document?.id === result.id &&
|
|
836
|
+
result.document.contentType === "application/zip" &&
|
|
837
|
+
result.document.downloadUrl ===
|
|
838
|
+
`/api/document-assistants/legal-generation/${encodeURIComponent(result.id)}/download`);
|
|
839
|
+
}
|
|
840
|
+
//# sourceMappingURL=legalGenerationSubmit.js.map
|