πΌ Business Context
In this scenario, the Cost Center is not a standard field but a Custom Segment created through Customization β Lists, Records & Fields β Segments.
This segment is visible on:
- The transaction Header, and
- Each Line Item sublist.
Your requirement remains the same:
Whenever a user selects or changes a Cost Center segment, the corresponding Department and Class should automatically populate on that line (or all lines if changed at the header).
π― Updated Functional Rules
- When the Cost Center (Custom Segment) on Header changes β All lines get Department and Class values based on the mapping.
- When a Cost Center (Custom Segment) on a line changes β Only that line updates.
- During Edit β Header changes update all lines unless line-level cost centers are explicitly changed.
- The script should support:
- Sales Orders
- Purchase Orders
- Journal Entries
- The mapping of Cost Center β Department β Class remains in a custom mapping record.
π§ Technical Approach
Because Cost Center is a custom segment, its field ID follows this pattern:
cseg_<segmentid>
For example, if your custom segment is named βCost Centerβ, its internal ID might be:
cseg_cost_center
You can confirm it by inspecting a record in the browser or using the Field Explorer in the script editor.
Your script will reference this segmentβs field ID on both header and line levels.
π§© Updated Script Logic
Below is the revised and human-readable SuiteScript 2.1 code to handle custom segment fields.
Client Script (Real-Time UI Updates)
/**
* @NApiVersion 2.1
* @NScriptType ClientScript
* @Author The NetSuite Pro
* @Description Auto-populates Department and Class based on Custom Segment (Cost Center)
*/
define(['N/search'], (search) => {
// Replace with your segment field ID
const SEGMENT_FIELD_ID = 'cseg_cost_center';
function fieldChanged(context) {
const rec = context.currentRecord;
const fieldId = context.fieldId;
// Header-level change
if (fieldId === SEGMENT_FIELD_ID) {
const costCenter = rec.getValue(SEGMENT_FIELD_ID);
if (!costCenter) return;
const mapping = getCostCenterMapping(costCenter);
if (!mapping) return;
const lineCount = rec.getLineCount({ sublistId: 'item' });
for (let i = 0; i < lineCount; i++) {
rec.selectLine({ sublistId: 'item', line: i });
rec.setCurrentSublistValue({ sublistId: 'item', fieldId: 'department', value: mapping.department });
rec.setCurrentSublistValue({ sublistId: 'item', fieldId: 'class', value: mapping.class });
rec.commitLine({ sublistId: 'item' });
}
}
// Line-level change (segment field on item line)
if (fieldId === SEGMENT_FIELD_ID) {
const costCenter = rec.getCurrentSublistValue({ sublistId: 'item', fieldId: SEGMENT_FIELD_ID });
if (!costCenter) return;
const mapping = getCostCenterMapping(costCenter);
if (mapping) {
rec.setCurrentSublistValue({ sublistId: 'item', fieldId: 'department', value: mapping.department });
rec.setCurrentSublistValue({ sublistId: 'item', fieldId: 'class', value: mapping.class });
}
}
}
function getCostCenterMapping(costCenterId) {
const results = search.create({
type: 'customrecord_cost_center_mapping',
filters: [['custrecord_cost_center', 'is', costCenterId]],
columns: ['custrecord_cost_center_dept', 'custrecord_cost_center_class']
}).run().getRange({ start: 0, end: 1 });
if (results.length > 0) {
return {
department: results[0].getValue('custrecord_cost_center_dept'),
class: results[0].getValue('custrecord_cost_center_class')
};
}
return null;
}
return { fieldChanged };
});
User Event Script (Server-Side / Integration Safety)
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
* @Description Ensures Department and Class are populated per Custom Segment (Cost Center)
*/
define(['N/record', 'N/search', 'N/log'], (record, search, log) => {
const SEGMENT_FIELD_ID = 'cseg_cost_center';
function beforeSubmit(context) {
const rec = context.newRecord;
const headerCostCenter = rec.getValue(SEGMENT_FIELD_ID);
const lineCount = rec.getLineCount({ sublistId: 'item' });
for (let i = 0; i < lineCount; i++) {
let lineCostCenter = rec.getSublistValue({
sublistId: 'item',
fieldId: SEGMENT_FIELD_ID,
line: i
});
const effectiveCostCenter = lineCostCenter || headerCostCenter;
if (!effectiveCostCenter) continue;
const mapping = getMapping(effectiveCostCenter);
if (!mapping) continue;
rec.setSublistValue({
sublistId: 'item',
fieldId: 'department',
line: i,
value: mapping.department
});
rec.setSublistValue({
sublistId: 'item',
fieldId: 'class',
line: i,
value: mapping.class
});
}
}
function getMapping(costCenterId) {
const results = search.create({
type: 'customrecord_cost_center_mapping',
filters: [['custrecord_cost_center', 'is', costCenterId]],
columns: ['custrecord_cost_center_dept', 'custrecord_cost_center_class']
}).run().getRange({ start: 0, end: 1 });
if (results.length) {
return {
department: results[0].getValue('custrecord_cost_center_dept'),
class: results[0].getValue('custrecord_cost_center_class')
};
}
return null;
}
return { beforeSubmit };
});
π§© Technical Highlights
| Area | Implementation |
|---|---|
| Segment Handling | References cseg_cost_center on both header and lines |
| Mapping Source | Custom record customrecord_cost_center_mapping |
| Supported Transactions | Sales Order, Purchase Order, Journal Entry |
| Client Script | Handles real-time updates in the UI |
| User Event Script | Ensures accuracy for imports and back-end operations |
| Deployment | beforeSubmit event for backend + fieldChanged event for UI |
β Benefits
| Benefit | Description |
|---|---|
| Accuracy | Ensures consistent financial classification |
| Real-Time Updates | Updates fields as soon as Cost Center changes |
| Integration Safe | Works for scripts, CSVs, and SuiteTalk |
| Auditability | Mapping stored in one central record |
| Configurable | Supports different cost center logic per subsidiary |
π Example Summary
This automation is especially powerful for companies using Custom Segments to track financial dimensions like Cost Center, Division, or Profit Center.
It keeps your Department and Class fields aligned with the selected segment, ensuring accurate reporting and saving your accounting team hours of manual data entry every month.