From a819aef21816c16f871153e7b59ca93c96ccf131 Mon Sep 17 00:00:00 2001 From: jorgtho Date: Tue, 27 Sep 2022 15:48:35 +0200 Subject: [PATCH] Added flow definitions for creating and sending a response-letter for a flow --- lib/archive.js | 145 ++++++++++++++++++++++++++++- lib/flows/KONTRAKT.js | 3 + lib/run-flow.js | 60 +++++++++++- mock/KONTRAKT-invalid-address.json | 22 +++++ mock/KONTRAKT.json | 22 +++++ 5 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 mock/KONTRAKT-invalid-address.json create mode 100644 mock/KONTRAKT.json diff --git a/lib/archive.js b/lib/archive.js index b01fb0b..621b920 100644 --- a/lib/archive.js +++ b/lib/archive.js @@ -61,10 +61,12 @@ const callArchive = async (payload, e18JobId, e18TaskId, endpoint) => { } } +const unknownAddress = 'Ukjent adresse' + const getAddress = streetAddress => { if (streetAddress.Adresselinje1 && streetAddress.Adresselinje1 !== ' ') return streetAddress.Adresselinje1 if (streetAddress.Adresselinje2 && streetAddress.Adresselinje2 !== ' ') return streetAddress.Adresselinje2 - return 'Ukjent adresse' + return unknownAddress } module.exports.archive = async (blobContent, archiveOptions) => { @@ -195,3 +197,144 @@ module.exports.syncElevmappa = async blobContent => { // still nothing :O logger('warn', ['archive', 'syncElevmappa', 'Hit kommer vi aldri 🎉']) } + +// Archive response letter - creates a pdf and archives it with status R, ready for dispatching with SvarUT +module.exports.archiveResponseLetter = async (blobContent) => { + try { + blobContent.flow.archiveResponseLetterTaskId = blobContent.flow.archiveResponseLetterTaskId || await createTask(blobContent.e18JobId, { system: 'p360', method: 'archive' }) + + logger('info', ['archive', 'archiveResponseLetter']) + + // First check if we have address block or invalid zip-code (If address code is not 0, or if zipcode length is not 4, or if zipcode is 9999, or if address is unknown) + let payload + let invalidAddressMsg = 'Svarbrev må opprettes og sendes manuelt til mottaker for å sikre korrekt addressehåndtering. ' + blobContent.flow.invalidAddress = false + + if (blobContent.flow.syncElevmappa.privatePerson.addressCode !== 0) { + blobContent.flow.invalidAddress = true + invalidAddressMsg += 'Mottaker er ikke vanlig bosatt (har adressesperrre eller klientadresse).' + } else if (blobContent.flow.syncElevmappa.privatePerson.zipCode.length !== 4 || blobContent.flow.syncElevmappa.privatePerson.zipCode === '9999') { + blobContent.flow.invalidAddress = true + invalidAddressMsg += 'Mottakers postnummer er ikke et gyldig norsk postnummer.' + } else if (blobContent.flow.syncElevmappa.privatePerson.streetAddress === unknownAddress) { + blobContent.flow.invalidAddress = true + invalidAddressMsg += 'Gyldig mottaker-addresse ble ikke funnet i folkeregisteret eller i VIGO.' + } + if (blobContent.flow.invalidAddress) { + logger('info', ['archive', 'archiveResponseLetter', invalidAddressMsg, 'will not send on SvarUT, but update incoming document with a note.']) + payload = { + service: 'DocumentService', + method: 'UpdateDocument', + parameter: { + DocumentNumber: blobContent.flow.archive.DocumentNumber, + Remarks: [ + { + Title: invalidAddressMsg, + RemarkType: 'ME' + } + ] + } + } + } else { + logger('info', ['archive', 'archiveResponseLetter', 'address is ok, will create and archive response letter']) + payload = { + system: 'vigo', + template: `${blobContent.Dokumentelement.Dokumenttype}-response`, + parameter: { + caseNumber: blobContent.flow.syncElevmappa.elevmappe.CaseNumber, + ssn: blobContent.flow.syncElevmappa.privatePerson.ssn, + studentName: `${blobContent.flow.syncElevmappa.privatePerson.firstName} ${blobContent.flow.syncElevmappa.privatePerson.lastName}`, + streetAddress: blobContent.flow.syncElevmappa.privatePerson.streetAddress, + zipCode: blobContent.flow.syncElevmappa.privatePerson.zipCode, + zipPlace: blobContent.flow.syncElevmappa.privatePerson.zipPlace, + documentDate: blobContent.Dokumentelement.Dokumentdato + } + } + } + + const res = await callArchive(payload, blobContent.e18JobId, blobContent.flow.archiveResponseLetterTaskId, 'archive') + if (typeof res === 'object') { + blobContent.flow.archiveResponseLetter = res + blobContent.flow.archiveResponseLetter.status = 'finished' + } + } catch (error) { + blobContent.flow.archiveResponseLetter = { error } + blobContent.flow.archiveResponseLetter.status = 'failed' + } + + return blobContent +} + +// Archive response letter - creates a pdf and archives it with status R, ready for dispatching with SvarUT +module.exports.sendResponseLetter = async (blobContent) => { + try { + blobContent.flow.sendResponseLetterTaskId = blobContent.flow.sendResponseLetterTaskId || await createTask(blobContent.e18JobId, { system: 'p360', method: 'dispatch' }) + + logger('info', ['archive', 'sendResponseLetter']) + + if (blobContent.flow.invalidAddress) { + logger('info', ['archive', 'sendResponseLetter', 'Either address block or invalid address, response letter has not been created, and will not be sent']) + blobContent.flow.sendResponseLetter = { msg: 'Either address block or invalid address, response letter has not been created, and will not be sent' } + blobContent.flow.sendResponseLetter.status = 'finished' + } else { + logger('info', ['archive', 'sendResponseLetter', 'Dispatching with SvarUT']) + const payload = { + service: 'DocumentService', + method: 'DispatchDocuments', + parameter: { + Documents: [ + { + DocumentNumber: blobContent.flow.archiveResponseLetter.DocumentNumber + } + ] + } + } + const res = await callArchive(payload, blobContent.e18JobId, blobContent.flow.sendResponseLetterTaskId, 'archive') + if (typeof res === 'object') { + blobContent.flow.sendResponseLetter = res + blobContent.flow.sendResponseLetter.status = 'finished' + } + } + } catch (error) { + blobContent.flow.sendResponseLetter = { error } + blobContent.flow.sendResponseLetter.status = 'failed' + } + + return blobContent +} + +// Archive response letter - creates a pdf and archives it with status R, ready for dispatching with SvarUT +module.exports.signOffResponseLetter = async (blobContent) => { + try { + blobContent.flow.signOffResponseLetterTaskId = blobContent.flow.signOffResponseLetterTaskId || await createTask(blobContent.e18JobId, { system: 'p360', method: 'signOff' }) + + logger('info', ['archive', 'signOffResponseLetter']) + + if (blobContent.flow.invalidAddress) { + logger('info', ['archive', 'signOffResponseLetter', 'Either address block or invalid address, response letter has not been created, will NOT signoff']) + blobContent.flow.signOffResponseLetter = { msg: 'Either address block or invalid address, response letter has not been created, will NOT signoff' } + blobContent.flow.signOffResponseLetter.status = 'finished' + } else { + logger('info', ['archive', 'signOffResponseLetter', 'Signing off the original document']) + const payload = { + service: 'DocumentService', + method: 'SignOffDocument', + parameter: { + Document: blobContent.flow.archive.DocumentNumber, + ResponseCode: 'BU', + ReplyDocument: blobContent.flow.archiveResponseLetter.DocumentNumber + } + } + const res = await callArchive(payload, blobContent.e18JobId, blobContent.flow.signOffResponseLetterTaskId, 'archive') + if (typeof res === 'object') { + blobContent.flow.signOffResponseLetter = res + blobContent.flow.signOffResponseLetter.status = 'finished' + } + } + } catch (error) { + blobContent.flow.signOffResponseLetter = { error } + blobContent.flow.signOffResponseLetter.status = 'failed' + } + + return blobContent +} \ No newline at end of file diff --git a/lib/flows/KONTRAKT.js b/lib/flows/KONTRAKT.js index e539a87..a53242f 100644 --- a/lib/flows/KONTRAKT.js +++ b/lib/flows/KONTRAKT.js @@ -5,6 +5,9 @@ module.exports = async blobContent => { syncElevmappa: true, archive: true, statusVigo: true, + archiveResponseLetter: true, + sendResponseLetter: true, + signOffResponseLetter: true, e18Stats: true }) } diff --git a/lib/run-flow.js b/lib/run-flow.js index 321c05f..2497e16 100644 --- a/lib/run-flow.js +++ b/lib/run-flow.js @@ -1,15 +1,25 @@ -const { archive, signOff, syncElevmappa } = require('./archive') +const { archive, signOff, syncElevmappa, archiveResponseLetter, sendResponseLetter, signOffResponseLetter } = require('./archive') const { createTaskTemplate, complete } = require('./e18') const { updateStatusFlow } = require('./update-vigo-status') const { RETRY_INTERVAL_HOURS, RETRY_MAX_COUNT } = require('../config') const { logger } = require('@vtfk/logger') +/** + * @typedef {Object} archiveOptions + * @property {boolean} useStudentName + * @property {boolean} determineFileExt + */ + /** * @typedef {Object} FlowDefinition * @property {boolean} syncElevmappa * @property {boolean} archive + * @property {archiveOptions} archiveOptions * @property {boolean} signOff * @property {boolean} statusVigo + * @property {boolean} archiveResponseLetter + * @property {boolean} sendResponseLetter + * @property {boolean} signOffResponseLetter * @property {boolean} e18Stats */ @@ -76,6 +86,54 @@ module.exports = async (blobContent, flowDef) => { } } + // create and archive response letter + if (flowDef.archiveResponseLetter) { + if (flowDef.signOff) throw new Error('You cannot both have regular signoff and reponse-letter activated. You need to activate signoffResponseLetter instead') + + if (!blobContent.flow.archiveResponseLetter || blobContent.flow.archiveResponseLetter.status !== 'finished') { + blobContent = await archiveResponseLetter(blobContent) + } + + if (blobContent.flow.archiveResponseLetter.status !== 'finished') { + const retryMsg = (blobContent.retryCount >= RETRY_MAX_COUNT) ? `Max retry count ${RETRY_MAX_COUNT} reached, moved to error` : `Will retry in ${(blobContent.retryCount + 1) * RETRY_INTERVAL_HOURS} hours` + logger('warn', ['flow', 'archiveResponseLetter failed', 'Aborting', retryMsg]) + blobContent.flow.status = 'failed' + return blobContent + } + } + + // send response letter + if (flowDef.sendResponseLetter) { + if (!flowDef.archiveResponseLetter) throw new Error('You cannot use sendResponseLetter without using archiveResponseLetter') + + if (!blobContent.flow.sendResponseLetter || blobContent.flow.sendResponseLetter.status !== 'finished') { + blobContent = await sendResponseLetter(blobContent) + } + + if (blobContent.flow.sendResponseLetter.status !== 'finished') { + const retryMsg = (blobContent.retryCount >= RETRY_MAX_COUNT) ? `Max retry count ${RETRY_MAX_COUNT} reached, moved to error` : `Will retry in ${(blobContent.retryCount + 1) * RETRY_INTERVAL_HOURS} hours` + logger('warn', ['flow', 'sendResponseLetter failed', 'Aborting', retryMsg]) + blobContent.flow.status = 'failed' + return blobContent + } + } + + // sign off with the original document with response letters DocumentNumber + if (flowDef.signOffResponseLetter) { + if (!flowDef.sendResponseLetter) throw new Error('You cannot use signOffResponseLetter without using sendResponseLetter') + + if (!blobContent.flow.signOffResponseLetter || blobContent.flow.signOffResponseLetter.status !== 'finished') { + blobContent = await signOffResponseLetter(blobContent) + } + + if (blobContent.flow.signOffResponseLetter.status !== 'finished') { + const retryMsg = (blobContent.retryCount >= RETRY_MAX_COUNT) ? `Max retry count ${RETRY_MAX_COUNT} reached, moved to error` : `Will retry in ${(blobContent.retryCount + 1) * RETRY_INTERVAL_HOURS} hours` + logger('warn', ['flow', 'signOffResponseLetter failed', 'Aborting', retryMsg]) + blobContent.flow.status = 'failed' + return blobContent + } + } + // add e18 task for statistics if (flowDef.e18Stats) { if (!blobContent.flow.e18StatsTask || blobContent.flow.e18StatsTask.status !== 'finished') { diff --git a/mock/KONTRAKT-invalid-address.json b/mock/KONTRAKT-invalid-address.json new file mode 100644 index 0000000..1b1bd91 --- /dev/null +++ b/mock/KONTRAKT-invalid-address.json @@ -0,0 +1,22 @@ +{ + "UnikId": "26", + "FagsystemNavn": "VIGO", + "Fodselsnummer": "12345678911", + "Fornavn": "Bjarte", + "Etternavn": "Tjøstheim", + "Skole": "", + "Fylke": "38", + "FolkeRegisterAdresse": { + "Adresselinje2": "", + "Postnummmer": "1234", + "Poststed": "_ Ukjent" + }, + "Dokumentelement": { + "Dokumenttype": "KONTRAKT", + "Dokumenttittel": "Ny søker (m/ønsker / avg.elev)", + "DokumentId": "invalidAddress", + "Dokumentdato": "2022-01-06T00:00:00+01:00", + "Dokumentfil": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwogIC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAvTWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0KPj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAgL1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9udAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2JqCgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJUCjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4gCjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAwMDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G" + }, + "retryCount": 0 +} diff --git a/mock/KONTRAKT.json b/mock/KONTRAKT.json new file mode 100644 index 0000000..1a9dfba --- /dev/null +++ b/mock/KONTRAKT.json @@ -0,0 +1,22 @@ +{ + "UnikId": "26", + "FagsystemNavn": "VIGO", + "Fodselsnummer": "12345678911", + "Fornavn": "Bjarte", + "Etternavn": "Tjøstheim", + "Skole": "", + "Fylke": "38", + "FolkeRegisterAdresse": { + "Adresselinje2": "Jeg har adresse og gyldig postnr", + "Postnummmer": "1234", + "Poststed": "Klukkstein" + }, + "Dokumentelement": { + "Dokumenttype": "KONTRAKT", + "Dokumenttittel": "Ny søker (m/ønsker / avg.elev)", + "DokumentId": "ADADBKHFGSYI", + "Dokumentdato": "2022-01-06T00:00:00+01:00", + "Dokumentfil": "JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwogIC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAvTWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0KPj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAgL1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9udAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2JqCgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJUCjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4gCjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAwMDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G" + }, + "retryCount": 0 +}