2017-04-16 22:09:08 +00:00
'use strict' ;
const db = require ( '../db' ) ;
const tableHelpers = require ( '../table-helpers' ) ;
const fields = require ( './fields' ) ;
const reportTemplates = require ( './report-templates' ) ;
const tools = require ( '../tools' ) ;
const _ = require ( '../translate' ) . _ ;
2017-04-20 23:42:01 +00:00
const allowedKeys = [ 'name' , 'description' , 'report_template' , 'params' ] ;
const ReportState = {
SCHEDULED : 0 ,
PROCESSING : 1 ,
FINISHED : 2 ,
2017-05-04 21:42:46 +00:00
FAILED : 3 ,
MAX : 4
2017-04-20 23:42:01 +00:00
} ;
module . exports . ReportState = ReportState ;
2017-04-16 22:09:08 +00:00
module . exports . list = ( start , limit , callback ) => {
2017-04-20 23:42:01 +00:00
tableHelpers . list ( 'reports' , [ '*' ] , 'name' , null , start , limit , callback ) ;
2017-04-16 22:09:08 +00:00
} ;
2017-04-20 23:42:01 +00:00
module . exports . listWithState = ( state , start , limit , callback ) => {
tableHelpers . list ( 'reports' , [ '*' ] , 'name' , { where : 'state=?' , values : [ state ] } , start , limit , callback ) ;
2017-04-23 19:24:31 +00:00
} ;
2017-04-20 23:42:01 +00:00
2017-04-16 22:09:08 +00:00
module . exports . filter = ( request , callback ) => {
tableHelpers . filter ( 'reports JOIN report_templates ON reports.report_template = report_templates.id' ,
2017-04-20 23:42:01 +00:00
[ 'reports.id AS id' , 'reports.name AS name' , 'reports.description AS description' , 'reports.state AS state' , 'reports.report_template AS report_template' , 'reports.params AS params' , 'reports.last_run AS last_run' , 'report_templates.name AS report_template_name' , 'report_templates.mime_type AS mime_type' ] ,
request , [ '#' , 'name' , 'report_templates.name' , 'description' , 'last_run' ] , [ 'name' ] , 'name ASC' , null , callback ) ;
2017-04-16 22:09:08 +00:00
} ;
module . exports . get = ( id , callback ) => {
id = Number ( id ) || 0 ;
if ( id < 1 ) {
return callback ( new Error ( _ ( 'Missing report ID' ) ) ) ;
}
db . getConnection ( ( err , connection ) => {
if ( err ) {
return callback ( err ) ;
}
connection . query ( 'SELECT * FROM reports WHERE id=?' , [ id ] , ( err , rows ) => {
connection . release ( ) ;
if ( err ) {
return callback ( err ) ;
}
if ( ! rows || ! rows . length ) {
return callback ( null , false ) ;
}
const template = tools . convertKeys ( rows [ 0 ] ) ;
const params = template . params . trim ( ) ;
2017-04-23 19:24:31 +00:00
if ( params !== '' ) {
2017-04-16 22:09:08 +00:00
try {
template . paramsObject = JSON . parse ( params ) ;
} catch ( err ) {
return callback ( err ) ;
}
} else {
template . params = { } ;
}
return callback ( null , template ) ;
} ) ;
} ) ;
} ;
2017-04-20 23:42:01 +00:00
// This method is not supposed to be used for unsanitized inputs. It does not do any checks.
module . exports . updateFields = ( id , fieldValueMap , callback ) => {
db . getConnection ( ( err , connection ) => {
if ( err ) {
2017-04-23 19:24:31 +00:00
return callback ( err ) ;
2017-04-20 23:42:01 +00:00
}
const clauses = [ ] ;
const values = [ ] ;
for ( let key of Object . keys ( fieldValueMap ) ) {
clauses . push ( tools . toDbKey ( key ) + '=?' ) ;
values . push ( fieldValueMap [ key ] ) ;
}
values . push ( id ) ;
const query = 'UPDATE reports SET ' + clauses . join ( ', ' ) + ' WHERE id=? LIMIT 1' ;
connection . query ( query , values , ( err , result ) => {
connection . release ( ) ;
if ( err ) {
return callback ( err ) ;
}
2017-04-23 19:24:31 +00:00
return callback ( null , result && result . affectedRows || false ) ;
2017-04-20 23:42:01 +00:00
} ) ;
} ) ;
} ;
module . exports . createOrUpdate = ( createMode , report , callback ) => {
report = report || { } ;
2017-04-16 22:09:08 +00:00
2017-04-20 23:42:01 +00:00
const id = 'id' in report ? Number ( report . id ) : 0 ;
2017-04-16 22:09:08 +00:00
if ( ! createMode && id < 1 ) {
return callback ( new Error ( _ ( 'Missing report ID' ) ) ) ;
}
2017-04-20 23:42:01 +00:00
const name = ( report . name || '' ) . toString ( ) . trim ( ) ;
2017-04-16 22:09:08 +00:00
if ( ! name ) {
return callback ( new Error ( _ ( 'Report name must be set' ) ) ) ;
}
2017-04-20 23:42:01 +00:00
const reportTemplateId = Number ( report . reportTemplate ) ;
2017-04-16 22:09:08 +00:00
reportTemplates . get ( reportTemplateId , ( err , reportTemplate ) => {
if ( err ) {
2017-04-23 19:24:31 +00:00
return callback ( err ) ;
2017-04-16 22:09:08 +00:00
}
2017-04-20 23:42:01 +00:00
const params = report . paramsObject ;
2017-04-16 22:09:08 +00:00
for ( const spec of reportTemplate . userFieldsObject ) {
if ( params [ spec . id ] . length < spec . minOccurences ) {
return callback ( new Error ( _ ( 'At least ' + spec . minOccurences + ' rows in "' + spec . name + '" have to be selected.' ) ) ) ;
}
if ( params [ spec . id ] . length > spec . maxOccurences ) {
return callback ( new Error ( _ ( 'At most ' + spec . minOccurences + ' rows in "' + spec . name + '" can be selected.' ) ) ) ;
}
}
const keys = [ 'name' , 'params' ] ;
const values = [ name , JSON . stringify ( params ) ] ;
2017-04-20 23:42:01 +00:00
Object . keys ( report ) . forEach ( key => {
let value = typeof report [ key ] === 'number' ? report [ key ] : ( report [ key ] || '' ) . toString ( ) . trim ( ) ;
2017-04-16 22:09:08 +00:00
key = tools . toDbKey ( key ) ;
if ( key === 'description' ) {
value = tools . purifyHTML ( value ) ;
}
if ( allowedKeys . indexOf ( key ) >= 0 && keys . indexOf ( key ) < 0 ) {
keys . push ( key ) ;
values . push ( value ) ;
}
} ) ;
db . getConnection ( ( err , connection ) => {
if ( err ) {
2017-04-23 19:24:31 +00:00
return callback ( err ) ;
2017-04-16 22:09:08 +00:00
}
let query ;
if ( createMode ) {
query = 'INSERT INTO reports (`' + keys . join ( '`, `' ) + '`) VALUES (' + values . map ( ( ) => '?' ) . join ( ',' ) + ')' ;
} else {
query = 'UPDATE reports SET ' + keys . map ( key => '`' + key + '`=?' ) . join ( ', ' ) + ' WHERE id=? LIMIT 1' ;
values . push ( id ) ;
}
connection . query ( query , values , ( err , result ) => {
connection . release ( ) ;
if ( err ) {
return callback ( err ) ;
}
if ( createMode ) {
return callback ( null , result && result . insertId || false ) ;
} else {
2017-04-23 19:24:31 +00:00
return callback ( null , result && result . affectedRows || false ) ;
2017-04-16 22:09:08 +00:00
}
} ) ;
} ) ;
} ) ;
} ;
module . exports . delete = ( id , callback ) => {
id = Number ( id ) || 0 ;
if ( id < 1 ) {
return callback ( new Error ( _ ( 'Missing report ID' ) ) ) ;
}
db . getConnection ( ( err , connection ) => {
if ( err ) {
return callback ( err ) ;
}
connection . query ( 'DELETE FROM reports WHERE id=? LIMIT 1' , [ id ] , ( err , result ) => {
connection . release ( ) ;
if ( err ) {
return callback ( err ) ;
}
const affected = result && result . affectedRows || 0 ;
return callback ( err , affected ) ;
} ) ;
} ) ;
} ;
const campaignFieldsMapping = {
2017-04-23 19:24:31 +00:00
tracker _count : 'tracker.count' ,
country : 'tracker.country' ,
device _type : 'tracker.device_type' ,
status : 'campaign.status' ,
first _name : 'subscribers.first_name' ,
last _name : 'subscribers.last_name' ,
email : 'subscribers.email'
2017-04-16 22:09:08 +00:00
} ;
module . exports . getCampaignResults = ( campaign , select , clause , callback ) => {
db . getConnection ( ( err , connection ) => {
if ( err ) {
return callback ( err ) ;
}
fields . list ( campaign . list , ( err , fieldList ) => {
if ( err ) {
return callback ( err ) ;
}
const fieldsMapping = fieldList . reduce ( ( map , field ) => {
map [ customFieldName ( field . key ) ] = 'subscribers.' + field . column ;
return map ;
} , Object . assign ( { } , campaignFieldsMapping ) ) ;
let selFields = [ ] ;
for ( let idx = 0 ; idx < select . length ; idx ++ ) {
const item = select [ idx ] ;
if ( item in fieldsMapping ) {
selFields . push ( fieldsMapping [ item ] + ' AS ' + item ) ;
2017-04-23 19:24:31 +00:00
} else if ( item === '*' ) {
2017-04-16 22:09:08 +00:00
selFields = selFields . concat ( Object . keys ( fieldsMapping ) . map ( item => fieldsMapping [ item ] + ' AS ' + item ) ) ;
} else {
selFields . push ( item ) ;
}
}
const query = 'SELECT ' + selFields . join ( ', ' ) + ' FROM `subscription__' + campaign . list + '` subscribers INNER JOIN `campaign__' + campaign . id + '` campaign on subscribers.id=campaign.subscription LEFT JOIN `campaign_tracker__' + campaign . id + '` tracker on subscribers.id=tracker.subscriber ' + clause ;
connection . query ( query , ( err , results ) => {
2017-05-03 19:46:49 +00:00
connection . release ( ) ;
2017-04-16 22:09:08 +00:00
if ( err ) {
return callback ( err ) ;
}
return callback ( null , results ) ;
} ) ;
} ) ;
} ) ;
} ;
function customFieldName ( id ) {
return id . replace ( /MERGE_/ , 'CUSTOM_' ) . toLowerCase ( ) ;
}