Problem :
Need to reschedule the map reduce script to update the invoice trandate. The error should save in a csv file.
Solution :
/**
* @NApiVersion 2.1
* @NScriptType MapReduceScript
*/
/*******************************************************************************
* CLIENTNAME: Branded
* Develop a script to help finance mass update the Invoice dates based on their Posting date mentioned in the
* Finance date range report.
*************************************************************************
* Date : 18-01-2022
*
* Author: Jobin & Jismi IT Services LLP
* Script Description :
* The script is to Import/export records as per the given criteria.
* Date created :18-01-2022
* REVISION HISTORY
* Revision 1.0 ${21-01-2022}
*
******************************************************************************/
define(['N/error', 'N/file', 'N/record', 'N/task', 'N/search','/SuiteScripts/J&J Script/papaparse.min.js'],
/**
* @param{error} error
* @param{file} file
* @param{record} record
* @param{search} search
*/
(error, file, record, task, search,papa) => {
/**
* Defines the function that is executed at the beginning of the map/reduce process and generates the input data.
* @param {Object} inputContext
* @param {boolean} inputContext.isRestarted - Indicates whether the current invocation of this function is the first
* invocation (if true, the current invocation is not the first invocation and this function has been restarted)
* @param {Object} inputContext.ObjectRef - Object that references the input data
* @typedef {Object} ObjectRef
* @property {string|number} ObjectRef.id - Internal ID of the record instance that contains the input data
* @property {string} ObjectRef.type - Type of the record instance that contains the input data
* @returns {Array|Object|Search|ObjectRef|File|Query} The input data to use in the map/reduce process
* @since 2015.2
*/
const getInputData = (inputContext) => {
try{
log.debug("GetInputData_Starting!");
var import_trandateSearchObj = search.create({
type: "customrecord_jj_finance_import_trandate",
filters:
[
["custrecord_jj_itd_status","is","PENDING"],
"AND",
["isinactive","is","F"]
],
columns:
[
search.createColumn({
name: "name",
sort: search.Sort.ASC,
label: "Name"
}),
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({name: "created", label: "Date Created"}),
search.createColumn({name: "custrecord_jj_itd_status", label: "STATUS"}),
search.createColumn({name: "custrecord_jj_itd_inputfile", label: "INPUT File"}),
search.createColumn({name: "custrecord_jj_itd_resultfile", label: "RESULT File"}),
search.createColumn({name: "custrecord_jj_itd_errorfile", label: "ERROR File"})
]
});
var searchResultCount = import_trandateSearchObj.runPaged().count;
let result=import_trandateSearchObj.run();
var resultRange=result.getRange({
start: 0,
end: 50
});
log.debug("Result Range",resultRange);
if(searchResultCount>0) {
// log.debug("Nothing will happen");
log.debug("Record_ID", resultRange[0].id);
var objRecord = record.load({
type: 'customrecord_jj_finance_import_trandate',
id: resultRange[0].id,
isDynamic: true,
});
log.debug("record", objRecord)
var file_internal_id = objRecord.getValue({
fieldId: 'custrecord_jj_itd_inputfile'
})
log.debug("File id", file_internal_id)
var uploadFile = file.load({id: file_internal_id});
log.debug("Record uploadFile", uploadFile)
var csvContent = uploadFile.getContents();
log.debug("Datacsv", csvContent)
var newValue = papa.parse(csvContent, {
header: true,
skipEmptyLines: true
});
log.debug("newValue", newValue)
objRecord.setValue({
fieldId: 'custrecord_jj_itd_status',
value: 'PROCESSING'
})
objRecord.save()
return newValue.data.map(el => {
el.customRecInternalId = resultRange[0].id;
return el
})
}
}
catch (err)
{
log.debug("Error@getinput",err)
}
}
/**
* Defines the function that is executed when the reduce entry point is triggered. This entry point is triggered
* automatically when the associated map stage is complete. This function is applied to each group in the provided context.
* @param {Object} reduceContext - Data collection containing the groups to process in the reduce stage. This parameter is
* provided automatically based on the results of the map stage.
* @param {Iterator} reduceContext.errors - Serialized errors that were thrown during previous attempts to execute the
* reduce function on the current group
* @param {number} reduceContext.executionNo - Number of times the reduce function has been executed on the current group
* @param {boolean} reduceContext.isRestarted - Indicates whether the current invocation of this function is the first
* invocation (if true, the current invocation is not the first invocation and this function has been restarted)
* @param {string} reduceContext.key - Key to be processed during the reduce stage
* @param {List<String>} reduceContext.values - All values associated with a unique key that was passed to the reduce stage
* for processing
* @since 2015.2
*/
const reduce = (reduceContext) => {
var array=[]
try{
log.debug("reduceContext_Starting!");
log.debug("InternalID Global",internalID);
let searchResult = JSON.parse(reduceContext.values);
log.debug("searchResult",searchResult)
let date = searchResult['date/time']
log.debug("Date",date)
let orderid=searchResult['order id']
log.debug("Order ID",orderid);
var invoiceSearchNewObj = search.create({
type: "invoice",
filters:
[
["type","anyof","CustInvc"],
"AND",
["mainline","is","T"],
"AND",
["custbody_celigo_etail_order_id","is",orderid]
],
columns:
[
search.createColumn({
name: "ordertype",
sort: search.Sort.ASC,
label: "Order Type"
}),
search.createColumn({name: "trandate", label: "Date"}),
search.createColumn({name: "internalid", label: "Internal ID"})
]
});
var recId
var searchResultCount = invoiceSearchNewObj.runPaged().count;
invoiceSearchNewObj.run().each(function(result){
recId=result.getValue({name: "internalid", label: "Internal ID"})
log.debug("Invo",recId)
let objRecord1 = record.submitFields({
type: record.Type.INVOICE,
id: recId,
values: {
'trandate': date
}
});
return true;
});
reduceContext.write({
key: 'success',
value: searchResult
})
}
catch (err)
{
log.debug("error",err)
let searchResult = JSON.parse(reduceContext.values);
reduceContext.write({
key: 'error',
value: {...searchResult,'error':err}
});
}
}
/**
* Defines the function that is executed when the summarize entry point is triggered. This entry point is triggered
* automatically when the associated reduce stage is complete. This function is applied to the entire result set.
* @param {Object} summaryContext - Statistics about the execution of a map/reduce script
* @param {number} summaryContext.concurrency - Maximum concurrency number when executing parallel tasks for the map/reduce
* script
* @param {Date} summaryContext.dateCreated - The date and time when the map/reduce script began running
* @param {boolean} summaryContext.isRestarted - Indicates whether the current invocation of this function is the first
* invocation (if true, the current invocation is not the first invocation and this function has been restarted)
* @param {Iterator} summaryContext.output - Serialized keys and values that were saved as output during the reduce stage
* @param {number} summaryContext.seconds - Total seconds elapsed when running the map/reduce script
* @param {number} summaryContext.usage - Total number of governance usage units consumed when running the map/reduce
* script
* @param {number} summaryContext.yields - Total number of yields when running the map/reduce script
* @param {Object} summaryContext.inputSummary - Statistics about the input stage
* @param {Object} summaryContext.mapSummary - Statistics about the map stage
* @param {Object} summaryContext.reduceSummary - Statistics about the reduce stage
* @since 2015.2
*/
const summarize = (summaryContext) => {
try {
var titleArray = ["order id", "Error Description"];
var csvFileData = titleArray.toString() + '\r\n';
let recID='',fileID='';
summaryContext.output.iterator().each(function (key, value) {
let parseSummary=JSON.parse(value);
if (key === 'error') {
recID=parseSummary.customRecInternalId;
let error=JSON.parse(value);
log.debug("error parse",parseSummary)
log.debug("error Order ID",parseSummary['order id'])
log.debug("error message",parseSummary.error.message)
csvFileData += parseSummary['order id'] + ',' +parseSummary.error.message.replace(','," ")+ '\r\n' ;
//log.debug("erooro ", value.error.message)
let fileObj = file.create({
name: 'ERROR-'+recID+'-'+Math.floor(Date.now()/1000) +'.csv',
fileType: file.Type.CSV,
folder: 5072,
contents: csvFileData
});
fileID=fileObj.save();
}
else{
recID=parseSummary.customRecInternalId;
}
return true
});
log.debug('summary Rec ID',recID);
if(recID) {
record.submitFields({
type: 'customrecord_jj_finance_import_trandate',
id: recID,
values: {
'custrecord_jj_itd_status': 'COMPLETE',
'custrecord_jj_itd_errorfile': fileID
}
});
}
var import_trandateSearchObj = search.create({
type: "customrecord_jj_finance_import_trandate",
filters:
[
["custrecord_jj_itd_status","is","PENDING"],
"AND",
["isinactive","is","F"]
],
columns:
[
search.createColumn({
name: "name",
sort: search.Sort.ASC,
label: "Name"
}),
search.createColumn({name: "internalid", label: "Internal ID"})
]
});
var searchResultCount = import_trandateSearchObj.runPaged().count;
if(searchResultCount>0) {
var scriptTask = task.create({
taskType: task.TaskType.MAP_REDUCE
});
scriptTask.scriptId = 'customscript_jj_ath2';
scriptTask.deploymentId = 'customdeploy_jj_ath2';
var scriptTaskId = scriptTask.submit();
log.debug('Called Map reduce script in summarize')
}
}catch(e){
log.debug("Summary error",e)
}
}
return {getInputData, reduce, summarize}
});