@salesforce/ui-bundle-template-feature-property-management-metadata 11.1.0 → 11.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/ui-bundle-template-feature-property-management-metadata",
|
|
3
|
-
"version": "11.1.
|
|
3
|
+
"version": "11.1.2",
|
|
4
4
|
"description": "Shared Property Management TDX object metadata and data for B2E/B2X sample apps",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"author": "",
|
|
@@ -1,85 +1,156 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Property-management seed-data prep for "sf data import tree".
|
|
4
|
+
*
|
|
5
|
+
* Ships alongside this feature's seed data so it can be run repeatedly (e.g.
|
|
6
|
+
* after the org already has data) without hitting duplicate rules, and so all
|
|
7
|
+
* @-references resolve. org-setup.mjs invokes whatever prepare script lives in
|
|
8
|
+
* the app's data dir — the generic template script carries no object-specific
|
|
9
|
+
* logic.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node prepare-import-unique-fields.js
|
|
13
|
+
* node prepare-import-unique-fields.js --data-dir /path/to/<sfdx-source>/data
|
|
14
|
+
*
|
|
15
|
+
* Operates on (each optional — missing files are skipped):
|
|
16
|
+
* Contact.json (Email unique domain+local, LastName, FirstName, Phone)
|
|
17
|
+
* Agent__c.json (License_Number__c — unique per record)
|
|
18
|
+
* Property_Management_Company__c.json (Company_Code__c, max 10 chars)
|
|
19
|
+
* Property_Owner__c.json (Email__c)
|
|
20
|
+
* Lease__c.json (Tenant__c → @TenantRef remapped into Tenant__c.json's refs)
|
|
21
|
+
* Maintenance_Request__c.json (User__c → @TenantRef remapped likewise)
|
|
5
22
|
*/
|
|
23
|
+
|
|
6
24
|
const fs = require("fs");
|
|
7
25
|
const path = require("path");
|
|
8
|
-
|
|
26
|
+
|
|
27
|
+
function parseArgs() {
|
|
28
|
+
const args = process.argv.slice(2);
|
|
29
|
+
let dataDir = __dirname;
|
|
30
|
+
for (let i = 0; i < args.length; i++) {
|
|
31
|
+
if (args[i] === "--data-dir" && args[i + 1]) {
|
|
32
|
+
dataDir = path.resolve(args[++i]);
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return dataDir;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const dataDir = parseArgs();
|
|
9
40
|
const runId = Date.now();
|
|
10
41
|
const runSuffix2 = String(runId % 100).padStart(2, "0"); // 00-99 for Company_Code__c (10-char limit)
|
|
11
42
|
|
|
12
|
-
// Contact: Email
|
|
43
|
+
// Contact: Email (unique domain + local), LastName, FirstName, Phone — avoid duplicate rules
|
|
13
44
|
const contactPath = path.join(dataDir, "Contact.json");
|
|
14
|
-
|
|
15
|
-
contact.
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
45
|
+
if (fs.existsSync(contactPath)) {
|
|
46
|
+
let contact = JSON.parse(fs.readFileSync(contactPath, "utf8"));
|
|
47
|
+
if (contact.records) {
|
|
48
|
+
contact.records.forEach((r, i) => {
|
|
49
|
+
if (r.Email && r.Email.includes("@")) {
|
|
50
|
+
const parts = r.Email.replace(/\+[0-9]+@/, "@").split("@");
|
|
51
|
+
const local = (parts[0] || "user") + "+" + runId;
|
|
52
|
+
const domain = "run" + runId + ".example.com";
|
|
53
|
+
r.Email = local + "@" + domain;
|
|
54
|
+
}
|
|
55
|
+
if (r.LastName) r.LastName = String(r.LastName).replace(/-[0-9]+$/, "") + "-" + runId;
|
|
56
|
+
if (r.FirstName) r.FirstName = String(r.FirstName).replace(/-[0-9]+$/, "") + "-" + (i + 1);
|
|
57
|
+
if (r.Phone) r.Phone = String(r.Phone).replace(/\d{2}$/, runSuffix2);
|
|
58
|
+
});
|
|
59
|
+
fs.writeFileSync(contactPath, JSON.stringify(contact, null, 2));
|
|
60
|
+
console.log("Updated Contact.json (Email, LastName, FirstName, Phone)");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
22
63
|
|
|
23
|
-
// Agent__c: License_Number__c —
|
|
64
|
+
// Agent__c: License_Number__c — unique per record (field is often unique in org)
|
|
24
65
|
const agentPath = path.join(dataDir, "Agent__c.json");
|
|
25
|
-
|
|
26
|
-
agent.
|
|
27
|
-
if (
|
|
28
|
-
r
|
|
29
|
-
r.License_Number__c
|
|
30
|
-
|
|
31
|
-
|
|
66
|
+
if (fs.existsSync(agentPath)) {
|
|
67
|
+
let agent = JSON.parse(fs.readFileSync(agentPath, "utf8"));
|
|
68
|
+
if (agent.records) {
|
|
69
|
+
agent.records.forEach((r, i) => {
|
|
70
|
+
if (r.License_Number__c) {
|
|
71
|
+
const base = r.License_Number__c.replace(/-[0-9]+(-[0-9]+)?$/, "");
|
|
72
|
+
r.License_Number__c = base + "-" + runId + "-" + (i + 1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
fs.writeFileSync(agentPath, JSON.stringify(agent, null, 2));
|
|
76
|
+
console.log("Updated Agent__c.json (License_Number__c)");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
32
79
|
|
|
33
80
|
// Property_Management_Company__c: Company_Code__c — max 10 chars, use 8-char base + 2-digit suffix
|
|
34
81
|
const companyPath = path.join(dataDir, "Property_Management_Company__c.json");
|
|
35
|
-
|
|
36
|
-
company.
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
82
|
+
if (fs.existsSync(companyPath)) {
|
|
83
|
+
let company = JSON.parse(fs.readFileSync(companyPath, "utf8"));
|
|
84
|
+
if (company.records) {
|
|
85
|
+
company.records.forEach((r) => {
|
|
86
|
+
if (r.Company_Code__c) r.Company_Code__c = r.Company_Code__c.slice(0, 8) + runSuffix2;
|
|
87
|
+
});
|
|
88
|
+
fs.writeFileSync(companyPath, JSON.stringify(company, null, 2));
|
|
89
|
+
console.log("Updated Property_Management_Company__c.json (Company_Code__c)");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
40
92
|
|
|
41
93
|
// Property_Owner__c: Email__c — add +runId before @
|
|
42
94
|
const ownerPath = path.join(dataDir, "Property_Owner__c.json");
|
|
43
|
-
|
|
44
|
-
owner.
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
95
|
+
if (fs.existsSync(ownerPath)) {
|
|
96
|
+
let owner = JSON.parse(fs.readFileSync(ownerPath, "utf8"));
|
|
97
|
+
if (owner.records) {
|
|
98
|
+
owner.records.forEach((r) => {
|
|
99
|
+
if (r.Email__c && r.Email__c.includes("@"))
|
|
100
|
+
r.Email__c = r.Email__c.replace(/\+[0-9]+@/, "@").replace("@", "+" + runId + "@");
|
|
101
|
+
});
|
|
102
|
+
fs.writeFileSync(ownerPath, JSON.stringify(owner, null, 2));
|
|
103
|
+
console.log("Updated Property_Owner__c.json (Email__c)");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
49
106
|
|
|
50
|
-
// Remap @TenantRefN in dependent files to only use refs that exist in Tenant__c.json
|
|
107
|
+
// Remap @TenantRefN in dependent files to only use refs that exist in Tenant__c.json.
|
|
108
|
+
// The valid ref count is derived from the data (no magic number), so refs stay in
|
|
109
|
+
// range and resolve even if Tenant__c.json's record count changes.
|
|
51
110
|
const tenantPath = path.join(dataDir, "Tenant__c.json");
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
111
|
+
if (fs.existsSync(tenantPath)) {
|
|
112
|
+
const tenantData = JSON.parse(fs.readFileSync(tenantPath, "utf8"));
|
|
113
|
+
const validTenantRefs = (tenantData.records || [])
|
|
114
|
+
.map((r) => r.attributes?.referenceId)
|
|
115
|
+
.filter(Boolean);
|
|
116
|
+
if (validTenantRefs.length === 0) throw new Error("Tenant__c.json has no referenceIds");
|
|
55
117
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
118
|
+
const remapTenantRef = (refValue) => {
|
|
119
|
+
if (typeof refValue !== "string" || !refValue.startsWith("@TenantRef")) return refValue;
|
|
120
|
+
const match = refValue.match(/^@(TenantRef)(\d+)$/);
|
|
121
|
+
if (!match) return refValue;
|
|
122
|
+
const n = parseInt(match[2], 10);
|
|
123
|
+
const idx = (n - 1) % validTenantRefs.length;
|
|
124
|
+
return "@" + validTenantRefs[idx];
|
|
125
|
+
};
|
|
64
126
|
|
|
65
|
-
const leasePath = path.join(dataDir, "Lease__c.json");
|
|
66
|
-
|
|
67
|
-
lease.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
127
|
+
const leasePath = path.join(dataDir, "Lease__c.json");
|
|
128
|
+
if (fs.existsSync(leasePath)) {
|
|
129
|
+
let lease = JSON.parse(fs.readFileSync(leasePath, "utf8"));
|
|
130
|
+
if (lease.records) {
|
|
131
|
+
lease.records.forEach((r) => {
|
|
132
|
+
if (r.Tenant__c) r.Tenant__c = remapTenantRef(r.Tenant__c);
|
|
133
|
+
});
|
|
134
|
+
fs.writeFileSync(leasePath, JSON.stringify(lease, null, 2));
|
|
135
|
+
console.log(
|
|
136
|
+
"Updated Lease__c.json (Tenant__c @TenantRef remap, validTenants=%s)",
|
|
137
|
+
validTenantRefs.length,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
71
141
|
|
|
72
|
-
const maintPath = path.join(dataDir, "Maintenance_Request__c.json");
|
|
73
|
-
|
|
74
|
-
maint.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
142
|
+
const maintPath = path.join(dataDir, "Maintenance_Request__c.json");
|
|
143
|
+
if (fs.existsSync(maintPath)) {
|
|
144
|
+
let maint = JSON.parse(fs.readFileSync(maintPath, "utf8"));
|
|
145
|
+
if (maint.records) {
|
|
146
|
+
maint.records.forEach((r) => {
|
|
147
|
+
if (r.User__c && String(r.User__c).startsWith("@TenantRef"))
|
|
148
|
+
r.User__c = remapTenantRef(r.User__c);
|
|
149
|
+
});
|
|
150
|
+
fs.writeFileSync(maintPath, JSON.stringify(maint, null, 2));
|
|
151
|
+
console.log("Updated Maintenance_Request__c.json (User__c @TenantRef remap)");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
79
155
|
|
|
80
|
-
console.log(
|
|
81
|
-
"Unique fields updated: runId=%s companySuffix=%s validTenants=%s",
|
|
82
|
-
runId,
|
|
83
|
-
runSuffix2,
|
|
84
|
-
validTenantRefs.length,
|
|
85
|
-
);
|
|
156
|
+
console.log("Unique fields updated: runId=%s companySuffix=%s", runId, runSuffix2);
|