Automate order approval in NetSuite using data from Stripe's fraud detection system using http://SuiteSync.io/
/* | |
Author: <mike@suitesync.io> | |
Description: Detects if a transaction is marked as fraudulent/safe by Stripe's fraud system | |
https://dashboard.suitesync.io/docs/fraud-prevention | |
Installation: | |
1. https://system.sandbox.netsuite.com/app/common/scripting/uploadScriptFile.nl | |
2. User Event | |
3. Name: Stripe Fraud Handler | |
4. ID: _stripe_fraud_handler | |
5. After Submit: afterSubmit | |
6. Deployments: SalesOrder, Invoice, CashSale (depending on your NetSuite usage) | |
*/ | |
// Pulled from utilities | |
// https://gist.github.com/iloveitaly/db7d532e772b67f5b81d0199d094301f | |
function log(msg) { | |
nlapiLogExecution('DEBUG', msg); | |
} | |
function isEmpty(obj) { | |
return obj === undefined || obj === null || obj === ""; | |
} | |
function startsWith(str, searchString) { | |
return str.indexOf(searchString) === 0; | |
} | |
// Don't ask why SuiteScript uses 'A' and 'B' to represent the `orderstatus` | |
var NETSUITE_SALES_ORDER_PENDING_APPROVAL_STATUS = 'A'; | |
var NETSUITE_SALES_ORDER_APPROVED_STATUS = 'B'; | |
var NETSUITE_INVOICE_APPROVED_STATUS = '2'; | |
// NOTE the wrapper function `processAfterSubmit` is used to enable the logic to be | |
// easily reused in other contexts (i.e. debugging, mass update, etc) | |
function afterSubmit() { | |
var recordType = nlapiGetRecordType(); | |
var recordId = nlapiGetRecordId(); | |
processAfterSubmit(recordType, recordId); | |
} | |
function processAfterSubmit(type, internalId) { | |
var isFraudProcessed = nlapiLookupField(type, internalId, 'custbody_suitesync_fraud_processed', false); | |
if(isFraudProcessed == 'T') { | |
if(isEmpty(nlapiLookupField(type, internalId, 'custbody_suitesync_fraud_message', false))) { | |
transactionIsSafe(type, internalId); | |
} else { | |
transactionIsFraudulent(type, internalId); | |
} | |
} else { | |
log("transaction not processed for fraud"); | |
} | |
} | |
function transactionIsFraudulent(recordType, internalId) { | |
log("transaction is fradulent"); | |
var fraudMessage = nlapiLookupField(recordType, internalId, 'custbody_suitesync_fraud_message', false); | |
// NOTE startsWith is used to prevent message detection from breaking when whitespace, punctuation, etc | |
// is added to the fraud message. Note that this is a custom method that is included at the top of this script. | |
// NOTE you may not want to change how you handle fraudulent transactions based on the fraud message. | |
// this logic is provided here as an example in case you need this functionality. | |
if(startsWith(fraudMessage, 'One of your rules placed this charge in manual review')) { | |
} else if(startsWith(fraudMessage, 'Marked as risky by Stripe')) { | |
} else { | |
// additional fraud messages may be added in the future, ensure that all fraud messages are handled | |
} | |
// NOTE exactly what you do when a transaction is fraudulent is highly dependent on your specific | |
// NetSuite environment. Below are some examples of what you could do. | |
// NOTE that setting status and statusRef don't do anything, although they won't fail. | |
// the orderstatus (NOT orderStatus) is the only field that will change the status. | |
// NOTE pro-tip: use `nlapiGetFieldValue('orderstatus')` in the browser console when you have a transaction | |
// in edit mode to pull the value that NetSuite expects in SuiteScript. | |
if(recordType == 'salesorder') { | |
nlapiSubmitField(recordType, internalId, 'orderStatus', NETSUITE_SALES_ORDER_PENDING_APPROVAL_STATUS); | |
} else if(type == 'invoice') { | |
// NOTE that invoices cannot be moved from Approved => Pending Approval | |
} else if(type == 'cashsale') { | |
} | |
} | |
function transactionIsSafe(recordType, internalId) { | |
log("transaction is safe"); | |
// NOTE exactly what you do when a transaction is safe is highly dependent on your specific | |
// NetSuite environment. Below are some examples of what you could do. | |
if(recordType == 'salesorder') { | |
nlapiSubmitField(recordType, internalId, 'orderstatus', NETSUITE_SALES_ORDER_APPROVED_STATUS); | |
} else if(type == 'invoice') { | |
nlapiSubmitField(recordType, internalId, 'approvalstatus', NETSUITE_INVOICE_APPROVED_STATUS); | |
} else if(type == 'cashsale') { | |
} | |
} | |
// this condition enables us to run this script and the debugger to test with | |
// a specific transaction in NetSuite. This is helpful for script debugging/editing | |
if(nlapiGetContext().getExecutionContext() == 'debugger') { | |
processAfterSubmit('salesorder', 8931604); | |
} | |
// allows you set a breakpoint at the end of the script | |
'debug'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment