const db=require('../config/dbproc.js'); // const slashes = require('slashes'); const QRCode = require('qrcode'); const Adapter=require('./dbadapter.js'); const fs = require("fs"); const { callbackPromise } = require('nodemailer/lib/shared/index.js'); const path = require('path'); // const { fs } = require('fs').promises; const libre = require('libreoffice-convert'); libre.convertAsync = require('util').promisify(libre.convert); function getToken(){ try { var n1=Math.floor(Math.random() * 9) + 0; var n2=Math.floor(Math.random() * 9) + 0; var n3=Math.floor(Math.random() * 9) + 0; var n4=Math.floor(Math.random() * 9) + 0; var n5=Math.floor(Math.random() * 9) + 0; var n6=Math.floor(Math.random() * 9) + 0; var otp=n1.toString()+n2.toString()+n3.toString()+n4.toString()+n5.toString()+n6.toString(); // console.log(otp); return otp; } catch (error) { return error; } } async function ConvertToPdf(inputPath, outputPath) { // const ext = '.pdf' // const inputPath = path.join(__dirname, '/resources/example.docx'); // const outputPath = path.join(__dirname, `/resources/example${ext}`); // Read file const docxBuf = await fs.readFile(inputPath); // Convert it to pdf format with undefined filter (see Libreoffice docs about filter) let pdfBuf = await libre.convertAsync(docxBuf, '.pdf', undefined); // Here in done you have pdf file which you can save or transfer in another stream await fs.writeFile(outputPath, pdfBuf); } class JustificationAdapter extends Adapter{ constructor(){ super(); } async queryJustificationBudgetRequestList(req,callback){ var apires = this.getApiResultDefined(); try { let id = req.query.id; // console.log(req); let qry = "select * from vw_requestbudget order by id asc"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; } callback(null, apires); } }); } catch(err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryNewJustification(filename, req, callback){ var apires = this.getApiResultDefined(); try { // console.log(req.body); let idxrequestbudget= req.body.idxrequestbudget; let trxid = req.body.trxid; let justificationnumber = req.body.nomorjustifikasi; let title = req.body.judul; let division = req.body.divisi; let glacc = req.body.acccode; let description = req.body.deskripsi; let budgettype = req.body.jenisbudget; let amount = req.body.nilai; let useddate = req.body.tanggalpelaksanaan; let textpurpose = "";//req.body.maksudtujuan; let textintroduce = "";//req.body.latarbelakang; let textstrategic = "";//req.body.strategis; let textbussiness = "";//req.body.bisnis; let textrisk = "";//req.body.risiko; let textfund = "";//req.body.pembiayaan; let textrecomendation = "";//req.body.rekomendasi; let textschedule = "";//req.body.penjadwalan; let filedoc = filename; let nik = req.body.nik; let boq = JSON.parse(req.body.boq); let ttd = JSON.parse(req.body.ttd); let status = -1; let statusdescription = "draft"; let qry = "insert into tbl_justification "; qry = qry +"set idxrequestbudget='"+idxrequestbudget+"', trxid='"+trxid+"',justificationnumber='"+justificationnumber+"',title='"+title+"',division='"+division+"',"; qry = qry +"glacc='"+glacc+"',description='"+description+"',budgettype='"+budgettype+"',amount='"+amount+"',useddate='"+useddate+"',textpurpose='"+textpurpose+"',textintroduce='"+textintroduce+"',"; qry = qry +"textstrategic='"+textstrategic+"',textbussiness='"+textbussiness+"',textrisk='"+textrisk+"',textfund='"+textfund+"',textrecomendation='"+textrecomendation+"',"; qry = qry +"textschedule='"+textschedule+"',status='"+status+"',statusdescription='"+statusdescription+"',filedoc='"+filedoc+"',iby='"+nik+"',idt=now()"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { var res = JSON.parse(JSON.stringify(result)); var idjustification = res.insertId; // ==== Add boq // console.log(boq); qry=""; Object.keys(boq).forEach(function(key){ var items = boq[key]['items']; var qty = boq[key]['qty']; var unitprice = boq[key]['unitprice']; var units = boq[key]['units']||""; var total = boq[key]['total']; qry = "insert into tbl_justificationboq set idxjustification='"+idjustification+"',"; qry = qry + "items='"+items+"',qty='"+qty+"',units='"+units+"',unitprice='"+unitprice+"',total='"+total+"',iby='"+nik+"',idt=now()"; db.query(qry,[],function(err2,result2,fields2){return result2;}); // console.log(r); }); // ==== add ttd var created = ttd.dibuatoleh; var approval = ttd.disetujuioleh; Object.keys(created).forEach(function(key){ var token =getToken(); var idemployee = created[key]['idemployee']; var nikapproval = created[key]['nik']; qry = "insert into tbl_justificationttd set idxjustification='"+idjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nikapproval+"',category='CRE',token='"+token+"',imgqr='',iby='"+nik+"',idt=now()"; db.query(qry,[],function(err3,result3,fields3){return result3;}); // QRCode.toDataURL(token, function (err, code) { // if(err) return console.log("error occurred") // qry = "insert into tbl_justificationttd set idxjustification='"+idjustification+"',idemployee='"+idemployee+"',"; // qry = qry + "nik='"+nik+"',category='CRE',token='"+token+"',imgqr='"+code+"',iby='"+nik+"',idt=now()"; // db.query(qry,[],function(err3,result3,fields3){return result3;}); // // Printing the code // // console.log(code) // }) // console.log(r); }); Object.keys(approval).forEach(function(key){ var token =getToken(); var idemployee = approval[key]['idemployee']; var nik = approval[key]['nik']; // if(err) return console.log("error occurred") qry = "insert into tbl_justificationttd set idxjustification='"+idjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nik+"',category='APR',token='"+token+"',imgqr='',iby='"+nik+"',idt=now()"; db.query(qry,[],function(err3,result3,fields3){return result3;}); // QRCode.toDataURL(token, function (err, code) { // if(err) return console.log("error occurred") // qry = "insert into tbl_justificationttd set idxjustification='"+idjustification+"',idemployee='"+idemployee+"',"; // qry = qry + "nik='"+nik+"',category='APR',token='"+token+"',imgqr='"+code+"',iby='"+nik+"',idt=now()"; // db.query(qry,[],function(err3,result3,fields3){return result3;}); // // Printing the code // // console.log(code) // }) // console.log(r); }); apires.success = true; apires.meta.message = "Saved Success"; apires.data = res; callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryUpdateJustification(filename, req, callback){ var apires = this.getApiResultDefined(); try { // console.log(req.body); let idxjustification= req.body.idxjustification; let idxrequestbudget= req.body.idxrequestbudget; let trxid = req.body.trxid; let justificationnumber = req.body.nomorjustifikasi; let title = req.body.judul; let division = req.body.divisi; let glacc = req.body.acccode; let description = req.body.deskripsi; let budgettype = req.body.jenisbudget; let amount = req.body.nilai; let useddate = req.body.tanggalpelaksanaan; let textpurpose = "";//req.body.maksudtujuan; let textintroduce = "";//req.body.latarbelakang; let textstrategic = "";//req.body.strategis; let textbussiness = "";//req.body.bisnis; let textrisk = "";//req.body.risiko; let textfund = "";//req.body.pembiayaan; let textrecomendation = "";//req.body.rekomendasi; let textschedule = "";//req.body.penjadwalan; let filedoc = filename; let nik = req.body.nik; let boq = JSON.parse(req.body.boq); let ttd = JSON.parse(req.body.ttd); let filedocqry = "filedoc='"+filedoc+"',"; if(filename==""){filedocqry="";} // console.log(filedocqry); let qry = "update tbl_justification "; qry = qry +"set idxrequestbudget='"+idxrequestbudget+"', trxid='"+trxid+"',justificationnumber='"+justificationnumber+"',title='"+title+"',division='"+division+"',"; qry = qry +"glacc='"+glacc+"',description='"+description+"',budgettype='"+budgettype+"',amount='"+amount+"',useddate='"+useddate+"',textpurpose='"+textpurpose+"',textintroduce='"+textintroduce+"',"; qry = qry +"textstrategic='"+textstrategic+"',textbussiness='"+textbussiness+"',textrisk='"+textrisk+"',textfund='"+textfund+"',textrecomendation='"+textrecomendation+"',"; qry = qry +"textschedule='"+textschedule+"',"+filedocqry+"uby='"+nik+"',udt=now() "; qry = qry +"where _idx='"+idxjustification+"'"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { Object.keys(boq).forEach(function(key){ var idboq = boq[key]['id']; var items = boq[key]['items']; var qty = boq[key]['qty']; var unitprice = boq[key]['unitprice']; var units = boq[key]['units']; var total = boq[key]['total']; var action = boq[key]['action']; qry = "insert into tbl_justificationboq set idxjustification='"+idxjustification+"',"; qry = qry + "items='"+items+"',qty='"+qty+"',units='"+units+"',unitprice='"+unitprice+"',total='"+total+"',iby='"+nik+"',idt=now()"; if(action=='update'){ qry = "update tbl_justificationboq set idxjustification='"+idxjustification+"',"; qry = qry + "items='"+items+"',qty='"+qty+"',units='"+units+"',unitprice='"+unitprice+"',total='"+total+"',uby='"+nik+"',udt=now() "; qry = qry + "where _idx='"+idboq+"'"; } if(action=='delete'){ qry = "update tbl_justificationboq set isdeleted=1,dby='"+nik+"',ddt=now() "; qry = qry + "where _idx='"+idboq+"'"; } db.query(qry,[],function(err2,result2,fields2){return result2;}); // console.log(r); }); var created = ttd.dibuatoleh; var approval = ttd.disetujuioleh; Object.keys(created).forEach(function(key){ var token =getToken(); var id = created[key]['id']; var idemployee = created[key]['idemployee']; var nik = created[key]['nik']; var action = created[key]['action']; qry = "insert into tbl_justificationttd set idxjustification='"+idxjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nik+"',category='CRE',token='"+token+"',imgqr='',iby='"+nik+"',idt=now()"; if(action=='update'){ qry = "update tbl_justificationttd set idxjustification='"+idxjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nik+"',category='CRE',token='"+token+"',imgqr='',uby='"+nik+"',udt=now() "; qry = qry + "where _idx='"+id+"' and issigned=0"; } if(action=='delete'){ qry = "update tbl_justificationttd set isdeleted=1,dby='"+nik+"',ddt=now() "; qry = qry+ "where _idx='"+id+"'"; } db.query(qry,[],function(err3,result3,fields3){return result3;}); }); Object.keys(approval).forEach(function(key){ var token =getToken(); var id = approval[key]['id']; var idemployee = approval[key]['idemployee']; var nik = approval[key]['nik']; var action = approval[key]['action']; qry = "insert into tbl_justificationttd set idxjustification='"+idxjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nik+"',category='APR',token='"+token+"',imgqr='',iby='"+nik+"',idt=now()"; if(action=='update'){ qry = "update tbl_justificationttd set idxjustification='"+idxjustification+"',idemployee='"+idemployee+"',"; qry = qry + "nik='"+nik+"',category='APR',token='"+token+"',imgqr='',uby='"+nik+"',udt=now() "; qry = qry + "where _idx='"+id+"' and issigned=0"; } if(action=='delete'){ qry = "update tbl_justificationttd set isdeleted=1,dby='"+nik+"',ddt=now() "; qry = qry+ "where _idx='"+id+"'"; } db.query(qry,[],function(err3,result3,fields3){return result3;}); }); apires.success = true; apires.meta.message = "Updated Success"; apires.data = JSON.parse(JSON.stringify(result)); callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryUpdateStatusJustification(req, callback) { try { var apires = this.getApiResultDefined(); var idxjustification = req.body.idxjustification; var status = req.body.status; var statusdescription = req.body.statusdescription; var nik = req.body.nik; var qry = "update tbl_justification set status='" + status +"',statusdescription='" + statusdescription +"',uby='"+nik+"',udt=now() "; qry = qry +"where _idx='" + idxjustification +"'"; db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { // if(result.length>0){ apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); // } // else{ // apires.meta.code = 200; // apires.meta.message = "Record Not Found"; // } callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryConvertdocxtoPdf(req, callback) { try { var apires = this.getApiResultDefined(); var idxjustification = req.body.idxjustification; var qry = "select * from vw_justification where id='" + idxjustification +"'"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ const inputPath = "/home/nodejs/wsproc/assets/words/justifikasitemplate.docx"; const outputPath = "/home/nodejs/wsproc/assets/pdf/justifikasitemplate.pdf"; // console.log(__dirname); ConvertToPdf(inputPath, outputPath).catch(function (err) { if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else{ apires.success = true; callback(null,apires); } // console.log(`Error converting file: ${err}`); }); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); } } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async querySignedJustification(filename, req, callback) { try { var apires = this.getApiResultDefined(); let idxjustification= req.body.idxjustification; let idxrequestbudget= req.body.idxrequestbudget; let trxid = req.body.trxid; let justificationnumber = req.body.nomorjustifikasi; let title = req.body.judul; let division = req.body.divisi; let glacc = req.body.acccode; let description = req.body.deskripsi; let budgettype = req.body.jenisbudget; let amount = req.body.nilai; let useddate = req.body.tanggalpelaksanaan; let filedoc = filename; var idxapproval = req.body.idxapproval; var nikapproval = req.body.nikapproval; var datesigned = req.body.datesigned; // console.log(datesigned); var nik = req.body.nik; var token = this.getToken(); var filepng = token+".png"; // token =getToken(); token = token +","+nikapproval; let filedocqry = "filedoc='"+filedoc+"',"; if(filename=="") { filedocqry=""; // apires.meta['message'] = "File tidak ditemukan"; // apires.meta['code'] = 500; // callback(null, apires); } let qry = "update tbl_justification "; qry = qry +"set idxrequestbudget='"+idxrequestbudget+"', trxid='"+trxid+"',justificationnumber='"+justificationnumber+"',title='"+title+"',division='"+division+"',"; qry = qry +"glacc='"+glacc+"',description='"+description+"',budgettype='"+budgettype+"',amount='"+amount+"',useddate='"+useddate+"',"; qry = qry +filedocqry+"uby='"+nik+"',udt=now() "; qry = qry +"where _idx='"+idxjustification+"'"; db.query(qry,[],function(err,result,fields){ if(err){ console.log('d'); apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { QRCode.toDataURL(token, function (err, code) { // console.log(code);` if(err) { console.log('ddf'); apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { var imageBuffer = Adapter.decodeBase64Image(code); fs.writeFile('./assets/png/'+filepng, imageBuffer.data, function(err) { // console.log(err); if(err){ console.log('eee'); apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback(err.toString(), apires); } else{ var qry = "update tbl_justificationttd set token=md5('"+token+"'),imgqr='"+filepng+"',issigned='1',signeddate='"+datesigned+"',uby='"+nik+"',udt=now() "; qry = qry +"where _idx='" + idxapproval +"'"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ console.log('ttetete'); apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { apires.success = true; // === qry = "select status from tbl_justification where _idx='"+idxjustification+"'"; db.query(qry,[],function(err,result2,fields){ if(err){ console.log('bbbb'); apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('error',apires); } else { var status = result2[0]['status']; var isapproved=0; if(status==2){isapproved = 1;} apires.data = { "isapproved":isapproved, "token":token, "urltoken": process.env.BASEURL+"/main/getimageinfo?route=png&name="+filepng }; callback(null, apires); } }); } }); } }); } }); } }); // else{ // } } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryDeleteJustification(req, callback){ var apires = this.getApiResultDefined(); try { let id = req.body.id; let remarkdeleted = req.body.remarkdeleted; let nik = req.body.nik; let qry = "update tbl_justification "; qry = qry +"set isdeleted=1,remarkdeleted='"+remarkdeleted+"',dby='"+nik+"',ddt=now()"; qry = qry +" where _idx='"+id+"'"; db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { apires.success = true; apires.meta.message = "Deleted Success"; callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryListCreatedBy(req,callback){ var apires = this.getApiResultDefined(); try { let qry = "select * from vw_createdby order by id asc"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; } callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryListCheckedBy(req,callback){ var apires = this.getApiResultDefined(); try { let qry = "select * from vw_checkedby order by id asc"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; } callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryListApprovedBy(req,callback){ var apires = this.getApiResultDefined(); try { let qry = "select * from vw_approvedby order by id asc"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ apires.success = true; apires.data = JSON.parse(JSON.stringify(result)); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; } callback(null, apires); } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryJustificationDetail(req,callback){ var apires = this.getApiResultDefined(); try { let _idx= req.query.id; let qry = "select * from vw_justificationdetail where id='"+_idx+"'"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { let dataRows = result.length; if(result.length<=0){ apires.meta.message = "Record not found"; callback('',apires); } else{ Object.keys(result).forEach(function(key){ qry = "select * from vw_justificationboq where idxjustification='"+_idx+"' order by id asc"; // console.log(qry); db.query(qry,[],function(err,result2,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('error',apires); } else{ result[key]['boq'] = []; result[key]['ttd']= []; if(result2.length>0){ result[key]['boq'] = JSON.parse(JSON.stringify(result2)); } // === Get Ttd qry = "select * from vw_justificationttd where idxjustification='"+_idx+"' order by id asc"; // console.log(qry); db.query(qry,[],function(err,result3,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('error',apires); } else{ if(result3.length>0){ var dibuatoleh = []; var disetujuioleh = []; Object.keys(result3).forEach(function(key2){ if(result3[key2]['category']=='CRE'){ dibuatoleh.push(JSON.parse(JSON.stringify(result3[key2]))); }else{ disetujuioleh.push(JSON.parse(JSON.stringify(result3[key2]))); } }); result[key]['ttd'] = { "dibuatoleh" : dibuatoleh, "disetujuioleh" : disetujuioleh } // result[key]['ttd'] = JSON.parse(JSON.stringify(result3)); } if(0 === --dataRows){ let resultJson = JSON.stringify(result); console.log(resultJson); resultJson = JSON.parse(resultJson); apires.success = true; apires.data = resultJson; callback(null,apires); } } }); } }); }); } } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } async queryJustificationList(req,callback){ var apires = this.getApiResultDefined(); try { let limit = req.body.limit; let offset = req.body.offset; let keyword = req.body.keyword; let nik = req.body.nik; let status = req.body.status; let swherenik=""; if(nik){ swherenik="iby='"+nik+"' and "; } // let qry = "select * from vw_justification "; // qry = qry +"where (trim(acccode) like '%"+ keyword +"%' or trim(nomorjustifikasi) like '%"+ keyword +"%') "; // qry = qry +"and iby='"+nik+"' and status in("+status+") order by id asc"; let qry = "select * from vw_justification "; qry = qry +"where (trim(acccode) like '%"+ keyword +"%' or trim(nomorjustifikasi) like '%"+ keyword +"%') "; qry = qry +"and "+swherenik+" status in("+status+") order by id asc"; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { if(result.length>0){ let pagination = result.length / limit; if(!Number.isInteger(pagination)){ pagination=(Math.floor(result.length / limit))+1; } // let pagination = Adapter.getPagination(result.length, limit); apires.success = true; apires.data.push({ "totalpage": pagination, "totalrows": result.length }); qry = "select * from vw_justification "; qry = qry +"where (trim(acccode) like '%"+ keyword +"%' or trim(nomorjustifikasi) like '%"+ keyword +"%') "; qry = qry +"and "+swherenik+" status in("+status+") order by id asc limit " + offset + ", " + limit; // console.log(qry); db.query(qry,[],function(err,result,fields){ if(err){ apires.meta['message'] = err.toString(); apires.meta['code'] = 500; callback('err',apires); } else { apires.data.push({ "results": JSON.parse(JSON.stringify(result)) }); callback(null, apires); } }); } else{ apires.meta.code = 200; apires.meta.message = "Record Not Found"; callback(null, apires); } } }); } catch (err) { apires.meta.code = 500; apires.meta.message = err.toString(); callback('error',apires); } } } module.exports = JustificationAdapter;