/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define([‘N/record’, ‘N/ui/serverWidget’, ‘N/search’, ‘N/query’, ‘N/runtime’],
(record, serverWidget, search, query, runtime) => {
/**
* Entry point for the Suitelet
* @param {Object} context – The context of the Suitelet request
*/
const onRequest = (context) => {
try {
var request = context.request;
// Get the userId from the query parameter
var userId = request.parameters.userId;
log.debug(“Received userId”, userId);
if (context.request.method === ‘GET’) {
log.debug(“currentUserId”, userId);
let currentUserId = userId;
if (!currentUserId) {
let currentUserId = getCurrentUserId();
log.debug(“currentUserId%%%%”, currentUserId);
let currentUserRole = getCurrentUserRole();
log.debug(“currentUserRole”, currentUserRole);
let isAuthorize = isAuthorizedUser(currentUserRole);
log.debug(“isAuthorize”, isAuthorize);
// Check if the user is either an Admin or Elevated Outside Sales Rep
if (!isAuthorize) {
log.debug(“Unauthorized Access”, “User does not have permission to view the report”);
context.response.write(“You don’t have permission to view the report.”); // Using write instead of writePage
return; // Exit if the user doesn’t have the correct role
}
let form = createForm();
let transactionResults = getTransactionData(currentUserId);
let salesRepIds = getSalesRepIds(transactionResults);
if (salesRepIds.length === 0) {
log.debug(“DFDDCDSCSD”, “dsfsdfds”);
context.response.writePage(form);
return;
}
let quotaResults = getQuotaData(salesRepIds);
log.debug(“quotaResults”, quotaResults);
populateSublist(form, transactionResults, quotaResults);
context.response.writePage(form);
}
else {
let currentUserRole = getCurrentUserRole();
log.debug(“currentUserRole”, currentUserRole);
let isAuthorize = isAuthorizedUser(currentUserRole);
log.debug(“isAuthorize”, isAuthorize);
// Check if the user is either an Admin or Elevated Outside Sales Rep
if (!isAuthorize) {
log.debug(“Unauthorized Access”, “User does not have permission to view the report”);
context.response.write(“You don’t have permission to view the report.”); // Using write instead of writePage
return; // Exit if the user doesn’t have the correct role
}
let form = createForm();
let transactionResults = getTransactionData(currentUserId);
let salesRepIds = getSalesRepIds(transactionResults);
if (salesRepIds.length === 0) {
log.debug(“DFDDCDSCSD”, “dsfsdfds”);
context.response.writePage(form);
return;
}
let quotaResults = getQuotaData(salesRepIds);
log.debug(“quotaResults”, quotaResults);
populateSublist(form, transactionResults, quotaResults);
context.response.writePage(form);
}
}
} catch (e) {
logError(‘Error Processing Suitelet Request’, e);
}
};
/**
* Checks if the current user is authorized based on their role.
*
* @param {string} currentUserRole – The internal ID of the user’s role.
* @returns {boolean} True if the user is authorized, false otherwise.
*/
const isAuthorizedUser = (currentUserRole) => {
try {
// Define the role IDs for Admin and Elevated Outside Sales Rep (replace with actual IDs)
const ADMIN_ROLE_ID = 3; // Example Admin role ID
const ELEVATE_OUTSIDE_SALES_REP = 1015; // Example Elevated Outside Sales Rep role ID
const portalview = 31;
if (currentUserRole === ADMIN_ROLE_ID || currentUserRole === ELEVATE_OUTSIDE_SALES_REP || currentUserRole === portalview) {
log.debug(“currentUserRole”, currentUserRole);
return true
}
else {
return false;
}
} catch (e) {
logError(‘Error checking user authorization’, e);
return false; // Default to false if there’s an error
}
};
/**
* Retrieves the current user’s role.
*
* @returns {string} The internal ID of the current user’s role.
*/
const getCurrentUserRole = () => {
try {
return runtime.getCurrentUser().role;
} catch (e) {
logError(‘Error fetching user role’, e);
return null;
}
};
/**
* Get the current user ID
* @returns {number} The ID of the current user
*/
const getCurrentUserId = () => {
try {
let currentUser = runtime.getCurrentUser();
log.debug(“currentUser”, currentUser);
return currentUser.id;
} catch (e) {
logError(‘Error getting current user ID’, e);
}
};
/**
* Create the Suitelet form
* @returns {serverWidget.Form} The created form
*/
const createForm = () => {
try {
let form = serverWidget.createForm({
title: ‘Sales vs. Quota this month’
});
let sublist = form.addSublist({
id: ‘custpage_quota_sublist’,
type: serverWidget.SublistType.LIST,
label: ‘Sales vs. Quota this month’
});
// Add fields to the sublist
sublist.addField({ id: ‘custpage_supervisor’, type: serverWidget.FieldType.TEXT, label: ‘Supervisor’ });
sublist.addField({ id: ‘custpage_sales_rep’, type: serverWidget.FieldType.TEXT, label: ‘Sales Rep’ });
sublist.addField({ id: ‘custpage_quota’, type: serverWidget.FieldType.CURRENCY, label: ‘Quota’ });
sublist.addField({ id: ‘custpage_actual_sales’, type: serverWidget.FieldType.CURRENCY, label: ‘Actual Sales’ });
sublist.addField({ id: ‘custpage_actual_quota_variance’, type: serverWidget.FieldType.PERCENT, label: ‘Actual/Quota Variance (%)’ });
sublist.addField({ id: ‘custpage_formula’, type: serverWidget.FieldType.CURRENCY, label: ‘Formula (Actual – Quota)’ });
return form;
} catch (e) {
logError(‘Error creating form’, e);
}
};
/**
* Get transaction data for the current user
* @param {number} currentUserId – The ID of the current user
* @returns {Array<Object>} The transaction results
*/
const getTransactionData = (currentUserId) => {
try {
let transactionSearch = search.create({
type: “transaction”,
filters: [
[“type”, “anyof”, “CustCred”, “CashSale”, “CustInvc”],
“AND”,
[“trandate”, “within”, “thismonth”],
“AND”,
[“mainline”, “is”, “F”],
“AND”,
[“taxline”, “is”, “F”],
“AND”,
[“shipping”, “is”, “F”],
“AND”,
[“partner”, “anyof”, currentUserId]
],
columns: [
search.createColumn({ name: “supervisor”, join: “salesRep”, summary: “GROUP” }),
search.createColumn({ name: “salesrep”, summary: “GROUP” }),
search.createColumn({ name: “amount”, summary: “SUM” })
]
});
let results = [];
transactionSearch.run().each(result => {
//let supervisor = result.getText({ name: ‘supervisor’, join: ‘salesRep’, summary: ‘GROUP’ });
results.push({
supervisor: result.getText({ name: ‘supervisor’, join: ‘salesRep’, summary: ‘GROUP’ }),
salesRep: result.getText({ name: ‘salesrep’, summary: ‘GROUP’ }),
salesRepId: result.getValue({ name: ‘salesrep’, summary: ‘GROUP’ }),
actualSales: parseFloat(result.getValue({ name: ‘amount’, summary: ‘SUM’ }))
});
return true;
});
return results;
} catch (e) {
logError(‘Error fetching transaction data’, e);
}
};
/**
* Extract sales representative IDs from transaction results
* @param {Array<Object>} transactionResults – The transaction data
* @returns {Array<string>} List of sales representative IDs
*/
const getSalesRepIds = (transactionResults) => {
try {
return transactionResults.map(result => result.salesRepId).filter(Boolean);
} catch (e) {
logError(‘Error extracting sales rep IDs’, e);
}
};
/**
* Get quota data for the sales representatives
* @param {Array<string>} salesRepIds – List of sales representative IDs
* @returns {Array<Object>} Quota results
*/
const getQuotaData = (salesRepIds) => {
try {
let salesRepIdsString = salesRepIds.map(id => `’${id}‘`).join(‘,’);
let sql = `
SELECT
employee.ID AS entityId,
BUILTIN.DF(QUOTA.entity) AS entity,
QUOTA.mamount AS mamount
FROM
QUOTA
INNER JOIN employee ON QUOTA.entity = employee.ID
WHERE
QUOTA.DATE BETWEEN BUILTIN.RELATIVE_RANGES(‘TM’, ‘START’, ‘DATETIME_AS_DATE’)
AND BUILTIN.RELATIVE_RANGES(‘TM’, ‘END’, ‘DATETIME_AS_DATE’)
AND QUOTA.entity IN (${salesRepIdsString})
`;
let resultSet = query.runSuiteQL({ query: sql });
return resultSet.results || [];
} catch (e) {
logError(‘Error fetching quota data’, e);
}
};
/**
* Populate the sublist with transaction and quota data
* @param {serverWidget.Form} form – The Suitelet form
* @param {Array<Object>} transactionResults – The transaction data
* @param {Array<Object>} quotaResults – The quota data
*/
const populateSublist = (form, transactionResults, quotaResults) => {
try {
let sublist = form.getSublist({ id: ‘custpage_quota_sublist’ });
quotaResults.forEach((quotaResult, i) => {
let entityId = quotaResult.values[0];
let quotaAmount = parseFloat(quotaResult.values[2]);
let actualData = transactionResults.find(t => t.salesRepId == entityId);
if (actualData) {
let actualSales = actualData.actualSales;
// Check if quotaAmount is valid and greater than zero before calculating variance
let variance = 0;
if (quotaAmount > 0) {
variance = (actualSales / quotaAmount) * 100;
}
// If actualSales or quotaAmount is not a number, set default values to avoid NaN
let formula = actualSales – (isNaN(quotaAmount) ? 0 : quotaAmount);
// Setting values with validation to avoid NaN or invalid field errors
sublist.setSublistValue({
id: ‘custpage_supervisor’,
line: i,
value: actualData.supervisor || ‘No Supervisor’
});
sublist.setSublistValue({
id: ‘custpage_sales_rep’,
line: i,
value: actualData.salesRep || ”
});
sublist.setSublistValue({
id: ‘custpage_quota’,
line: i,
value: isNaN(quotaAmount) ? ‘0.00’ : quotaAmount.toFixed(2)
});
sublist.setSublistValue({
id: ‘custpage_actual_sales’,
line: i,
value: isNaN(actualSales) ? ‘0.00’ : actualSales.toFixed(2)
});
sublist.setSublistValue({
id: ‘custpage_actual_quota_variance’,
line: i,
value: isNaN(variance) ? ‘0.00’ : variance.toFixed(2)
});
sublist.setSublistValue({
id: ‘custpage_formula’,
line: i,
value: isNaN(formula) ? ‘0.00’ : formula.toFixed(2)
});
}
});
} catch (e) {
logError(‘Error populating sublist’, e);
}
};
/**
* Log an error message
* @param {string} title – The title of the error log
* @param {Error} error – The error object
*/
const logError = (title, error) => {
log.debug({ title, details: error });
};
return { onRequest };
});