Home SuiteScript API: N/record - Part 2
Post
Cancel

SuiteScript API: N/record - Part 2

Introduction

In the last post, we looked at the basics of the N/record module in SuiteScript. We looked at loading, saving, and deleting records. We looked at getting and setting values. In this post we will look at getting and setting sublists and subrecords.

What is a Sublist?

A sublist is a lists of records, usually found in a subtab on a record. For example, Sales Orders and Item fulfillments have a sublist called item. Here we list the items that are on the sales order or item fulfillment.

Some common sublists include:

  • item (Sales Order, Item Fulfillment, Work Order, etc.)
  • line (Journal Entry)
  • component (Bom Revision)
  • expense (Bills, Invoices)

Because the methods for working will sublists depend on whether the record was loaded in standard or dynamic mode, we will look at each mode separately. The methods for standard mode also work in dynamic mode so we will start with standard mode. See this post for more information on standard and dynamic modes.

Standard Mode (and Dynamic Mode)

Getting a Sublist

Imagine our item sublist for a Sales Order looks like this:

ItemRateQuantityAmount
Item 110110
Item 220240

To get the rate field on the item sublist (item), we would use the record.getSublistValue method.

1
2
3
4
5
6
7
8
9
10
const rec = record.load({
    type: record.Type.SALES_ORDER,
    id: 123
});

const item1Rate = rec.getSublistValue({
    sublistId: 'item',
    fieldId: 'rate',
    line: 0
});

The getSublistValue method takes in an object with the following properties:

  • sublistId - The id of the sublist
  • fieldId - The id of the field on the sublist
  • line - The line number of the sublist

Suppose we want to get the whole sublist and put it in an array of objects:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
    {
        item: 'Item 1',
        rate: 10,
        quantity: 1,
        amount: 10
    },
    {
        item: 'Item 2',
        rate: 20,
        quantity: 2,
        amount: 40
    }
]

We would have to loop through the sublist and get each value. But how do we know the length of the sublist? This is where the getLineCount method comes in.

1
2
3
4
5
const rec = record.load(...);

const lineCount = rec.getLineCount({
    sublistId: 'item'
}) // 2 ;

Now we can loop through the sublist and get each value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const rec = record.load(...);

const lineCount = rec.getLineCount({sublistId: 'item'}) // 2 ;

const items = [];
for(let i = 0; i < lineCount; i++) {
    items.push({
        item: rec.getSublistValue({
            sublistId: 'item',
            fieldId: 'item',
            line: i
        }),
        rate: rec.getSublistValue({
            sublistId: 'item',
            fieldId: 'rate',
            line: i
        }),
        quantity: rec.getSublistValue({
            sublistId: 'item',
            fieldId: 'quantity',
            line: i
        }),
        amount: rec.getSublistValue({
            sublistId: 'item',
            fieldId: 'amount',
            line: i
        })
    });
}

Setting a Sublist

To set a sublist value, we use the setSublistValue method.

This method takes the same parameters as the getSublistValue method, with the addition of a value parameter.

1
2
3
4
5
6
7
8
const rec = record.load(...);

rec.setSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    line: 0,
    value: 1111
});

Where 1111 is the internal id of the item record.

Now if we are setting a new line, we would select the line number as 1 greater than the current index.

1
2
3
4
5
6
7
8
9
const rec = record.load(...);

const lineCount = rec.getLineCount({sublistId: 'item'}) // 2 ;
rec.setSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    line: lineCount,
    value: 1111
});

Remember the the line number is 0 based, so the lineCount which is 2, is the 3rd line. We can then set the next line, using lineCount + 1 as the line number.

If we try to set a line that is more than 1 greater than the current index, we will get an error.

1
2
3
4
5
6
7
8
const rec = record.load(...);

rec.setSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    line: 10,
    value: 1111
}); // Error: You have attempted an invalid sublist operation. You are either trying to access a field on a non-existent line or you are trying to add or remove lines from a static sublist.

Let’s suppose we want to add a line to the sublist in a certain position. So using our example above, we want to add a line between the first and second line.

We can use the insertLine method to do this.

1
2
3
4
5
6
7
8
9
10
11
12
13
const rec = record.load(...);

rec.insertLine({
    sublistId: 'item',
    line: 1
});

rec.setSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    line: 1,
    value: 1111
});

Removing a Sublist Line

To remove a sublist line, we use the removeLine method.

1
2
3
4
5
6
const rec = record.load(...);
rec.removeLine({
    sublistId: 'item',
    line: 1
});

If we try to remove a line that does not exist, we will get an error.

1
2
3
4
5
6
const rec = record.load(...);

rec.removeLine({
    sublistId: 'item',
    line: 10
}); // Error: You have attempted an invalid sublist operation. You are either trying to access a field on a non-existent line or you are trying to add or remove lines from a static sublist.

Dynamic Mode

In dynamic mode we have the ability to work with sublists in a manner similar to working with sublists in the UI.

This means that we will “Select” a line and then work with it and then “Commit” the line.

Selecting a Line

To select a line, we use the selectLine method.

1
2
3
4
5
const rec = record.load(...);
rec.selectLine({
    sublistId: 'item',
    line: 0
});

Now that line 0 (the first line) is selected, we can work with it using the getCurrentSublistValue and setCurrentSublistValue methods.

1
2
3
4
5
6
7
8
9
10
11
rec.setCurrentSublistValue({
    sublistId: 'item',
    fieldId: 'item',
    value: 1111
});

rec.setCurrentSublistValue({
    sublistId: 'item',
    fieldId: 'quantity',
    value: 10
});

Note that we did not have to specify the line number, since we already selected the line.

After we have set the values, we can commit the line using the commitLine method.

1
2
3
rec.commitLine({
    sublistId: 'item'
});

Now we will take a brief detour to discuss getting and setting subrecords which is a common task when working with sublists.

What is a Subrecord?

A subrecord is a record that is attached to another record. This does not include fields that you select a full record such as location or subsidiary. Subrecords are used specifically for records that store information about the main record.

Examples of subrecords include:

  • Inventory Detail
  • Landed Cost
  • Addresses

Getting a Subrecord

Subrecords are retrieved using the getSubrecord method of a loaded record.

1
2
3
4
5
6
7
8
const rec = record.load({
    type: record.Type.SALES_ORDER,
    id: 123
});

const subrec = rec.getSubrecord({
    fieldId: 'shippingaddress'
});

This will get the shipping address subrecord for the sales order.

We now are able to query the subrecord for information.

1
2
3
4
5
const rec = record.load(...)
const subrec = rec.getSubrecord({ fieldId: 'shippingaddress' });
const shipcity = subrec.getValue({ fieldId: 'city' });
const shipstate = subrec.getValue({ fieldId: 'state' });

We can also set values on the subrecord.

1
2
3
4
const rec = record.load(...)
const subrec = rec.getSubrecord({ fieldId: 'shippingaddress' });
subrec.setValue({ fieldId: 'city', value: 'New York' });
subrec.setValue({ fieldId: 'state', value: 'NY' });

Subrecords do not have to saved; they are saved when the parent record is saved.

Some subrecords, such as the inventory detail subrecord, have their own sublists.

1
2
3
4
5
6
7
8
const rec = record.load(...) // Assembly Build
const subrec = rec.getSubrecord({ fieldId: 'inventorydetail' });
subrec.setSublistValue({
    sublistId: 'inventoryassignment',
    fieldId: 'quantity',
    line: 0,
    value: 10
});

Subrecords on Sublists

Many sublists have subrecords attached to them.

The method getSublistSubrecord is used to get the subrecord for a sublist line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const rec = record.load(...) // Assembly Build
const subrec = rec.getSublistSubrecord({
    sublistId: 'item',
    fieldId: 'inventorydetail',
    line: 0
});

subrec.setSublistValue({
    sublistId: 'inventoryassignment',
    fieldId: 'quantity',
    line: 0,
    value: 10
});

For dynamic mode, we can use the selectLine method to select a sublist line and then use the getCurrentSublistSubrecord method to get the subrecord for the selected line.

1
2
3
4
5
6
7
8
9
10
11
12
const rec = record.load(..., isDynamic: true) // Assembly Build

rec.selectLine({
    sublistId: 'item',
    line: 0
});

const subrec = rec.getCurrentSublistSubrecord({
    sublistId: 'item',
    fieldId: 'inventorydetail'
});

Note that subrecords are always loaded in the mode of the parent record. If the parent record is loaded in dynamic mode, then the subrecord will be loaded in dynamic mode and you’ll be able to use methods such as setCurrentSublistValue.

Conclusion

In this post we looked at sublists and subrecords.

This should wrap up our discussion of the N/record api. As usual, you should visit the help documentation for a complete overview of the record module.

This post is licensed under CC BY 4.0 by the author.

Implementation: Item Types

SuiteScript API: N/record - Part 1