REQUIREMENT
The requirement is to delete a few subscription records created in NS. The subscription records are of different statuses- Draft, Closed, Active, and Pending Activation. The subscriptions include change orders associated with them. Develop a script to delete subscription records through scripting.
SOLUTION
The requirement can be achieved by using the map /reduce script. First, need to delete all subscriptions change Orders, delete all revenue elements, and revenue arrangements and change all-subscription lines status to draft, then delete the related record and subscription record.
We cannot delete the subscription record whose subscription line is revised (Revision)or renew. Because it has other dependent records
/**
* @NApiVersion 2.1
* @NScriptType MapReduceScript
*/
define(['N/record', 'N/search'],
/**
* @param{record} record
* @param{search} search
*/
(record, search) => {
const getInputData = (inputContext) => {
try {
let searchResults = getSubscriptionLine();
log.debug("searchResults", searchResults)
return searchResults
} catch (e) {
log.debug("error@getInputData", e)
}
}
const reduce = (reduceContext) => {
try {
let dataObj = JSON.parse(reduceContext.values[0])
let filterConfigArray = []
let columnConfigArray = []
if (checkForParameter(dataObj.id)) {
let checkChangeOrderStatus = checkSubChangeOrderStatus(dataObj.id)
if (checkChangeOrderStatus === true) {
let subRec = record.load({
type: "subscription",
id: dataObj.id,
isDynamic: true,
})
let status = dataObj.values.status[0].value
if (status == "DRAFT") {
subRevenueArranges(dataObj.id, filterConfigArray, columnConfigArray)
subCharges(dataObj.id, filterConfigArray, columnConfigArray)
} else {
subChangeOrders(dataObj.id, filterConfigArray, columnConfigArray)
subLines(dataObj.id, filterConfigArray, columnConfigArray, subRec)
subRevenueArranges(dataObj.id, filterConfigArray, columnConfigArray)
subCharges(dataObj.id, filterConfigArray, columnConfigArray)
}
let deletedSubscriptionRecordId = record.delete({
type: "subscription",
id: dataObj.id
})
log.debug("deletedSubscriptionRecordId deleted", deletedSubscriptionRecordId)
}
}
} catch (e) {
log.debug("error@reduce", e)
}
}
const summarize = (summaryContext) => {
}
/**
* This function is executed to fetch the subscription records.
* @returns {Result[]|*[]} -Returns the search result or empty array.
*/
function getSubscriptionLine() {
try {
var subscriptionSearchObj = search.create({
type: "subscription",
filters:
[
"NOT",
["transaction.type", "anyof", "CustInvc"],
"AND",
["internalid", "anyof", "1201"]
],
columns:
[
search.createColumn({name: "internalid", label: "Internal ID"}),
search.createColumn({name: "status", label: "Status"})
]
});
let searchRes = subscriptionSearchObj.run().getRange({
start: 0,
end: 1000
})
if (searchRes.length > 0) {
return searchRes
} else {
return []
}
} catch (e) {
log.debug("error@getSubscriptionLine", e)
}
}
/**
* This function checks the subscription change orders of the subscription records Renew with status -Active and Renewal Method- Extend Existing Subscriptions
* @param intId -Internal Id of the subscription records.
* @returns {boolean} -Returns true if the record does not have the subscription change orders Renew with status -Active and Renewal Method- Extend Existing Subscriptions and returns false otherwise.
*/
function checkSubChangeOrderStatus(intId) {
try {
var subscriptionSearchObj = search.create({
type: "subscription",
filters:
[
["internalid", "anyof", intId],
"AND",
[[["subscriptionchangeorder.action", "anyof", "RENEW"], "AND", ["subscriptionchangeorder.status", "anyof", "ACTIVE"]], "OR", [["subscriptionchangeorder.renewalmethod", "anyof", "EXTEND_EXISTING_SUBSCRIPTION"]]],
],
columns:
[
search.createColumn({name: "internalid", label: "Internal ID"})
]
});
let searchRes = subscriptionSearchObj.run().getRange({
start: 0,
end: 1000
})
log.debug("searchRes", searchRes)
if (searchRes.length < 1) {
return true
} else {
return false
}
} catch (e) {
log.debug("error@checkSubChangeOrderStatus", e)
}
}
function checkForParameter(parameter) {
if (parameter !== "" && parameter !== null && parameter !== undefined && parameter !== false && parameter !== "null" && parameter !== "undefined" && parameter !== " " && parameter !== 'false') {
return true;
}
}
/**
* Defines the function that execute a search function that will
* @param intId - Internal Id of the subscription record
* @param filterConfig - Filter array of the search used
* @param columnConfig - Columns of the search used
* @returns {Result[]|*[]} - Returns either the search result or an empty array
*/
function checkRecordExist(intId, filterConfig, columnConfig) {
try {
let subscriptionSearchObj = search.create({
type: "subscription",
filters:
[
["internalid", "anyof", intId],
...filterConfig
],
columns:
[
...columnConfig
]
});
let searchRes = subscriptionSearchObj.run().getRange({
start: 0,
end: 1000
})
log.debug("searchRes", searchRes.length)
if (searchRes.length > 0) {
return searchRes
} else {
return []
}
} catch (e) {
log.debug("error@checkRecordExist", e)
}
}
/**
* The function that execute a search to fetch and delete the change orders of the subscription record.
* @param intId - Internal Id of the subscription record
* @param filterConfig - Filter array of the search used
* @param columnConfig - Columns of the search used
* @returns {*}
*/
function subChangeOrders(intId, filterConfigArray, columnConfigArray) {
try {
filterConfigArray = []
columnConfigArray = []
filterConfigArray.push("AND",
["subscriptionchangeorder.status", "noneof", "VOIDED"])
columnConfigArray.push(search.createColumn({
name: "internalid",
join: "subscriptionChangeOrder",
label: "Internal ID"
}),)
columnConfigArray.push(search.createColumn({
name: "status",
join: "subscriptionChangeOrder",
label: "Status"
}))
let subChangeOrder = checkRecordExist(intId, filterConfigArray, columnConfigArray)
if (subChangeOrder.length > 0) {
for (let changeOrderNo = 0; changeOrderNo < subChangeOrder.length; changeOrderNo++) {
let subChangeOrderId = subChangeOrder[changeOrderNo].getValue({
name: "internalid",
join: "subscriptionChangeOrder",
label: "Internal ID"
})
if (checkForParameter(subChangeOrderId)) {
let subChangeOrderRec = record.delete({
type: "subscriptionChangeOrder",
id: subChangeOrderId
})
log.debug("subChangeOrderRec deleted", subChangeOrderRec)
}
}
}
} catch (e) {
log.debug("error@subChangeOrders", e)
}
}
function subLines(intId, filterConfigArray, columnConfigArray, subRec) {
try {
filterConfigArray = []
columnConfigArray = []
columnConfigArray.push(search.createColumn({
name: "internalid",
join: "subscriptionLine",
label: "Internal ID"
}),)
columnConfigArray.push(search.createColumn({
name: "status",
join: "subscriptionLine",
label: "Status"
}),)
columnConfigArray.push(search.createColumn({
name: "include",
join: "subscriptionLine",
label: "Include"
})
)
let subLineRec = checkRecordExist(intId, filterConfigArray, columnConfigArray)
for (let subLine = 0; subLine < subLineRec.length; subLine++) {
let lineNum = subRec.selectLine({
sublistId: 'subscriptionline',
line: subLine
});
let isincluded = subRec.getCurrentSublistValue({
sublistId: 'subscriptionline',
fieldId: 'isincluded',
})
if (isincluded !== true) {
subRec.setCurrentSublistValue({
sublistId: 'subscriptionline',
fieldId: 'isincluded',
value: true,
});
subRec.commitLine({
sublistId: 'subscriptionline'
})
} else if ((isincluded === true) && (subRec.getCurrentSublistValue({
sublistId: 'subscriptionline',
fieldId: 'status',
}) != 'DRAFT')) {
subRec.setCurrentSublistValue({
sublistId: 'subscriptionline',
fieldId: 'status',
value: 'DRAFT'
})
subRec.commitLine({
sublistId: 'subscriptionline'
})
}
}
let recordId = subRec.save({
ignoreMandatoryFields: true,
enableSourcing: true
})
} catch (e) {
log.debug("error@subLines", e)
}
}
/**
* The function is executed to fetch the revenue elements of the subscription record.
* The revenue arrangement of the the revenue element will be deleted and correspondingly the revenue element will be removed from the subscription record.
* @param intId - Internal Id of the subscription record
* @param filterConfig - Filter array of the search used
* @param columnConfig - Columns of the search used
*/
function subRevenueArranges(intId, filterConfigArray, columnConfigArray) {
try {
filterConfigArray = []
columnConfigArray = []
columnConfigArray.push(search.createColumn({
name: "revenuearrangement",
join: "revenueElement",
summary: "GROUP",
sort: search.Sort.ASC,
label: "Revenue Arrangement"
}))
let revenueArrangements = checkRecordExist(intId, filterConfigArray, columnConfigArray)
if (revenueArrangements.length > 0) {
for (let revArrangeNo = 0; revArrangeNo < revenueArrangements.length; revArrangeNo++) {
let revArrangeId = revenueArrangements[revArrangeNo].getValue({
name: "revenuearrangement",
join: "revenueElement",
summary: "GROUP",
sort: search.Sort.ASC,
label: "Revenue Arrangement"
})
if (checkForParameter(revArrangeId)) {
let revRecId = record.delete({
type: "revenuearrangement",
id: revArrangeId
})
log.debug("revenue arrange Record deleted", revRecId)
}
}
}
} catch (e) {
log.debug("error@subRevenueArranges", e)
}
}
/**
* The function is executed to delete the charges from the subscription record.
* @param intId - Internal Id of the subscription record
* @param filterConfig - Filter array of the search used
* @param columnConfig - Columns of the search used
*/
function subCharges(intId, filterConfigArray, columnConfigArray) {
try {
filterConfigArray = []
columnConfigArray = []
columnConfigArray.push(search.createColumn({
name: "internalid",
join: "charge",
label: "Internal ID"
}))
let chargeRecord = checkRecordExist(intId, filterConfigArray, columnConfigArray)
//let chargeRecord = checkCharges(intId)
if (chargeRecord.length > 0) {
for (let chargeNo = 0; chargeNo < chargeRecord.length; chargeNo++) {
let chargeRecId = chargeRecord[chargeNo].getValue({
name: "internalid",
join: "charge",
label: "Internal ID"
})
if (checkForParameter(chargeRecId)) {
let delChrgeRec = record.delete({
type: "charge",
id: chargeRecId
})
log.debug("chargeRec Deleted", delChrgeRec)
}
}
}
} catch (e) {
log.debug("error@subCharges", e)
}
}
return {getInputData, reduce, summarize}
});