'use strict'; const Dayjs = require('dayjs'); const Joi = require('joi'); const Rfr = require('rfr'); const Common = Rfr('/shared/common'); const ComSrv = Rfr('/server/comsrv'); const Db = Rfr('/server/db'); const dispToNumber = function(disp) { disp = disp.toUpperCase(); if (disp === 'ANSWERED') { return Common.resAnswered; } if (disp === 'NO ANSWER') { return Common.resNoAnswer; } if (disp === 'FAILED') { return Common.resFailed; } if (disp === 'BUSY') { return Common.resBusy; } if (disp === 'CANCELLED') { return Common.resCancelled; } return Common.resOther; } const moveSingleRecord = async function(r) { try { await Db.db().transaction(async trx => { const n = { calldate: Dayjs(r.calldate), source: Common.uglifyPhone(r.src), destination: (r.actualdst ? Common.uglifyPhone(r.actualdst) : Common.uglifyPhone(r.dst)), uniqueid: (r.actualuniqueid ? r.actualuniqueid : r.uniqueid), callduration: (r.actualbillsec ? r.actualbillsec : r.billsec), totalduration: r.duration, ivr: (r.ivr || 0) }; if (r.actualdst2 && r.ivr === 3) { n.destination = Common.uglifyPhone(r.actualdst2); } if (r.startedat && r.end) { const actualCD = Math.ceil(r.end - parseInt(r.startedat, 10)); if (Number.isSafeInteger(actualCD)) { n.callduration = actualCD; console.log('changing CD'); } } n.calltype = Common.getCallType(n.source, n.destination); if (r.actualdisposition) { n.callresult = dispToNumber(r.actualdisposition); } else if (r.ivr === 1 || r.ivr === 2) { n.callresult = Common.resCancelled; } else if (r.disposition === 'ANSWERED' && !r.startedat) { n.callresult = Common.resNoAnswer; } else { n.callresult = dispToNumber(r.disposition); } if (n.callresult === Common.resCancelled || n.callresult === Common.resNoAnswer) { n.callduration = 0; } const maxDaily = await trx.max('dailyid').from('ptable') .where('calldate', '>=', Dayjs(r.calldate).startOf('day')) .andWhere('calldate', '<=', Dayjs(r.calldate).endOf('day')).first(); n.dailyid = (!maxDaily || !maxDaily.max) ? 1 : (maxDaily.max + 1); const maxCT = await trx.max('dailyct').from('ptable') .where('calldate', '>=', Dayjs(r.calldate).startOf('day')) .andWhere('calldate', '<=', Dayjs(r.calldate).endOf('day')) .andWhere('calltype', '=', n.calltype).first(); n.dailyct = (!maxCT || !maxCT.max) ? 1 : (maxCT.max + 1); await trx.insert(n).into('ptable'); ComSrv.debug('Inserted record with UID: ' + n.uniqueid); }); } catch (e) { console.error('Failed to insert record to PTable: ' + e); } } const createPTable = async function() { const hasTable = await Db.db().schema.hasTable('ptable'); if (!hasTable) { console.log('PTable is missing - will create'); await Db.db().schema.createTable('ptable', t => { t.increments('id').primary(); t.timestamp('calldate'); t.integer('calltype'); t.integer('callresult'); t.string('source'); t.string('destination'); t.string('uniqueid'); t.integer('callduration'); t.integer('totalduration'); t.integer('dailyid'); t.integer('dailyct'); t.string('comment'); t.integer('ivr'); }); console.log('PTable created'); } }; const moveToPTable = async function() { await createPTable(); const rec = await Db.db().select('*').from(process.env.DB_TABLE) .where(function() { this.where(function() { this.whereNotNull('uniqueid') .whereNull('actualuniqueid') .whereNotIn('uniqueid', function() { this.select('uniqueid').from('ptable'); }) }) .orWhere(function() { this.whereNotNull('actualuniqueid') .whereNotIn('actualuniqueid', function() { this.select('uniqueid').from('ptable'); }) }) }) .where('duration', '>', 0) .whereNotNull('realcall') .where('realcall', '>=', 1) .whereNot(function() { this.whereNotNull('ivr') .where('ivr', '=', 3) .whereNull('startedat') }) .orderBy('calldate', 'asc'); if (rec && rec.length) { ComSrv.debug('Importing ' + rec.length + ' new records to PTable'); for (const r of rec) { await moveSingleRecord(r); } } setTimeout(moveToPTable, process.env.PTABLE_INTERVAL * 1000); }; const initPTable = async function() { await moveToPTable(); ComSrv.debug('PTable initialized'); }; module.exports = { initPTable: initPTable, config: Joi.object({ PTABLE_INTERVAL: Joi.number().min(1).max(300).default(10).optional() }) };