retold-facto 0.0.4
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/.claude/launch.json +11 -0
- package/.dockerignore +8 -0
- package/.quackage.json +19 -0
- package/Dockerfile +26 -0
- package/bin/retold-facto.js +909 -0
- package/examples/facto-government-data.sqlite +0 -0
- package/examples/government-data-catalog.json +137 -0
- package/examples/government-data-loader.js +1432 -0
- package/package.json +91 -0
- package/scripts/facto-download.js +425 -0
- package/source/Retold-Facto.js +1042 -0
- package/source/services/Retold-Facto-BeaconProvider.js +511 -0
- package/source/services/Retold-Facto-CatalogManager.js +1252 -0
- package/source/services/Retold-Facto-DataLakeService.js +1642 -0
- package/source/services/Retold-Facto-DatasetManager.js +417 -0
- package/source/services/Retold-Facto-IngestEngine.js +1315 -0
- package/source/services/Retold-Facto-ProjectionEngine.js +3960 -0
- package/source/services/Retold-Facto-RecordManager.js +360 -0
- package/source/services/Retold-Facto-SchemaManager.js +1110 -0
- package/source/services/Retold-Facto-SourceFolderScanner.js +2243 -0
- package/source/services/Retold-Facto-SourceManager.js +730 -0
- package/source/services/Retold-Facto-StoreConnectionManager.js +441 -0
- package/source/services/Retold-Facto-ThroughputMonitor.js +478 -0
- package/source/services/web-app/codemirror-entry.js +7 -0
- package/source/services/web-app/pict-app/Pict-Application-Facto-Configuration.json +9 -0
- package/source/services/web-app/pict-app/Pict-Application-Facto.js +70 -0
- package/source/services/web-app/pict-app/Pict-Facto-Bundle.js +11 -0
- package/source/services/web-app/pict-app/providers/Pict-Provider-Facto-UI.js +66 -0
- package/source/services/web-app/pict-app/providers/Pict-Provider-Facto.js +69 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Catalog.js +93 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Connections.js +42 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Datasets.js +605 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Projections.js +188 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Scanner.js +80 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Schema.js +116 -0
- package/source/services/web-app/pict-app/providers/facto-api/Facto-API-Sources.js +104 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Catalog.js +526 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Datasets.js +173 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Ingest.js +259 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Layout.js +191 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Projections.js +231 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Records.js +326 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Scanner.js +624 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Sources.js +201 -0
- package/source/services/web-app/pict-app/views/PictView-Facto-Throughput.js +456 -0
- package/source/services/web-app/pict-app-full/Pict-Application-Facto-Full-Configuration.json +14 -0
- package/source/services/web-app/pict-app-full/Pict-Application-Facto-Full.js +391 -0
- package/source/services/web-app/pict-app-full/providers/PictRouter-Facto-Configuration.json +56 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-BottomBar.js +68 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Connections.js +340 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Dashboard.js +149 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Dashboards.js +819 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Datasets.js +178 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-IngestJobs.js +99 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Layout.js +62 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-MappingEditor.js +158 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-ProjectionDetail.js +1120 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Projections.js +172 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-QueryPanel.js +119 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-RecordViewer.js +663 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Records.js +648 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Scanner.js +1017 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaDetail.js +1404 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaDocEditor.js +1036 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaEditor.js +636 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SchemaResearch.js +357 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceDetail.js +822 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceEditor.js +1036 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-SourceResearch.js +487 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Sources.js +165 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-Throughput.js +439 -0
- package/source/services/web-app/pict-app-full/views/PictView-Facto-Full-TopBar.js +335 -0
- package/source/services/web-app/pict-app-full/views/projections/Facto-Projections-Constants.js +71 -0
- package/source/services/web-app/web/chart.min.js +20 -0
- package/source/services/web-app/web/codemirror-bundle.js +30099 -0
- package/source/services/web-app/web/css/facto-themes.css +467 -0
- package/source/services/web-app/web/css/facto.css +502 -0
- package/source/services/web-app/web/index.html +28 -0
- package/source/services/web-app/web/retold-facto.js +12138 -0
- package/source/services/web-app/web/retold-facto.js.map +1 -0
- package/source/services/web-app/web/retold-facto.min.js +2 -0
- package/source/services/web-app/web/retold-facto.min.js.map +1 -0
- package/source/services/web-app/web/simple/index.html +17 -0
- package/test/Facto_Browser_Integration_tests.js +798 -0
- package/test/RetoldFacto_tests.js +4117 -0
- package/test/fixtures/weather-readings.csv +17 -0
- package/test/fixtures/weather-stations.csv +9 -0
- package/test/model/MeadowModel-Extended.json +8497 -0
- package/test/model/MeadowModel-PICT.json +1 -0
- package/test/model/MeadowModel.json +1355 -0
- package/test/model/ddl/Facto.ddl +225 -0
- package/test/model/fable-configuration.json +14 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retold Facto - Record Manager Service
|
|
3
|
+
*
|
|
4
|
+
* Manages record ingest, versioning, and certainty index operations.
|
|
5
|
+
* Provides endpoints for batch ingest, version history, and certainty
|
|
6
|
+
* tracking beyond the auto-generated Meadow CRUD endpoints.
|
|
7
|
+
*
|
|
8
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
9
|
+
*/
|
|
10
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
11
|
+
|
|
12
|
+
const defaultRecordManagerOptions = (
|
|
13
|
+
{
|
|
14
|
+
RoutePrefix: '/facto',
|
|
15
|
+
DefaultCertaintyValue: 0.5
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
class RetoldFactoRecordManager extends libFableServiceProviderBase
|
|
19
|
+
{
|
|
20
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
21
|
+
{
|
|
22
|
+
let tmpOptions = Object.assign({}, defaultRecordManagerOptions, pOptions);
|
|
23
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
24
|
+
|
|
25
|
+
this.serviceType = 'RetoldFactoRecordManager';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Ingest a single record: create it via the DAL, then auto-create a
|
|
30
|
+
* CertaintyIndex entry at the default certainty value.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} pRecordData - The record fields to create
|
|
33
|
+
* @param {function} fCallback - (pError, pCreatedRecord)
|
|
34
|
+
*/
|
|
35
|
+
ingestSingleRecord(pRecordData, fCallback)
|
|
36
|
+
{
|
|
37
|
+
if (!this.fable.DAL || !this.fable.DAL.Record)
|
|
38
|
+
{
|
|
39
|
+
return fCallback(new Error('Record DAL not initialized'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Set IngestDate to now if not provided
|
|
43
|
+
if (!pRecordData.IngestDate)
|
|
44
|
+
{
|
|
45
|
+
pRecordData.IngestDate = new Date().toISOString();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Default Version to 1 if not provided
|
|
49
|
+
if (!pRecordData.Version)
|
|
50
|
+
{
|
|
51
|
+
pRecordData.Version = 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let tmpCreateQuery = this.fable.DAL.Record.query.clone()
|
|
55
|
+
.addRecord(pRecordData);
|
|
56
|
+
|
|
57
|
+
this.fable.DAL.Record.doCreate(tmpCreateQuery,
|
|
58
|
+
(pError, pQuery, pQueryRead, pRecord) =>
|
|
59
|
+
{
|
|
60
|
+
if (pError)
|
|
61
|
+
{
|
|
62
|
+
return fCallback(pError);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!pRecord || !pRecord.IDRecord)
|
|
66
|
+
{
|
|
67
|
+
return fCallback(new Error('Record creation returned no record'));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Auto-create a CertaintyIndex entry
|
|
71
|
+
if (!this.fable.DAL.CertaintyIndex)
|
|
72
|
+
{
|
|
73
|
+
// No CertaintyIndex DAL; return the record without certainty
|
|
74
|
+
return fCallback(null, pRecord);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let tmpCertaintyQuery = this.fable.DAL.CertaintyIndex.query.clone()
|
|
78
|
+
.addRecord(
|
|
79
|
+
{
|
|
80
|
+
IDRecord: pRecord.IDRecord,
|
|
81
|
+
CertaintyValue: this.options.DefaultCertaintyValue,
|
|
82
|
+
Dimension: 'overall',
|
|
83
|
+
Justification: 'Default certainty assigned at ingest'
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
this.fable.DAL.CertaintyIndex.doCreate(tmpCertaintyQuery,
|
|
87
|
+
(pCertaintyError, pCertaintyQuery, pCertaintyQueryRead, pCertaintyRecord) =>
|
|
88
|
+
{
|
|
89
|
+
if (pCertaintyError)
|
|
90
|
+
{
|
|
91
|
+
this.fable.log.warn(`RecordManager warning: Record ${pRecord.IDRecord} created but CertaintyIndex creation failed: ${pCertaintyError}`);
|
|
92
|
+
}
|
|
93
|
+
return fCallback(null, pRecord);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Connect REST API routes for record management.
|
|
100
|
+
*
|
|
101
|
+
* @param {object} pOratorServiceServer - The Orator service server instance
|
|
102
|
+
*/
|
|
103
|
+
connectRoutes(pOratorServiceServer)
|
|
104
|
+
{
|
|
105
|
+
let tmpRoutePrefix = this.options.RoutePrefix;
|
|
106
|
+
|
|
107
|
+
// POST /facto/record/ingest -- ingest a batch of records
|
|
108
|
+
pOratorServiceServer.doPost(`${tmpRoutePrefix}/record/ingest`,
|
|
109
|
+
(pRequest, pResponse, fNext) =>
|
|
110
|
+
{
|
|
111
|
+
let tmpBody = pRequest.body || {};
|
|
112
|
+
let tmpRecords = tmpBody.Records || tmpBody.records || [];
|
|
113
|
+
let tmpIDDataset = tmpBody.IDDataset || 0;
|
|
114
|
+
let tmpIDSource = tmpBody.IDSource || 0;
|
|
115
|
+
|
|
116
|
+
if (!Array.isArray(tmpRecords) || tmpRecords.length === 0)
|
|
117
|
+
{
|
|
118
|
+
pResponse.send(
|
|
119
|
+
{
|
|
120
|
+
Error: 'No records provided. Send { Records: [...], IDDataset: N, IDSource: N }',
|
|
121
|
+
Ingested: 0,
|
|
122
|
+
DefaultCertainty: this.options.DefaultCertaintyValue
|
|
123
|
+
});
|
|
124
|
+
return fNext();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let tmpIngested = 0;
|
|
128
|
+
let tmpErrors = 0;
|
|
129
|
+
let tmpCreatedRecords = [];
|
|
130
|
+
|
|
131
|
+
let tmpAnticipate = this.fable.newAnticipate();
|
|
132
|
+
|
|
133
|
+
for (let i = 0; i < tmpRecords.length; i++)
|
|
134
|
+
{
|
|
135
|
+
let tmpRecordData = tmpRecords[i];
|
|
136
|
+
tmpAnticipate.anticipate(
|
|
137
|
+
(fStep) =>
|
|
138
|
+
{
|
|
139
|
+
// Apply batch-level defaults
|
|
140
|
+
if (tmpIDDataset && !tmpRecordData.IDDataset)
|
|
141
|
+
{
|
|
142
|
+
tmpRecordData.IDDataset = tmpIDDataset;
|
|
143
|
+
}
|
|
144
|
+
if (tmpIDSource && !tmpRecordData.IDSource)
|
|
145
|
+
{
|
|
146
|
+
tmpRecordData.IDSource = tmpIDSource;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.ingestSingleRecord(tmpRecordData,
|
|
150
|
+
(pError, pRecord) =>
|
|
151
|
+
{
|
|
152
|
+
if (pError)
|
|
153
|
+
{
|
|
154
|
+
tmpErrors++;
|
|
155
|
+
this.fable.log.error(`RecordManager ingest error: ${pError}`);
|
|
156
|
+
}
|
|
157
|
+
else
|
|
158
|
+
{
|
|
159
|
+
tmpIngested++;
|
|
160
|
+
tmpCreatedRecords.push(pRecord);
|
|
161
|
+
}
|
|
162
|
+
return fStep();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
tmpAnticipate.wait(
|
|
168
|
+
(pError) =>
|
|
169
|
+
{
|
|
170
|
+
pResponse.send(
|
|
171
|
+
{
|
|
172
|
+
Ingested: tmpIngested,
|
|
173
|
+
Errors: tmpErrors,
|
|
174
|
+
Total: tmpRecords.length,
|
|
175
|
+
DefaultCertainty: this.options.DefaultCertaintyValue,
|
|
176
|
+
Records: tmpCreatedRecords
|
|
177
|
+
});
|
|
178
|
+
return fNext();
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// GET /facto/record/:IDRecord/certainty -- get all certainty indices for a record
|
|
183
|
+
pOratorServiceServer.doGet(`${tmpRoutePrefix}/record/:IDRecord/certainty`,
|
|
184
|
+
(pRequest, pResponse, fNext) =>
|
|
185
|
+
{
|
|
186
|
+
let tmpIDRecord = parseInt(pRequest.params.IDRecord, 10);
|
|
187
|
+
if (isNaN(tmpIDRecord) || tmpIDRecord < 1)
|
|
188
|
+
{
|
|
189
|
+
pResponse.send({ Error: 'Invalid IDRecord parameter', CertaintyIndices: [] });
|
|
190
|
+
return fNext();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!this.fable.DAL || !this.fable.DAL.CertaintyIndex)
|
|
194
|
+
{
|
|
195
|
+
pResponse.send({ Error: 'CertaintyIndex DAL not initialized', CertaintyIndices: [] });
|
|
196
|
+
return fNext();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let tmpQuery = this.fable.DAL.CertaintyIndex.query.clone()
|
|
200
|
+
.addFilter('IDRecord', tmpIDRecord)
|
|
201
|
+
.addFilter('Deleted', 0);
|
|
202
|
+
|
|
203
|
+
this.fable.DAL.CertaintyIndex.doReads(tmpQuery,
|
|
204
|
+
(pError, pQuery, pRecords) =>
|
|
205
|
+
{
|
|
206
|
+
if (pError)
|
|
207
|
+
{
|
|
208
|
+
this.fable.log.error(`RecordManager error reading certainty for record ${tmpIDRecord}: ${pError}`);
|
|
209
|
+
pResponse.send({ Error: pError.message || pError, CertaintyIndices: [] });
|
|
210
|
+
return fNext();
|
|
211
|
+
}
|
|
212
|
+
pResponse.send({ IDRecord: tmpIDRecord, Count: pRecords.length, CertaintyIndices: pRecords });
|
|
213
|
+
return fNext();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// POST /facto/record/:IDRecord/certainty -- add a new certainty index entry
|
|
218
|
+
pOratorServiceServer.doPost(`${tmpRoutePrefix}/record/:IDRecord/certainty`,
|
|
219
|
+
(pRequest, pResponse, fNext) =>
|
|
220
|
+
{
|
|
221
|
+
let tmpIDRecord = parseInt(pRequest.params.IDRecord, 10);
|
|
222
|
+
if (isNaN(tmpIDRecord) || tmpIDRecord < 1)
|
|
223
|
+
{
|
|
224
|
+
pResponse.send({ Error: 'Invalid IDRecord parameter' });
|
|
225
|
+
return fNext();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (!this.fable.DAL || !this.fable.DAL.CertaintyIndex)
|
|
229
|
+
{
|
|
230
|
+
pResponse.send({ Error: 'CertaintyIndex DAL not initialized' });
|
|
231
|
+
return fNext();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let tmpBody = pRequest.body || {};
|
|
235
|
+
let tmpCertaintyValue = parseFloat(tmpBody.CertaintyValue);
|
|
236
|
+
if (isNaN(tmpCertaintyValue) || tmpCertaintyValue < 0 || tmpCertaintyValue > 1)
|
|
237
|
+
{
|
|
238
|
+
tmpCertaintyValue = this.options.DefaultCertaintyValue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let tmpCertaintyData = {
|
|
242
|
+
IDRecord: tmpIDRecord,
|
|
243
|
+
CertaintyValue: tmpCertaintyValue,
|
|
244
|
+
Dimension: tmpBody.Dimension || 'overall',
|
|
245
|
+
Justification: tmpBody.Justification || ''
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
let tmpQuery = this.fable.DAL.CertaintyIndex.query.clone()
|
|
249
|
+
.addRecord(tmpCertaintyData);
|
|
250
|
+
|
|
251
|
+
this.fable.DAL.CertaintyIndex.doCreate(tmpQuery,
|
|
252
|
+
(pError, pQuery, pQueryRead, pRecord) =>
|
|
253
|
+
{
|
|
254
|
+
if (pError)
|
|
255
|
+
{
|
|
256
|
+
this.fable.log.error(`RecordManager error creating certainty for record ${tmpIDRecord}: ${pError}`);
|
|
257
|
+
pResponse.send({ Error: pError.message || pError });
|
|
258
|
+
return fNext();
|
|
259
|
+
}
|
|
260
|
+
pResponse.send({ Success: true, CertaintyIndex: pRecord });
|
|
261
|
+
return fNext();
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// GET /facto/record/:IDRecord/versions -- list all versions of a record (matching GUIDRecord)
|
|
266
|
+
pOratorServiceServer.doGet(`${tmpRoutePrefix}/record/:IDRecord/versions`,
|
|
267
|
+
(pRequest, pResponse, fNext) =>
|
|
268
|
+
{
|
|
269
|
+
let tmpIDRecord = parseInt(pRequest.params.IDRecord, 10);
|
|
270
|
+
if (isNaN(tmpIDRecord) || tmpIDRecord < 1)
|
|
271
|
+
{
|
|
272
|
+
pResponse.send({ Error: 'Invalid IDRecord parameter', Versions: [] });
|
|
273
|
+
return fNext();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!this.fable.DAL || !this.fable.DAL.Record)
|
|
277
|
+
{
|
|
278
|
+
pResponse.send({ Error: 'Record DAL not initialized', Versions: [] });
|
|
279
|
+
return fNext();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// First read the record to get its GUIDRecord
|
|
283
|
+
let tmpReadQuery = this.fable.DAL.Record.query.clone()
|
|
284
|
+
.addFilter('IDRecord', tmpIDRecord);
|
|
285
|
+
|
|
286
|
+
this.fable.DAL.Record.doRead(tmpReadQuery,
|
|
287
|
+
(pError, pQuery, pRecord) =>
|
|
288
|
+
{
|
|
289
|
+
if (pError || !pRecord)
|
|
290
|
+
{
|
|
291
|
+
pResponse.send({ Error: pError ? (pError.message || pError) : 'Record not found', Versions: [] });
|
|
292
|
+
return fNext();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Find all records sharing the same GUIDRecord (version chain)
|
|
296
|
+
let tmpVersionQuery = this.fable.DAL.Record.query.clone()
|
|
297
|
+
.addFilter('GUIDRecord', pRecord.GUIDRecord)
|
|
298
|
+
.addFilter('Deleted', 0);
|
|
299
|
+
|
|
300
|
+
this.fable.DAL.Record.doReads(tmpVersionQuery,
|
|
301
|
+
(pVersionError, pVersionQuery, pVersionRecords) =>
|
|
302
|
+
{
|
|
303
|
+
if (pVersionError)
|
|
304
|
+
{
|
|
305
|
+
pResponse.send({ Error: pVersionError.message || pVersionError, Versions: [] });
|
|
306
|
+
return fNext();
|
|
307
|
+
}
|
|
308
|
+
pResponse.send(
|
|
309
|
+
{
|
|
310
|
+
IDRecord: tmpIDRecord,
|
|
311
|
+
GUIDRecord: pRecord.GUIDRecord,
|
|
312
|
+
Count: pVersionRecords.length,
|
|
313
|
+
Versions: pVersionRecords
|
|
314
|
+
});
|
|
315
|
+
return fNext();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// GET /facto/record/:IDRecord/binary -- list binary attachments for a record
|
|
321
|
+
pOratorServiceServer.doGet(`${tmpRoutePrefix}/record/:IDRecord/binary`,
|
|
322
|
+
(pRequest, pResponse, fNext) =>
|
|
323
|
+
{
|
|
324
|
+
let tmpIDRecord = parseInt(pRequest.params.IDRecord, 10);
|
|
325
|
+
if (isNaN(tmpIDRecord) || tmpIDRecord < 1)
|
|
326
|
+
{
|
|
327
|
+
pResponse.send({ Error: 'Invalid IDRecord parameter', Binaries: [] });
|
|
328
|
+
return fNext();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (!this.fable.DAL || !this.fable.DAL.RecordBinary)
|
|
332
|
+
{
|
|
333
|
+
pResponse.send({ Error: 'RecordBinary DAL not initialized', Binaries: [] });
|
|
334
|
+
return fNext();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
let tmpQuery = this.fable.DAL.RecordBinary.query.clone()
|
|
338
|
+
.addFilter('IDRecord', tmpIDRecord)
|
|
339
|
+
.addFilter('Deleted', 0);
|
|
340
|
+
|
|
341
|
+
this.fable.DAL.RecordBinary.doReads(tmpQuery,
|
|
342
|
+
(pError, pQuery, pRecords) =>
|
|
343
|
+
{
|
|
344
|
+
if (pError)
|
|
345
|
+
{
|
|
346
|
+
pResponse.send({ Error: pError.message || pError, Binaries: [] });
|
|
347
|
+
return fNext();
|
|
348
|
+
}
|
|
349
|
+
pResponse.send({ IDRecord: tmpIDRecord, Count: pRecords.length, Binaries: pRecords });
|
|
350
|
+
return fNext();
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
this.fable.log.info(`RecordManager routes connected at ${tmpRoutePrefix}/record/*`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
module.exports = RetoldFactoRecordManager;
|
|
359
|
+
module.exports.serviceType = 'RetoldFactoRecordManager';
|
|
360
|
+
module.exports.default_configuration = defaultRecordManagerOptions;
|