ofsc-utility 1.0.36 → 1.0.38
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/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/inventory/index.js +4 -2
- package/dist/users/index.d.ts +2 -0
- package/dist/users/index.js +96 -1
- package/dist/utilities/index.d.ts +5 -0
- package/dist/utilities/index.js +13 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { generateAllOnHandInventoryOfAllResources, generateAllOnHandInventoryOfA
|
|
|
14
14
|
export { getOAuthToken } from './oauthTokenService';
|
|
15
15
|
export { downloadWorkZoneCSV } from './workZones';
|
|
16
16
|
export { AllResources, downloadAllResourcesCSV, getworkSkillsOfResource } from './resources';
|
|
17
|
-
export { downloadAllUsersCSV, generateUsersCollaborationCSV } from './users';
|
|
17
|
+
export { downloadAllInactiveUsersCSV, downloadAllUsersCSV, generateUsersCollaborationCSV } from './users';
|
|
18
18
|
export { downloadAllInventoryTypesCSV, getInventoryTypesDetail, updateCreateInventoryType } from './inventoryTypes';
|
|
19
19
|
export { getActivitybyId, getAllActivities } from './activities';
|
|
20
20
|
export { createActivityCustomerInventories, getActivityCustomerInventories } from './activityInventories';
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.createConfigurationFile = exports.createExcelFile = exports.downloadAllEventsOfLastOneHour = exports.downloadAllEventsOfDLastTwoMinutes = exports.downloadAllEventsOfDayCSV = exports.downloadAllEventsOfDay = exports.getActivityCustomerInventories = exports.createActivityCustomerInventories = exports.getAllActivities = exports.getActivitybyId = exports.updateCreateInventoryType = exports.getInventoryTypesDetail = exports.downloadAllInventoryTypesCSV = exports.generateUsersCollaborationCSV = exports.downloadAllUsersCSV = exports.getworkSkillsOfResource = exports.downloadAllResourcesCSV = exports.AllResources = exports.downloadWorkZoneCSV = exports.getOAuthToken = exports.generateAllOnHandInventoryOfAllResourcesCSV = exports.generateAllOnHandInventoryOfAllResources = exports.WorkZone = exports.Utilities = exports.User = exports.Resource = exports.OauthTokenService = exports.CreateConfigurationFile = exports.InventoryType = exports.Inventory = exports.Events = exports.ActivityInventories = exports.Activity = void 0;
|
|
39
|
+
exports.createConfigurationFile = exports.createExcelFile = exports.downloadAllEventsOfLastOneHour = exports.downloadAllEventsOfDLastTwoMinutes = exports.downloadAllEventsOfDayCSV = exports.downloadAllEventsOfDay = exports.getActivityCustomerInventories = exports.createActivityCustomerInventories = exports.getAllActivities = exports.getActivitybyId = exports.updateCreateInventoryType = exports.getInventoryTypesDetail = exports.downloadAllInventoryTypesCSV = exports.generateUsersCollaborationCSV = exports.downloadAllUsersCSV = exports.downloadAllInactiveUsersCSV = exports.getworkSkillsOfResource = exports.downloadAllResourcesCSV = exports.AllResources = exports.downloadWorkZoneCSV = exports.getOAuthToken = exports.generateAllOnHandInventoryOfAllResourcesCSV = exports.generateAllOnHandInventoryOfAllResources = exports.WorkZone = exports.Utilities = exports.User = exports.Resource = exports.OauthTokenService = exports.CreateConfigurationFile = exports.InventoryType = exports.Inventory = exports.Events = exports.ActivityInventories = exports.Activity = void 0;
|
|
40
40
|
// Export all methods grouped by category
|
|
41
41
|
exports.Activity = __importStar(require("./activities"));
|
|
42
42
|
exports.ActivityInventories = __importStar(require("./activityInventories"));
|
|
@@ -63,6 +63,7 @@ Object.defineProperty(exports, "AllResources", { enumerable: true, get: function
|
|
|
63
63
|
Object.defineProperty(exports, "downloadAllResourcesCSV", { enumerable: true, get: function () { return resources_1.downloadAllResourcesCSV; } });
|
|
64
64
|
Object.defineProperty(exports, "getworkSkillsOfResource", { enumerable: true, get: function () { return resources_1.getworkSkillsOfResource; } });
|
|
65
65
|
var users_1 = require("./users");
|
|
66
|
+
Object.defineProperty(exports, "downloadAllInactiveUsersCSV", { enumerable: true, get: function () { return users_1.downloadAllInactiveUsersCSV; } });
|
|
66
67
|
Object.defineProperty(exports, "downloadAllUsersCSV", { enumerable: true, get: function () { return users_1.downloadAllUsersCSV; } });
|
|
67
68
|
Object.defineProperty(exports, "generateUsersCollaborationCSV", { enumerable: true, get: function () { return users_1.generateUsersCollaborationCSV; } });
|
|
68
69
|
var inventoryTypes_1 = require("./inventoryTypes");
|
package/dist/inventory/index.js
CHANGED
|
@@ -106,13 +106,15 @@ async function generateAllOnHandInventoryOfAllResources(clientId, clientSecret,
|
|
|
106
106
|
console.log("--------------------------------------------------");
|
|
107
107
|
// 2. Fetch on hand inventories for each resource
|
|
108
108
|
const resourcesToProcess = limit
|
|
109
|
-
? allResources.slice(
|
|
109
|
+
? allResources.slice(-limit)
|
|
110
110
|
: allResources;
|
|
111
111
|
const rows = [];
|
|
112
112
|
for (const [index, resource] of resourcesToProcess.entries()) {
|
|
113
113
|
console.log(`${index} 👤 Fetching Inventories for ${resource.resourceId}`);
|
|
114
|
-
if (!resource)
|
|
114
|
+
if (!resource || !resource.resourceId || ["", null, undefined, "undefined"].includes(resource.resourceId)) {
|
|
115
|
+
console.log(`resourceId is misisng for ${JSON.stringify(resource, undefined, 2)}`);
|
|
115
116
|
continue;
|
|
117
|
+
}
|
|
116
118
|
if (resource.status !== "active") {
|
|
117
119
|
console.log(` ⚠ Skipping inactive resource ${resource.resourceId}`);
|
|
118
120
|
continue;
|
package/dist/users/index.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ export { generateUsersCollaborationCSV } from './collaborationGroups';
|
|
|
3
3
|
declare const OfscUserUtility: {
|
|
4
4
|
generateUsersCollaborationCSV: any;
|
|
5
5
|
downloadAllUsersCSV: typeof downloadAllUsersCSV;
|
|
6
|
+
downloadAllInactiveUsersCSV: typeof downloadAllInactiveUsersCSV;
|
|
6
7
|
};
|
|
8
|
+
export declare function downloadAllInactiveUsersCSV(clientId: string, clientSecret: string, instanceUrl: string, inactivityThresholdDays?: number): Promise<void>;
|
|
7
9
|
export default OfscUserUtility;
|
package/dist/users/index.js
CHANGED
|
@@ -38,9 +38,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.generateUsersCollaborationCSV = void 0;
|
|
40
40
|
exports.downloadAllUsersCSV = downloadAllUsersCSV;
|
|
41
|
+
exports.downloadAllInactiveUsersCSV = downloadAllInactiveUsersCSV;
|
|
41
42
|
const fs = __importStar(require("fs"));
|
|
42
43
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
43
44
|
const index_1 = require("../oauthTokenService/index");
|
|
45
|
+
const index_2 = require("../utilities/index");
|
|
44
46
|
async function downloadAllUsersCSV(clientId, clientSecret, instanceUrl) {
|
|
45
47
|
let offset = 0;
|
|
46
48
|
const limit = 100;
|
|
@@ -118,6 +120,99 @@ var collaborationGroups_1 = require("./collaborationGroups");
|
|
|
118
120
|
Object.defineProperty(exports, "generateUsersCollaborationCSV", { enumerable: true, get: function () { return collaborationGroups_1.generateUsersCollaborationCSV; } });
|
|
119
121
|
const OfscUserUtility = {
|
|
120
122
|
generateUsersCollaborationCSV: require('./collaborationGroups').generateUsersCollaborationCSV,
|
|
121
|
-
downloadAllUsersCSV
|
|
123
|
+
downloadAllUsersCSV,
|
|
124
|
+
downloadAllInactiveUsersCSV
|
|
122
125
|
};
|
|
126
|
+
/**
|
|
127
|
+
* Returns true if the user is "inactive":
|
|
128
|
+
* - has no lastLoginTime at all, OR
|
|
129
|
+
* - lastLoginTime is older than thresholdDays
|
|
130
|
+
*/
|
|
131
|
+
function isInactiveUser(item, thresholdDays, now = new Date()) {
|
|
132
|
+
const lastLogin = (0, index_2.parseOFSCDate)(item.lastLoginTime);
|
|
133
|
+
if (!lastLogin)
|
|
134
|
+
return true; // never logged in => treat as inactive
|
|
135
|
+
const diffMs = now.getTime() - lastLogin.getTime();
|
|
136
|
+
const diffDays = diffMs / (1000 * 60 * 60 * 24);
|
|
137
|
+
return diffDays > thresholdDays;
|
|
138
|
+
}
|
|
139
|
+
async function downloadAllInactiveUsersCSV(clientId, clientSecret, instanceUrl, inactivityThresholdDays = 14) {
|
|
140
|
+
let offset = 0;
|
|
141
|
+
const limit = 100;
|
|
142
|
+
let allItems = [];
|
|
143
|
+
let totalFetched = 0;
|
|
144
|
+
console.log("🚀 Starting users download...");
|
|
145
|
+
console.log("-------------------------------------");
|
|
146
|
+
while (true) {
|
|
147
|
+
const url = `https://${instanceUrl}.fs.ocs.oraclecloud.com/rest/ofscCore/v1/users/?offset=${offset}&limit=${limit}`;
|
|
148
|
+
const token = await (0, index_1.getOAuthToken)(clientId, clientSecret, instanceUrl);
|
|
149
|
+
console.log(`➡️ Fetching offset=${offset} limit=${limit}`);
|
|
150
|
+
const res = await (0, node_fetch_1.default)(url, {
|
|
151
|
+
method: "GET",
|
|
152
|
+
headers: {
|
|
153
|
+
Authorization: `Bearer ${token}`,
|
|
154
|
+
Accept: "application/json"
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
if (!res.ok) {
|
|
158
|
+
throw new Error(`❌ Fetch failed: ${res.status} ${res.statusText}`);
|
|
159
|
+
}
|
|
160
|
+
const data = (await res.json());
|
|
161
|
+
allItems.push(...data.items);
|
|
162
|
+
totalFetched += data.items.length;
|
|
163
|
+
console.log(` ✔ Received ${data.items.length} items (Total: ${totalFetched})`);
|
|
164
|
+
if (offset + limit >= data.totalResults)
|
|
165
|
+
break;
|
|
166
|
+
offset += limit;
|
|
167
|
+
}
|
|
168
|
+
console.log("-------------------------------------");
|
|
169
|
+
console.log(`🔎 Filtering inactive users (no login in last ${inactivityThresholdDays} days)...`);
|
|
170
|
+
const now = new Date();
|
|
171
|
+
const inactiveItems = allItems.filter(item => isInactiveUser(item, inactivityThresholdDays, now));
|
|
172
|
+
console.log(` ✔ ${inactiveItems.length} of ${allItems.length} users are inactive`);
|
|
173
|
+
console.log("-------------------------------------");
|
|
174
|
+
console.log("🧩 Collecting all unique properties...");
|
|
175
|
+
// Collect union of all properties (from inactive users only)
|
|
176
|
+
const allProperties = new Set();
|
|
177
|
+
for (const item of inactiveItems) {
|
|
178
|
+
for (const key of Object.keys(item)) {
|
|
179
|
+
if (!["resources", "collaborationGroups", "resourceInternalIds", "links"].includes(key)) {
|
|
180
|
+
allProperties.add(key);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const headers = Array.from(allProperties);
|
|
185
|
+
console.log(`📝 Total unique fields: ${headers.length}`);
|
|
186
|
+
// Build CSV rows
|
|
187
|
+
const csvRows = [];
|
|
188
|
+
csvRows.push(headers.join(","));
|
|
189
|
+
for (const item of inactiveItems) {
|
|
190
|
+
const row = headers.map(field => {
|
|
191
|
+
let value = item[field];
|
|
192
|
+
if (field === "keys") {
|
|
193
|
+
if (Array.isArray(value))
|
|
194
|
+
return `"${value.join("|")}"`;
|
|
195
|
+
if (value)
|
|
196
|
+
return `"${String(value)}"`;
|
|
197
|
+
return "";
|
|
198
|
+
}
|
|
199
|
+
// Objects → JSON-safe string
|
|
200
|
+
if (typeof value === "object" && value !== null) {
|
|
201
|
+
return `"${JSON.stringify(value).replace(/"/g, "'")}"`;
|
|
202
|
+
}
|
|
203
|
+
return value !== undefined ? `"${String(value).replace(/"/g, "'")}"` : "";
|
|
204
|
+
});
|
|
205
|
+
csvRows.push(row.join(","));
|
|
206
|
+
}
|
|
207
|
+
const filePath = "./inactive_users.csv";
|
|
208
|
+
fs.writeFileSync(filePath, csvRows.join("\n"));
|
|
209
|
+
console.log("-------------------------------------");
|
|
210
|
+
console.log("✅ Inactive Users CSV Created Successfully!");
|
|
211
|
+
console.log(`📁 File: ${filePath}`);
|
|
212
|
+
console.log(`📦 Total Fetched: ${totalFetched}`);
|
|
213
|
+
console.log(`🚫 Inactive Records (>${inactivityThresholdDays} days): ${inactiveItems.length}`);
|
|
214
|
+
console.log(`🧩 Total Columns (Dynamic): ${headers.length}`);
|
|
215
|
+
console.log(`🧩 Date Time: ${new Date()}`);
|
|
216
|
+
console.log("-------------------------------------");
|
|
217
|
+
}
|
|
123
218
|
exports.default = OfscUserUtility;
|
|
@@ -30,4 +30,9 @@ interface ValidationResult {
|
|
|
30
30
|
export declare function validateDateTimeStrict(dateTimeStr: string): ValidationResult;
|
|
31
31
|
export declare function getTimeBefore180SecondsAlt(): string;
|
|
32
32
|
export declare function getTimeBefore3600SecondsAlt(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Parses OFSC-style "YYYY-MM-DD HH:mm:ss" into a Date object.
|
|
35
|
+
* Falls back to null if the value is missing/unparseable.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseOFSCDate(value: unknown): Date | null;
|
|
33
38
|
export {};
|
package/dist/utilities/index.js
CHANGED
|
@@ -43,6 +43,7 @@ exports.createExcelFile = createExcelFile;
|
|
|
43
43
|
exports.validateDateTimeStrict = validateDateTimeStrict;
|
|
44
44
|
exports.getTimeBefore180SecondsAlt = getTimeBefore180SecondsAlt;
|
|
45
45
|
exports.getTimeBefore3600SecondsAlt = getTimeBefore3600SecondsAlt;
|
|
46
|
+
exports.parseOFSCDate = parseOFSCDate;
|
|
46
47
|
const XLSX = __importStar(require("xlsx-js-style"));
|
|
47
48
|
const xmldom_1 = require("xmldom");
|
|
48
49
|
const oauthTokenService_1 = require("../oauthTokenService");
|
|
@@ -318,3 +319,15 @@ function getTimeBefore3600SecondsAlt() {
|
|
|
318
319
|
.replace('T', ' ')
|
|
319
320
|
.substring(0, 19);
|
|
320
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Parses OFSC-style "YYYY-MM-DD HH:mm:ss" into a Date object.
|
|
324
|
+
* Falls back to null if the value is missing/unparseable.
|
|
325
|
+
*/
|
|
326
|
+
function parseOFSCDate(value) {
|
|
327
|
+
if (!value || typeof value !== "string")
|
|
328
|
+
return null;
|
|
329
|
+
// Convert "2026-08-07 12:31:18" -> "2026-08-07T12:31:18"
|
|
330
|
+
const isoLike = value.trim().replace(" ", "T");
|
|
331
|
+
const d = new Date(isoLike);
|
|
332
|
+
return isNaN(d.getTime()) ? null : d;
|
|
333
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofsc-utility",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.38",
|
|
4
4
|
"description": "TypeScript helpers for Oracle Field Service Cloud (OFSC): events, resources, inventories, metadata and CSV/Excel utilities.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|