23maverick23
4/28/2016 - 2:41 PM

NSOA: Generate a project ledger CSV file

NSOA: Generate a project ledger CSV file

function generateProjectLedger(type) {
    var logPrefix = 'generateProjectLedger<br>';

    try {
        var LibOA = require('LibOpenAirBabyparse');
        var Base64 = require('Base64');

        var newRec = NSOA.form.getNewRecord();
        var timeentryData = getTimeEntries(newRec.id);
        var receiptData = getExpenseReceipts(newRec.id);
        var jsonData = timeentryData.concat(receiptData);

        NSOA.meta.log('debug', _debug(jsonData));

        var csvData = LibOA.Baby.unparse(jsonData);

        NSOA.meta.log('debug', _debug(csvData));

        var unixStr = new Date().getTime();
        var fileName = _slugify(newRec.name) + '-Project-Ledger-' + unixStr;

        var fileObj = new NSOA.record.oaAttachment();
        fileObj.file_name   = fileName + '.csv';
        fileObj.owner_type  = 'Project';
        fileObj.name        = fileName;
        fileObj.ownerid     = newRec.id;
        fileObj.base64_data = Base64.encode(csvData);
        fileObj.is_a_folder = 0;

        var file = NSOA.wsapi.add([fileObj]);
    } catch (e) {
        NSOA.meta.log('error', logPrefix + 'Unexpected error: ' + _error(e));
    }
}


function LedgerLine(type, id, date, employee, qty, currency, amount) {
    this.type     = type || "";
    this.id       = id || "";
    this.date     = date || "";
    this.employee = employee || "";
    this.qty      = qty || "";
    this.currency = currency || "";
    this.amount   = amount || "";
}


function _debug(object) {
    return new Date().getTime() + ' - ' + JSON.stringify(object);
}


function _error(error) {
    return error.message + ' (' + error.lineNumber + ')';
}


function _slugify(text) {
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}


function getEmployeeNames() {
    var logPrefix = 'getEmployeeNames<br>';
    var employees = {};

    try {
        var employeeObj = new NSOA.record.oaUser();

        var req = {
            type: "User",
            method: "equal to",
            fields: "id,name",
            attributes: [{name: "limit", value: "50"}],
            objects: [employeeObj]
        };

        var res = NSOA.wsapi.read(req);

        if (res === undefined || res[0].objects === null) {
            return employees;
        }

        for (var i = res[0].objects.length - 1; i >= 0; i--) {
            employees[res[0].objects[i].id] = res[0].objects[i].name;
        }

    } catch (e) {
        NSOA.meta.log('error', logPrefix + 'Unexpected error: ' + _error(e));
    } finally {
        return employees;
    }
}

function getTimeEntries(projectid) {
    var logPrefix = 'getTimeEntries<br>';
    var timeentries = [];

    try {
        if (!projectid || projectid.length === 0) {
            return timeentries;
        }

        var taskObj = new NSOA.record.oaTask();
        taskObj.projectid = projectid;

        var req = {
            type: "Task",
            method: "equal to",
            fields: "id,date,hours,userid",
            attributes: [{name: "limit", value: "100"}],
            objects: [taskObj]
        };

        var res = NSOA.wsapi.read(req);

        if (res === undefined || res[0].objects === null) {
            return timeentries;
        }

        var employees = getEmployeeNames();

        for (var i = res[0].objects.length - 1; i >= 0; i--) {
            // type, id, date, employee, qty, currency, amount
            var timeentry = new LedgerLine(
                "time",
                res[0].objects[i].id,
                res[0].objects[i].date,
                employees[res[0].objects[i].userid],
                res[0].objects[i].hours
            );
            timeentries.push(timeentry);
        }
    } catch (e) {
        NSOA.meta.log('error', logPrefix + 'Unexpected error: ' + _error(e));
    } finally {
        return timeentries;
    }
}


function getExpenseReceipts(projectid) {
    var logPrefix = 'getExpenseReceipts<br>';
    var receipts = [];

    try {
        if (!projectid || projectid.length === 0) {
            return receipts;
        }

        var ticketObj = new NSOA.record.oaTicket();
        ticketObj.projectid = projectid;

        var req = {
            type: "Ticket",
            method: "equal to",
            fields: "id,date,quantity,currency,total,userid",
            attributes: [{name: "limit", value: "100"}],
            objects: [ticketObj]
        };

        var res = NSOA.wsapi.read(req);

        if (res === undefined || res[0].objects === null) {
            return receipts;
        }

        var employees = getEmployeeNames();

        for (var i = res[0].objects.length - 1; i >= 0; i--) {
            // type, id, date, employee, qty, currency, amount
            var receipt = new LedgerLine(
                "expense",
                res[0].objects[i].id,
                res[0].objects[i].date,
                employees[res[0].objects[i].userid],
                res[0].objects[i].quantity,
                res[0].objects[i].currency,
                res[0].objects[i].total
            );
            receipts.push(receipt);
        }
    } catch (e) {
        NSOA.meta.log('error', logPrefix + 'Unexpected error: ' + _error(e));
    } finally {
        return receipts;
    }
}
function base64_decode(data) {
    var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
        ac = 0,
        dec = '',
        tmp_arr = [];

    if (!data) {
        return data;
    }

    data += '';

    do { // unpack four hexets into three octets using index points in b64
        h1 = b64.indexOf(data.charAt(i++));
        h2 = b64.indexOf(data.charAt(i++));
        h3 = b64.indexOf(data.charAt(i++));
        h4 = b64.indexOf(data.charAt(i++));

        bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;

        o1 = bits >> 16 & 0xff;
        o2 = bits >> 8 & 0xff;
        o3 = bits & 0xff;

        if (h3 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1);
        } else if (h4 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1, o2);
        } else {
            tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
        }
    } while (i < data.length);

    dec = tmp_arr.join('');

    return dec.replace(/\0+$/, '');
}

function base64_encode(data) {
    var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
        ac = 0,
        enc = '',
        tmp_arr = [];

    if (!data) {
        return data;
    }

    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);

        bits = o1 << 16 | o2 << 8 | o3;

        h1 = bits >> 18 & 0x3f;
        h2 = bits >> 12 & 0x3f;
        h3 = bits >> 6 & 0x3f;
        h4 = bits & 0x3f;

        // use hexets to index into b64, and append result to encoded string
        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    } while (i < data.length);

    enc = tmp_arr.join('');

    var r = data.length % 3;

    return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
}

exports.decode = base64_decode;
exports.encode = base64_encode;