Skip to content

Commit 3efc794

Browse files
authored
refactor: templateBuilder (#34)
1 parent 3703b14 commit 3efc794

3 files changed

Lines changed: 139 additions & 110 deletions

File tree

src/schemas/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const commonSuccessResponse = (itemsSchema) =>
1212
export const dataCodeModel = S.object()
1313
.id('DataCodeModel')
1414
.prop('dataText', S.anyOf([S.string(), S.null()]))
15-
.prop('dataCode', S.anyOf([S.number(), S.null()]));
15+
.prop('dataCode', S.anyOf([S.string(), S.number(), S.null()]));
1616

1717
export const toggle = S.string().id('ToggleModel').enum(['1', '2']);
1818

src/utils/templateBuilder.js

Lines changed: 121 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { idValidator, mobileValidator } from './complaintsValidator.js';
22

3-
const defualt = {
3+
const defaultTemplate = {
44
contactType: {
55
selectContactType: '1',
66
isChosenType: true,
@@ -116,10 +116,23 @@ const defualt = {
116116
language: 'hebrew',
117117
},
118118
};
119-
Object.freeze(defualt);
119+
Object.freeze(defaultTemplate);
120+
121+
const formatted = new Intl.DateTimeFormat('en-US', {
122+
timeZone: 'Asia/Jerusalem',
123+
year: 'numeric',
124+
month: '2-digit',
125+
day: '2-digit',
126+
});
120127

121128
export function formatDateTime(dateTime) {
122-
return new Date(dateTime).toLocaleDateString('en-GB');
129+
const date = new Date(dateTime);
130+
if (isNaN(date.getTime())) {
131+
throw new Error(`Invalid date: ${dateTime}`);
132+
}
133+
const format = formatted.format(date);
134+
const [month, day, year] = format.split('/');
135+
return `${day}/${month}/${year}`;
123136
}
124137

125138
function fillTemplate(template, data = {}) {
@@ -150,18 +163,37 @@ function fillTemplate(template, data = {}) {
150163
return data === undefined ? template : data;
151164
}
152165

153-
/**
154-
* Build an XML element.
155-
*
156-
* @param {string} tagName - Name of the XML tag.
157-
* @param {string|undefined} value - Optional string value.
158-
* @param {Object.<string, string>} attributes - XML attributes.
159-
* @returns {string} XML string.
160-
*/
166+
function processTransportSection(fillData, bodyData, sectionName) {
167+
if (bodyData[sectionName]) {
168+
fillData.requestDetails[sectionName] = fillTemplate(defaultTemplate.requestDetails[sectionName], bodyData[sectionName]);
169+
delete fillData[sectionName];
170+
}
171+
172+
Object.keys(fillData.requestDetails[sectionName]).forEach((key) => {
173+
if (fillData.requestDetails[sectionName][key] === false) {
174+
delete fillData.requestDetails[sectionName][key];
175+
}
176+
if (typeof fillData.requestDetails[sectionName][key]?.dataCode === 'string' && fillData.requestDetails[sectionName][key]?.dataCode !== '') {
177+
fillData.requestDetails[sectionName][key].dataCode = Number(fillData.requestDetails[sectionName][key].dataCode);
178+
}
179+
});
180+
}
181+
182+
const xmlEscapes = {
183+
'<': '&lt;',
184+
'>': '&gt;',
185+
'&': '&amp;',
186+
"'": '&#39;',
187+
'"': '&quot;',
188+
};
189+
190+
function escapeXml(str) {
191+
return str.replace(/[<>&'"]/gu, (char) => xmlEscapes[char] ?? char);
192+
}
193+
161194
export function buildXmlElement(tagName, value = undefined) {
162195
const attrs = value === null || value === undefined || value === '' ? ' xsi:nil="true" ' : '';
163-
164-
const val = value === null || value === undefined ? '' : value;
196+
const val = value === null || value === undefined ? '' : String(value);
165197
return `<${tagName}${attrs}>${val}</${tagName}>`;
166198
}
167199

@@ -180,54 +212,40 @@ export function templateBuilder(body, ref) {
180212
}
181213
body.data.personalDetails.mobile = validatedMobile;
182214

183-
const fillData = fillTemplate(defualt, body.data);
215+
const fillData = fillTemplate(defaultTemplate, body.data);
184216
fillData.formInformation.loadingDate = new Date().toLocaleDateString('en-us');
185217
fillData.formInformation.referenceNumber = ref;
186218
fillData.requestDetails.title = fillData.title;
187219
delete fillData.title;
188220

189221
// Fill busAndOther if present
190-
if (body.data.busAndOther) {
191-
fillData.requestDetails.busAndOther = fillTemplate(defualt.requestDetails.busAndOther, body.data.busAndOther);
192-
fillData.requestDetails.busAndOther.addFrequencyOverCrowd = fillData.requestDetails.busAndOther.addingFrequencyReason.includes('LoadTopics');
193-
fillData.requestDetails.busAndOther.addFrequencyLongWait = fillData.requestDetails.busAndOther.addingFrequencyReason.includes('LongWaiting');
194-
fillData.requestDetails.busAndOther.addFrequencyExtendTime = fillData.requestDetails.busAndOther.addingFrequencyReason.includes('ExtensionHours');
195-
delete fillData.busAndOther;
196-
Object.keys(fillData.requestDetails.busAndOther).forEach((key) => {
197-
if (fillData.requestDetails.busAndOther[key] === false) {
198-
delete fillData.requestDetails.busAndOther[key];
199-
}
200-
if (typeof fillData.requestDetails.busAndOther[key]?.dataCode === 'string' && fillData.requestDetails.busAndOther[key]?.dataCode !== '') {
201-
fillData.requestDetails.busAndOther[key].dataCode = Number(fillData.requestDetails.busAndOther[key].dataCode);
202-
}
203-
});
204-
}
222+
processTransportSection(fillData, body.data, 'busAndOther');
223+
205224
// Fill Train if present
206-
if (body.data.train) {
207-
fillData.requestDetails.train = fillTemplate(defualt.requestDetails.train, body.data.train);
208-
delete fillData.train;
209-
}
225+
processTransportSection(fillData, body.data, 'train');
210226

211227
// Fill taxi if present
212-
if (body.data.taxi) {
213-
fillData.requestDetails.taxi = fillTemplate(defualt.requestDetails.taxi, body.data.taxi);
214-
delete fillData.taxi;
215-
}
228+
processTransportSection(fillData, body.data, 'taxi');
216229

217230
// Fill documentsList
218231
if (body.data.documentsList) {
219232
fillData.documentAttachment.documentsList = body.data.documentsList.map((doc) => ({ attacmentName: doc.attachmentName }));
220233
delete fillData.documentsList;
221234
}
222235

223-
if (fillData.requestDetails.train?.eventDat) fillData.requestDetails.train.eventDate = formatDateTime(fillData.requestDetails.train.eventDate);
224-
if (fillData.requestDetails.taxi?.eventDate) fillData.requestDetails.taxi.eventDate = formatDateTime(fillData.requestDetails.taxi.eventDate);
225-
if (fillData.requestDetails.busAndOther?.eventDate)
236+
// Format Dates
237+
if (fillData.requestDetails?.train?.eventDate) {
238+
fillData.requestDetails.train.eventDate = formatDateTime(fillData.requestDetails?.train.eventDate);
239+
}
240+
if (fillData.requestDetails?.taxi?.eventDate) {
241+
fillData.requestDetails.taxi.eventDate = formatDateTime(fillData.requestDetails?.taxi.eventDate);
242+
}
243+
if (fillData.requestDetails?.busAndOther?.eventDate) {
226244
fillData.requestDetails.busAndOther.eventDate = formatDateTime(fillData.requestDetails.busAndOther.eventDate);
227-
if (fillData.requestDetails.busAndOther.reportdate)
245+
}
246+
if (fillData.requestDetails?.busAndOther?.reportdate) {
228247
fillData.requestDetails.busAndOther.reportdate = formatDateTime(fillData.requestDetails.busAndOther.reportdate);
229-
230-
const dataModelSaver = JSON.stringify(fillData).replace(/"/gu, '&quot;');
248+
}
231249

232250
return `<?xml version='1.0' encoding='UTF-8'?>
233251
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" formId="PniotMot@mot.gov.il" formVersion="3.0.5" formCompileTime="" xmlns="http://AGForms/PniotMot@mot.gov.il" >
@@ -238,7 +256,7 @@ export function templateBuilder(body, ref) {
238256
<BTSProcessID xsi:nil="true" ></BTSProcessID>
239257
${buildXmlElement('ReferenceNumber', ref)}
240258
<StageStatus>UserToOffice</StageStatus>
241-
${buildXmlElement('dataModelSaver', dataModelSaver)}
259+
${buildXmlElement('dataModelSaver', escapeXml(JSON.stringify(fillData)))}
242260
<isMobile>false</isMobile>
243261
<DeviceType>PC</DeviceType>
244262
<FirstLoadingDate xsi:nil="true" ></FirstLoadingDate>
@@ -260,67 +278,67 @@ ${buildXmlElement('Email', fillData.personalDetails.email)}
260278
<ZipCode xsi:nil="true" ></ZipCode>
261279
${buildXmlElement('ApplySubject', fillData.requestSubject.applySubject?.dataText)}
262280
${buildXmlElement('TypeReq', fillData.requestSubject.applyType?.dataText)}
263-
${buildXmlElement('TrainType', fillData.requestDetails.train?.trainType)}
264-
${buildXmlElement('EventDate2', fillData.requestDetails.train?.eventDate)}
265-
${buildXmlElement('EventHour2', fillData.requestDetails.train?.eventHour)}
266-
${buildXmlElement('StartStation', fillData.requestDetails.train?.startStation?.dataText)}
267-
${buildXmlElement('DestStation', fillData.requestDetails.train?.destinationStation?.dataText)}
268-
${buildXmlElement('TrainNumber', fillData.requestDetails.train?.number)}
269-
${buildXmlElement('ApplyContent3', fillData.requestDetails.train?.applyContent)}
270-
${buildXmlElement('FirstDeclaration', fillData.requestDetails.busAndOther?.firstDeclaration || fillData.requestDetails.taxi?.firstDeclaration || false)}
271-
${buildXmlElement('SecondDeclaration', fillData.requestDetails.busAndOther?.secondDeclaration || fillData.requestDetails.taxi?.secondDeclaration || false)}
272-
${buildXmlElement('EventDetails', fillData.requestDetails.taxi?.eventDetails)}
273-
${buildXmlElement('Invoice', fillData.requestDetails.taxi?.invoice)}
274-
${buildXmlElement('Evidence', fillData.requestDetails.taxi?.evidence)}
275-
${buildXmlElement('OtherFactors', fillData.requestDetails.taxi?.otherFactors)}
276-
${buildXmlElement('ETaxiType', fillData.requestDetails.taxi?.taxiType)}
277-
${buildXmlElement('DrivingLicense2', fillData.requestDetails.taxi?.licenseNum)}
278-
${buildXmlElement('TaxiCap', fillData.requestDetails.taxi?.cap)}
279-
${buildXmlElement('TaxiDriverName', fillData.requestDetails.taxi?.driverName)}
280-
${buildXmlElement('TaxiEventDate', fillData.requestDetails.taxi?.eventDate)}
281-
${buildXmlElement('TaxiEventHour', fillData.requestDetails.taxi?.eventHour)}
282-
${buildXmlElement('TaxiEventLocation', fillData.requestDetails.taxi?.eventLocation)}
281+
${buildXmlElement('TrainType', fillData.requestDetails?.train?.trainType)}
282+
${buildXmlElement('EventDate2', fillData.requestDetails?.train?.eventDate)}
283+
${buildXmlElement('EventHour2', fillData.requestDetails?.train?.eventHour)}
284+
${buildXmlElement('StartStation', fillData.requestDetails?.train?.startStation?.dataText)}
285+
${buildXmlElement('DestStation', fillData.requestDetails?.train?.destinationStation?.dataText)}
286+
${buildXmlElement('TrainNumber', fillData.requestDetails?.train?.number)}
287+
${buildXmlElement('ApplyContent3', fillData.requestDetails?.train?.applyContent)}
288+
${buildXmlElement('FirstDeclaration', fillData.requestDetails?.taxi?.firstDeclaration || false)}
289+
${buildXmlElement('SecondDeclaration', fillData.requestDetails?.taxi?.secondDeclaration || false)}
290+
${buildXmlElement('EventDetails', fillData.requestDetails?.taxi?.eventDetails)}
291+
${buildXmlElement('Invoice', fillData.requestDetails?.taxi?.invoice)}
292+
${buildXmlElement('Evidence', fillData.requestDetails?.taxi?.evidence)}
293+
${buildXmlElement('OtherFactors', fillData.requestDetails?.taxi?.otherFactors)}
294+
${buildXmlElement('ETaxiType', fillData.requestDetails?.taxi?.taxiType)}
295+
${buildXmlElement('DrivingLicense2', fillData.requestDetails?.taxi?.licenseNum)}
296+
${buildXmlElement('TaxiCap', fillData.requestDetails?.taxi?.cap)}
297+
${buildXmlElement('TaxiDriverName', fillData.requestDetails?.taxi?.driverName)}
298+
${buildXmlElement('TaxiEventDate', fillData.requestDetails?.taxi?.eventDate)}
299+
${buildXmlElement('TaxiEventHour', fillData.requestDetails?.taxi?.eventHour)}
300+
${buildXmlElement('TaxiEventLocation', fillData.requestDetails?.taxi?.eventLocation)}
283301
<ApplyContent xsi:nil="true" ></ApplyContent>
284-
${buildXmlElement('FinanceRavKav', fillData.requestDetails.busAndOther?.ravKav)}
285-
${buildXmlElement('FinanceRavKavNumber', fillData.requestDetails.busAndOther?.ravKavNumber)}
302+
${buildXmlElement('FinanceRavKav', fillData.requestDetails?.busAndOther?.ravKav)}
303+
${buildXmlElement('FinanceRavKavNumber', fillData.requestDetails?.busAndOther?.ravKavNumber)}
286304
<FinanceOther>false</FinanceOther>
287-
${buildXmlElement('SingleTrip', fillData.requestDetails.busAndOther?.singleTrip || false)}
288-
${buildXmlElement('LoadTopics', fillData.requestDetails.busAndOther?.addFrequencyOverCrowd || false)}
289-
${buildXmlElement('LongWaiting', fillData.requestDetails.busAndOther?.addFrequencyLongWait || false)}
290-
${buildXmlElement('ExtensionHours', fillData.requestDetails.busAndOther?.addFrequencyExtendTime || false)}
291-
${buildXmlElement('Operator', fillData.requestDetails.busAndOther?.operator?.dataText)}
292-
${buildXmlElement('BusDriverName', fillData.requestDetails.busAndOther?.driverName)}
293-
${buildXmlElement('BusLicenseNum', fillData.requestDetails.busAndOther?.licenseNum)}
294-
${buildXmlElement('BusEventDate', fillData.requestDetails.busAndOther?.eventDate)}
295-
${buildXmlElement('BusEventHour', fillData.requestDetails.busAndOther?.eventHour)}
296-
${buildXmlElement('from', fillData.requestDetails.busAndOther?.fromHour)}
297-
${buildXmlElement('by', fillData.requestDetails.busAndOther?.toHour)}
298-
${buildXmlElement('Reportdate', fillData.requestDetails.busAndOther?.reportdate)}
299-
${buildXmlElement('ReportTime', fillData.requestDetails.busAndOther?.reportTime)}
300-
${buildXmlElement('Stationupdate', fillData.requestDetails.busAndOther?.addOrRemoveStation)}
301-
${buildXmlElement('NumStation', fillData.requestDetails.busAndOther?.addOrRemoveStation)}
302-
${buildXmlElement('LineNumberBoarding', fillData.requestDetails.busAndOther?.lineNumberText)}
303-
${buildXmlElement('Direction', fillData.requestDetails.busAndOther?.direction?.dataText)}
304-
${buildXmlElement('BusStationBoard', fillData.requestDetails.busAndOther?.raisingStation?.dataText)}
305-
${buildXmlElement('BoardingSettlement', fillData.requestDetails.busAndOther?.raisingStationCity?.dataText)}
306-
${buildXmlElement('DropStaionAppeal', fillData.requestDetails.busAndOther?.destinationStationCity?.dataText)}
307-
${buildXmlElement('Risestationaddress', fillData.requestDetails.busAndOther?.raisingStationAddress)}
308-
${buildXmlElement('MakatStation', fillData.requestDetails.busAndOther?.makatStation)}
309-
${buildXmlElement('LineNumber', fillData.requestDetails.busAndOther?.lineNumberFromList?.dataCode)}
310-
${buildXmlElement('BusDirectionFrom', fillData.requestDetails.busAndOther?.busDirectionFrom)}
311-
${buildXmlElement('BusDirectionTo', fillData.requestDetails.busAndOther?.busDirectionTo)}
312-
${buildXmlElement('Testimony', fillData.requestDetails.busAndOther?.firstDeclaration || false)}
313-
${buildXmlElement('Courttestimony', fillData.requestDetails.busAndOther?.secondDeclaration || false)}
314-
${buildXmlElement('CaseEssence', fillData.requestDetails.busAndOther?.applyContent)}
315-
${buildXmlElement('OriginCityCode', fillData.requestDetails.busAndOther?.originCityCode)}
316-
${buildXmlElement('OriginCityName', fillData.requestDetails.busAndOther?.originCityName)}
317-
${buildXmlElement('LineCode', fillData.requestDetails.busAndOther?.lineCode)}
318-
${buildXmlElement('CityId', fillData.requestDetails.busAndOther?.cityId)}
319-
${buildXmlElement('CityName', fillData.requestDetails.busAndOther?.cityName)}
320-
${buildXmlElement('StationName', fillData.requestDetails.busAndOther?.stationName)}
321-
${buildXmlElement('DirectionCode', fillData.requestDetails.busAndOther?.directionCode)}
322-
${buildXmlElement('DestinationCityCode', fillData.requestDetails.busAndOther?.destinationCityCode)}
323-
${buildXmlElement('DestinationCityText', fillData.requestDetails.busAndOther?.destinationCityText)}
305+
${buildXmlElement('SingleTrip', fillData.requestDetails?.busAndOther?.singleTrip || false)}
306+
${buildXmlElement('LoadTopics', fillData.requestDetails?.busAndOther?.addingFrequencyReason.includes('LoadTopics') || false)}
307+
${buildXmlElement('LongWaiting', fillData.requestDetails?.busAndOther?.addingFrequencyReason.includes('LongWaiting') || false)}
308+
${buildXmlElement('ExtensionHours', fillData.requestDetails?.busAndOther?.addingFrequencyReason.includes('ExtensionHours') || false)}
309+
${buildXmlElement('Operator', fillData.requestDetails?.busAndOther?.operator?.dataText)}
310+
${buildXmlElement('BusDriverName', fillData.requestDetails?.busAndOther?.driverName)}
311+
${buildXmlElement('BusLicenseNum', fillData.requestDetails?.busAndOther?.licenseNum)}
312+
${buildXmlElement('BusEventDate', fillData.requestDetails?.busAndOther?.eventDate)}
313+
${buildXmlElement('BusEventHour', fillData.requestDetails?.busAndOther?.eventHour)}
314+
${buildXmlElement('from', fillData.requestDetails?.busAndOther?.fromHour)}
315+
${buildXmlElement('by', fillData.requestDetails?.busAndOther?.toHour)}
316+
${buildXmlElement('Reportdate', fillData.requestDetails?.busAndOther?.reportdate)}
317+
${buildXmlElement('ReportTime', fillData.requestDetails?.busAndOther?.reportTime)}
318+
${buildXmlElement('Stationupdate', fillData.requestDetails?.busAndOther?.addOrRemoveStation)}
319+
${buildXmlElement('NumStation', fillData.requestDetails?.busAndOther?.addOrRemoveStation)}
320+
${buildXmlElement('LineNumberBoarding', fillData.requestDetails?.busAndOther?.lineNumberText)}
321+
${buildXmlElement('Direction', fillData.requestDetails?.busAndOther?.direction?.dataText)}
322+
${buildXmlElement('BusStationBoard', fillData.requestDetails?.busAndOther?.raisingStation?.dataText)}
323+
${buildXmlElement('BoardingSettlement', fillData.requestDetails?.busAndOther?.raisingStationCity?.dataText)}
324+
${buildXmlElement('DropStaionAppeal', fillData.requestDetails?.busAndOther?.destinationStationCity?.dataText)}
325+
${buildXmlElement('Risestationaddress', fillData.requestDetails?.busAndOther?.raisingStationAddress)}
326+
${buildXmlElement('MakatStation', fillData.requestDetails?.busAndOther?.makatStation)}
327+
${buildXmlElement('LineNumber', fillData.requestDetails?.busAndOther?.lineNumberFromList?.dataCode)}
328+
${buildXmlElement('BusDirectionFrom', fillData.requestDetails?.busAndOther?.busDirectionFrom)}
329+
${buildXmlElement('BusDirectionTo', fillData.requestDetails?.busAndOther?.busDirectionTo)}
330+
${buildXmlElement('Testimony', fillData.requestDetails?.busAndOther?.firstDeclaration || false)}
331+
${buildXmlElement('Courttestimony', fillData.requestDetails?.busAndOther?.secondDeclaration || false)}
332+
${buildXmlElement('CaseEssence', fillData.requestDetails?.busAndOther?.applyContent)}
333+
${buildXmlElement('OriginCityCode', fillData.requestDetails?.busAndOther?.originCityCode)}
334+
${buildXmlElement('OriginCityName', fillData.requestDetails?.busAndOther?.originCityName)}
335+
${buildXmlElement('LineCode', fillData.requestDetails?.busAndOther?.lineCode)}
336+
${buildXmlElement('CityId', fillData.requestDetails?.busAndOther?.cityId)}
337+
${buildXmlElement('CityName', fillData.requestDetails?.busAndOther?.cityName)}
338+
${buildXmlElement('StationName', fillData.requestDetails?.busAndOther?.stationName)}
339+
${buildXmlElement('DirectionCode', fillData.requestDetails?.busAndOther?.directionCode)}
340+
${buildXmlElement('DestinationCityCode', fillData.requestDetails?.busAndOther?.destinationCityCode)}
341+
${buildXmlElement('DestinationCityText', fillData.requestDetails?.busAndOther?.destinationCityText)}
324342
${buildXmlElement('Title', fillData.requestDetails?.title)}
325343
<RequestSubjectCode>0</RequestSubjectCode>
326344
<RequestTypeCode>0</RequestTypeCode>

0 commit comments

Comments
 (0)