NetSuite Restlet - USER_ERROR - netsuite

I am creating this script to write the invoice in NetSuite. However, when I send the data this error appears: "The approval status field should only be used when the approval routing preference is selected."
PS: in the interface the same error occurs when trying to save.
Can you help me? Here's the code:
/**
* #NApiVersion 2.x
* #NScriptType restlet
* #author Adriano Barbosa
* #since 2019.2
*/
define(['N/record', 'N/file', 'N/log', 'N/search'], function (record, file, log, search) {
function vpc_contas_receber(context) {
if ( context.cnpj_forn ) {
var id_forn;
search.create({ type: "customer",
filters: [
[ "custentity_enl_cnpjcpf", "is", context.cnpj_forn ]
],
columns: [
search.createColumn({ name: "internalid", label: "ID interna" })
]
}).run().each(function(result) {
id_forn = result.id;
return true;
});
if ( !id_forn ) {
log.debug({ title: 'Erro', details: 'Fornecedor ' + context.cnpj_forn + ' não localizado!' });
return { status: 'Erro', mensagem: 'Fornecedor ' + context.cnpj_forn + ' não localizado!' }
} else if ( context.nf ) {
var id_nf_existe, nf_existe, num_fat;
search.create({ type: "invoice",
filters: [
[ "type", "anyof", "CustInvc" ], "AND",
[ "custbody_enl_fiscaldocnumber", "is", context.nf ]
],
columns: [
search.createColumn({ name: "custbody_enl_fiscaldocnumber", label: "Número da Nota Fiscal" }),
search.createColumn({ name: "formulatext", formula: "SUBSTR({tranid}, 0)", label: "nº fatura" })
]
}).run().each(function(result) {
id_nf_existe = result.id;
nf_existe = result.getValue({ name: 'custbody_enl_fiscaldocnumber' });
num_fat = result.getValue({ name: 'formulatext' });
});
if ( nf_existe ) {
log.debug({ title: 'NF ' + nf_existe + ' já cadastrada!', details: 'VPC: ' + id_nf_existe + '; ' + 'Nº Fatura: ' + num_fat });
return {
status: 'NF ' + nf_existe + ' já cadastrada!',
mensagem: 'VPC: ' + id_nf_existe + '; ' + 'Nº Fatura: ' + num_fat
}
} else {
vpc = record.create({ type: 'invoice', isDynamic: true })
.setValue({ fieldId: 'entity', value: id_forn })
.setValue({ fieldId: 'memo', value: context.obs })
.setValue({ fieldId: 'location', value: 1 })
.selectNewLine({ sublistId: 'item' })
.setCurrentSublistValue({ sublistId: 'item', fieldId: 'item', value: 27901 })
.setCurrentSublistValue({ sublistId: 'item', fieldId: 'rate', value: context.valor })
.commitLine({ sublistId: 'item' })/*
.setValue({ fieldId: 'custbody_rsc_dtvencboleto', value: new Date(context.venc_blt) })*/
.setValue({ fieldId: 'custbody_enl_operationtypeid', value: 15 })
.setValue({ fieldId: 'custbody_enl_order_documenttype', value: 7 })
.setValue({ fieldId: 'custbody_enl_fiscaldocnumber', value: context.nf })/*
.save({ enableSourcing: true, ignoreMandatoryFields: true })*/
if ( context.venc_blt ) {
var venc_blt = new Date(context.venc_blt);
venc_blt.setDate(venc_blt.getDate());
vpc.setValue({ fieldId: 'custbody_rsc_dtvencboleto', value: venc_blt });
}
var id_vpc = vpc.save({ enableSourcing: true, ignoreMandatoryFields: true });
try {
var bodyObject = {};
var load_id_vpc = record.load({ type: 'invoice', id: id_vpc });
bodyObject['id_vpc'] = id_vpc;
bodyObject['doc_vpc'] = load_id_vpc.getValue({ fieldId: 'tranid' });
bodyObject['memo'] = load_id_vpc.getValue({ fieldId: 'memo' }) || '';
bodyObject['valor'] = load_id_vpc.getSublistValue({ sublistId: 'item', fieldId: 'rate', line: 0 }).toFixed(2);
bodyObject['nf'] = load_id_vpc.getValue({ fieldId: 'custbody_enl_fiscaldocnumber' });
bodyObject['venc_blt'] = load_id_vpc.getValue({ fieldId: 'custbody_rsc_dtvencboleto' });
log.debug({ title: 'VPC["Contas a Receber"] cadastrado com sucesso!', details: bodyObject });
return { 'status': 'Sucesso!', 'infoVPC': bodyObject }
} catch (e) {
log.debug({ title: 'Erro', details: e });
return { status: 'Erro!', mensagem: e }
}
}
}
}
// forn = search.create({ type: "vendor",
// filters: [
// [ "custentity_enl_cnpjcpf", "is", context.fornecedor ]
// ],
// columns: [
// search.createColumn({ name: "internalid", label: "ID interna" })
// ]
// }).run().getRange({ start: 0, end: 1 })
}
return { 'post': vpc_contas_receber }
});

As the message indicates:
to use the Approval Status field, you must activate Approval Routing for invoices.
To do so, go to Setup -> Accounting -> Accounting Preferences -> Tab "Approval Routing" and check the Transactions(s) on which you want to manage approvals. This will make the "Approval Status" available for use.

Related

NetSuite Script 2.0

I am trying to create a payment record from invoice record with following code.
/**
*#NApiVersion 2.0
*#NScriptType mapreducescript
*#NModuleScope SameAccount
*/
define(
[
'N/log',
'N/error',
'N/record',
],
(record,log) => {
function invoice() {
var invRec = record.transform({
fromType: record.Type.INVOICE,
fromId: 44701349,
toType: record.Type.PAYMENT,
isDynamic: true,
defaultValues: { customform: 12 }
});
invRec.setValue({
fieldId: 'undepfunds',
value: 'Return Magic Fix Account (Inactive FY22 P04)',
ignoreFieldChange: true
});
invRec.setValue({
fieldId: 'memo',
value: 'Rounding Written Off',
ignoreFieldChange: true
});
return{
invRec
}
}
return {
record: invoice
};
});
I tried to run it in script debugger but getting

How can I use a Restlet to transform a NetSuite Purchase Order to an Item Receipt

I am trying to transform a PO into an Item Receipt using a Restlet accessed through a rest api call.
So I have the following Restlet script which I based on the NetSuite example.
/**
*#NApiVersion 2.x
*#NScriptType Restlet
*/
define(['N/record', 'N/error'],
function(record, error) {
function _get(context) {
transformPurchaseOrder(context);
}
function transformPurchaseOrder(context) {
const fromRecord = 'purchaseorder';
const fromId = context.poId;
const toRecord = 'itemreceipt';
const trecord = record.transform({
fromType: fromRecord,
fromId: fromId,
toType: toRecord,
});
trecord.setSublistValue({
sublistId: 'item',
fieldId: 'quantity',
line: 1,
value: '2'
});
const idl = trecord.save({
enableSourcing: true
});
}
return {
get: _get,
}
});
But when I run it and pass in the PO id, I get...
error: {
code: 'UNEXPECTED_ERROR',
message: '{"type":"error.SuiteScriptError","name":"UNEXPECTED_ERROR","message":null,"stack":["anonymous(N/serverRecordService)","transformPurchaseOrder(/SuiteScripts/Integration/po_to_item_receipt.js:21)","_get(/SuiteScripts/Integration/po_to_item_receipt.js:8)"],"cause":{"type":"internal error","code":"UNEXPECTED_ERROR","details":null,"userEvent":null,"stackTrace":["anonymous(N/serverRecordService)","transformPurchaseOrder(/SuiteScripts/Integration/po_to_item_receipt.js:21)","_get(/SuiteScripts/Integration/po_to_item_receipt.js:8)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}'
}
If I remove trecord.setSublistValue, and run it again, I get the following error.
{
error: {
code: 'USER_ERROR',
message: '{"type":"error.SuiteScriptError","name":"USER_ERROR","message":"Please configure the inventory detail in line 1 of the item list.","stack":["anonymous(N/serverRecordService)","transformPurchaseOrder(/SuiteScripts/Integration/po_to_item_receipt.js:21)","_get(/SuiteScripts/Integration/po_to_item_receipt.js:8)"],"cause":{"type":"internal error","code":"USER_ERROR","details":"Please configure the inventory detail in line 1 of the item list.","userEvent":null,"stackTrace":["anonymous(N/serverRecordService)","transformPurchaseOrder(/SuiteScripts/Integration/po_to_item_receipt.js:21)","_get(/SuiteScripts/Integration/po_to_item_receipt.js:8)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}'
}
}
But as this is the first time I have ever used netSuite, I don't know what is required to configure the inventory detail in line 1 of the item list. I also don't know if there is a way for me to view more details about the error.
Based on the comments below, I tried a version where I loaded dynamically.
`
define([`N/record`, `N/error`], function (record, error) {
function _get(context) {
transformPurchaseOrder(context);
}
function transformPurchaseOrder(context) {
const fromRecord = `purchaseorder`;
const fromId = context.poId;
const toRecord = `itemreceipt`;
const trecord = record.transform({
fromType: fromRecord,
fromId: fromId,
toType: toRecord,
isDynamic: true,
});
const inventoryDetail = trecord.getCurrentSublistSubrecord({
sublistId: `item`,
fieldId: `inventorydetail`,
});
log.debug({
title: `INVENTORY DETAIL &&&&&`,
details: inventoryDetail,
});
inventoryDetail.setValue({
fieldId: `quantity`,
value: `1`,
});
inventoryDetail.setValue({
fieldId: `totalquantity`,
value: `1`,
});
inventoryDetail.setValue({
fieldId: `issueinventorynumber`,
value: `lmrlmrlmr`,
});
inventoryDetail.setCurrentSublistValue({
sublistId: `inventoryassignment`,
fieldId: `issueinventorynumber`,
value: `lmrlmrlmr`,
});
inventoryDetail.setCurrentSublistValue({
sublistId: `inventoryassignment`,
fieldId: `issueinventorynumber_display`,
value: `lmrlmrlmr`,
});
inventoryDetail.setCurrentSublistValue({
sublistId: `inventoryassignment`,
fieldId: `quantity`,
value: `1`,
});
trecord.setCurrentSublistValue({
sublistId: `item`,
fieldId: `quantity`,
value: `1`,
});
const idl = trecord.save({
enableSourcing: true,
ignoreMandatoryFields: true,
});
}
return {
get: _get,
};
});`
With this version, I get UNEXPECTED_ERROR on trecord.getCurrentSublistSubrecord({.
And this is the equivalent non-dynamic version
define([`N/record`, `N/error`], function (record, error) {
function _get(context) {
transformPurchaseOrder(context);
}
function transformPurchaseOrder(context) {
const fromRecord = `purchaseorder`;
const fromId = context.poId;
const toRecord = `itemreceipt`;
const trecord = record.transform({
fromType: fromRecord,
fromId: fromId,
toType: toRecord,
});
const inventoryDetail = trecord.getSublistSubrecord({
sublistId: `item`,
fieldId: `inventorydetail`,
line: 0,
});
inventoryDetail.setValue({
fieldId: `quantity`,
value: `1`,
});
inventoryDetail.setValue({
fieldId: `totalquantity`,
value: `1`,
});
inventoryDetail.setValue({
fieldId: `issueinventorynumber`,
value: `lmrlmrlmr`,
});
inventoryDetail.setSublistValue({
sublistId: `inventoryassignment`,
fieldId: `issueinventorynumber`,
line: 0,
value: `lmrlmrlmr`,
});
inventoryDetail.setSublistValue({
sublistId: `inventoryassignment`,
fieldId: `issueinventorynumber_display`,
line: 0,
value: `lmrlmrlmr`,
});
inventoryDetail.setSublistValue({
sublistId: `inventoryassignment`,
fieldId: `quantity`,
line: 0,
value: `1`,
});
log.debug({
title: `INVENTORY DETAIL &&&&&`,
details: inventoryDetail,
});
trecord.setSublistValue({
sublistId: `item`,
fieldId: `quantity`,
line: 0,
value: `1`,
});
const idl = trecord.save({
enableSourcing: true,
ignoreMandatoryFields: true,
});
}
return {
get: _get,
};
});
Which works except for the fact that it adds a new inventoryassignment line instead of editing currentLine as shown below. And the error I get is "message":"Please enter value(s) for: Serial/Lot Number" so I assume that means I have to set that field in in the currentLine object.
{
type: `inventorydetail`,
isDynamic: false,
fields: {
itemdescription: `Descr`,
nlloc: `0`,
nlsub: `1`,
ignoreqtyvalidation: `F`,
trandate: `1/18/2023`,
_eml_nkey_: `xxxxxxx`,
type: `inventorydetail`,
subrecord_parent_tran_type: `ItemRcpt`,
nsapiCT: `xxxxx`,
sys_id: `xxxxx`,
nluser: `13080`,
nldept: `0`,
subrecord_transform_from_parent_id: `xxxxx`,
subrecord_transform_from_parent_tran_type: `PurchOrd`,
tolocationusesbins: `F`,
item: `13760`,
quantity: `1`,
sys_parentid: `4168409225838594`,
templatestored: `F`,
entryformquerystring: `orderline=1&item=13760&unit=1&quantity=1&subrecord_transform_from_parent_id=1075097&trandate=1/18/2023&location=713&uitype=MOH_BIN_FIELD_OPTIONAL&wavefulfillment=&subrecord_transform_from_parent_tran_type=purchord&subrecord_parent_tran_type=itemrcpt`,
nlrole: `3`,
uitype: `MOH_BIN_FIELD_OPTIONAL`,
baserecordtype: `inventorydetail`,
baseunitquantity: `1`,
totalquantity: `1`,
orderline: `1`,
haslines: `F`,
unit: `1`,
tolocation: `-1`,
customform: `-10820`,
location: `713232`,
conversionrate: `1`,
issueinventorynumber: `lmrlmrlmr`,
},
sublists: {
inventoryassignment: {
currentline: {
basequantityavailable: ``,
binnumber: ``,
binnumber_display: ``,
existingexpdate: ``,
existinginventorynumber: ``,
expirationdate: ``,
internalid: `-1`,
inventorydetail: `-1`,
inventorystatus: ``,
inventorystatus_display: ``,
issueinventorynumber: ``,
issueinventorynumber_display: ``,
lotquantityavailable: ``,
numberedrecordid: ``,
packcarton: ``,
pickcarton: ``,
quantity: ``,
quantityavailable: ``,
quantitystaged: ``,
receiptinventorynumber: ``,
sequencenumber: ``,
sys_id: `-xxxxx`,
sys_parentid: `-xxxxx`,
tobinnumber: ``,
tobinnumber_display: ``,
toinventorystatus: ``,
toinventorystatus_display: ``,
totalquantityavailable: ``,
'#': `1`,
},
'line 1': {
issueinventorynumber: `lmrlmrlmr`,
issueinventorynumber_display: `lmrlmrlmr`,
quantity: `1`,
sys_id: `-xxxxx`,
sys_parentid: `-xxxxxx`,
},
},
},
};

NodeJs promise in loop is not get all of data result

I'm using promise.
Now I try to put the promise inside loop query, assume result2['recordset'] have 2 data.
result2['recordset'].forEach(function(element, index){
var query = new Promise((success, failure) => {
request.query("SELECT M.id, M.name, M.link, M.project_idfk, M.icon FROM tbl_module M WHERE M.project_idfk = '" + element.project_idfk + "' AND M.id IN(SELECT module_idfk FROM tbl_access_module WHERE group_idfk = '" + element.group_idfk + "' AND role IS NOT NULL AND(role = 'CREATE' OR role = 'VIEW'))", function (err, result3){
success(result3['recordset']);
console.log(result3['recordset']);
});
});
});
query.then(function(result) {
console.log(result);
res.json({ module: result });
})
When I tried to console.log(result3['recordset']); it can show me the all of both data.
[
{
id: 6,
name: 'Department',
link: 'department',
project_idfk: 2,
icon: 'glyphicon-tasks'
}
]
[
{
id: 1,
name: 'Location',
link: 'location',
project_idfk: 1,
icon: 'glyphicon-screenshot'
},
{
id: 2,
name: 'Device',
link: 'device',
project_idfk: 1,
icon: 'glyphicon-hdd'
},
{
id: 3,
name: 'Floor Map',
link: 'map',
project_idfk: 1,
icon: 'glyphicon-map-marker'
},
{
id: 4,
name: 'Notification',
link: 'notificaction',
project_idfk: 1,
icon: 'glyphicon-globe'
},
{
id: 5,
name: 'Report',
link: 'report',
project_idfk: 1,
icon: 'glyphicon-tasks'
}
]
But why when I tried to console.log(result); it only show me the first data (no ID number 6)
[
{
id: 1,
name: 'Location',
link: 'location',
project_idfk: 1,
icon: 'glyphicon-screenshot'
},
{
id: 2,
name: 'Device',
link: 'device',
project_idfk: 1,
icon: 'glyphicon-hdd'
},
{
id: 3,
name: 'Floor Map',
link: 'map',
project_idfk: 1,
icon: 'glyphicon-map-marker'
},
{
id: 4,
name: 'Notification',
link: 'notificaction',
project_idfk: 1,
icon: 'glyphicon-globe'
},
{
id: 5,
name: 'Report',
link: 'report',
project_idfk: 1,
icon: 'glyphicon-tasks'
}
]
forEach on won't handle promises, Change that to map and use Promise.all to get results.
const promises = result2["recordset"].map(function (element, index) {
return new Promise((success, failure) => {
request.query(
"SELECT M.id, M.name, M.link, M.project_idfk, M.icon FROM tbl_module M WHERE M.project_idfk = '" +
element.project_idfk +
"' AND M.id IN(SELECT module_idfk FROM tbl_access_module WHERE group_idfk = '" +
element.group_idfk +
"' AND role IS NOT NULL AND(role = 'CREATE' OR role = 'VIEW'))",
(err, result) => {
success(result["recordset"]);
console.log(result["recordset"]);
}
);
});
});
Promise.all(promises).then(function (result) {
console.log(result); // list or all result
// Do something and send response
res.json({ module: result });
});

NetSuite SS 2.0: Salesorder Custom address

We are currently importing Salesorder from 3rd party,
The Salesorder creation is done fine.
We are struggling with the shipping address, we need to create a custom shipping address at each new salesorder.
when we use the following code, only the shipzip is shown in the salesorder, do you see any reason for that?
var shippingDetails = order[k].shipping_address;
log.debug('shipping',shippingDetails);
salesOrder.setValue('shipaddresslist', null);
salesOrder.setValue('shipcountry', shippingDetails.country_iso_code.substring(0,2));
log.debug('shipcountry',
salesOrder.getValue({
fieldId: 'shipcountry'
})
);
salesOrder.setValue('shipisresidential', 'T');
salesOrder.setValue('shipattention', 'Adresse de livraison');
log.debug('shipattention',
salesOrder.getValue({
fieldId: 'shipattention'
})
);
salesOrder.setValue('shipaddressee', shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname);
log.debug('shipaddressee',
salesOrder.getValue({
fieldId: 'shipaddressee'
})
);
salesOrder.setValue('shipaddrphone', shippingDetails.phone);
salesOrder.setValue('shipaddr1', shippingDetails.street_1);
salesOrder.setValue('shipaddr2', shippingDetails.street_2);
salesOrder.setValue('shipcity', shippingDetails.city);
//salesOrder.setValue('shipstate', 'CA');
salesOrder.setValue('shipzip', shippingDetails.zip_code);
as a workaround we try to use instead the below code, how can we have the carriage return?:
salesOrder.setValue('shipaddress', shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname +'\n'+shippingDetails.street_1+'\n'+shippingDetails.zip_code+' '+shippingDetails.city);
To correctly set a Billing or Shipping address on a Sales Order using SuiteScript 2.0 you must use the subrecord method.
Here is a full working example of creating a sales order with the specified Customer Internal ID and a single valid Item Internal ID
You can adapt it to suit your needs.
/**
*#NApiVersion 2.x
*/
require(['N/record'], function (record) {
var VALID_CUSTOMER_ID = 14907; // A valid Customer Internal ID for testing
var VALID_ITEM_ID = 7006; // A valid Item Internal ID for testing
// Example address details
var shippingDetails = { "country_iso_code": "USA", "civility": "civilty", "firstname": "firstname", "lastname": "lastname", "phone": "0123456789", "street_1": "Street 1", "street_2": "Street 2", "city": "Bell", "shipstate": "California", "zip_code": "90201" };
var billingDetails = { "country_iso_code": "USA", "civility": "civilty", "firstname": "firstname", "lastname": "lastname", "phone": "0123456789", "street_1": "Street 1", "street_2": "Street 2", "city": "Bell", "shipstate": "California", "zip_code": "90201" };
function CreateSalesOrder() {
// Create our new sales order
var salesOrder = record.create({
type: record.Type.SALES_ORDER,
isDynamic: true,
defaultValues: { entity: VALID_CUSTOMER_ID }
});
// Add a line item (just for testing / example)
salesOrder.selectNewLine({sublistId: 'item'});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'item',
value: VALID_ITEM_ID
});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'quantity',
value: 1
});
salesOrder.setCurrentSublistValue({
sublistId: 'item',
fieldId: 'amount',
value: 1
});
salesOrder.commitLine({sublistId: 'item'});
// Set our billing address
salesOrder.setValue({
fieldId: 'billaddresslist',
value: null // Needed to override default address
});
var billaddrSubrecord = salesOrder.getSubrecord({fieldId: 'billingaddress'});
billaddrSubrecord.setValue({
fieldId: 'country',
value: billingDetails.country_iso_code.substring(0,2)
});
billaddrSubrecord.setValue({
fieldId: 'isresidential',
value: 'T'
});
billaddrSubrecord.setValue({
fieldId: 'attention',
value: 'Adresse de livraison'
});
billaddrSubrecord.setValue({
fieldId: 'addressee',
value: billingDetails.civility +' '+billingDetails.firstname+' '+billingDetails.lastname
});
billaddrSubrecord.setValue({
fieldId: 'addrphone',
value: billingDetails.phone
});
billaddrSubrecord.setValue({
fieldId: 'addr1',
value: billingDetails.street_1
});
billaddrSubrecord.setValue({
fieldId: 'addr2',
value: billingDetails.street_2
});
billaddrSubrecord.setValue({
fieldId: 'city',
value: billingDetails.city
});
billaddrSubrecord.setValue({
fieldId: 'state',
value: billingDetails.state
});
billaddrSubrecord.setValue({
fieldId: 'zip',
value: billingDetails.zip_code
});
// Set our shipping address
salesOrder.setValue({
fieldId: 'shipaddresslist',
value: null // Needed to override default address
});
var shipaddrSubrecord = salesOrder.getSubrecord({fieldId: 'shippingaddress'});
shipaddrSubrecord.setValue({
fieldId: 'country',
value: shippingDetails.country_iso_code.substring(0,2)
});
shipaddrSubrecord.setValue({
fieldId: 'isresidential',
value: 'T'
});
shipaddrSubrecord.setValue({
fieldId: 'attention',
value: 'Adresse de livraison'
});
shipaddrSubrecord.setValue({
fieldId: 'addressee',
value: shippingDetails.civility +' '+shippingDetails.firstname+' '+shippingDetails.lastname
});
shipaddrSubrecord.setValue({
fieldId: 'addrphone',
value: shippingDetails.phone
});
shipaddrSubrecord.setValue({
fieldId: 'addr1',
value: shippingDetails.street_1
});
shipaddrSubrecord.setValue({
fieldId: 'addr2',
value: shippingDetails.street_2
});
shipaddrSubrecord.setValue({
fieldId: 'city',
value: shippingDetails.city
});
shipaddrSubrecord.setValue({
fieldId: 'state',
value: shippingDetails.state
});
shipaddrSubrecord.setValue({
fieldId: 'zip',
value: shippingDetails.zip_code
});
// Save our new sales order
salesOrder.save({ignoreMandatoryFields: true});
}
CreateSalesOrder();
});
Working Example Video
After an hour of fighting here's a 2021 update. When in doubt, RTM: https://6396621-sb1.app.netsuite.com/app/help/helpcenter.nl?fid=section_4704101831.html
//Create the custom shipping address
let shipaddr = so.getSubrecord('shippingaddress');
shipaddr.setValue('country', order.shippingAddress.country.id);
shipaddr.setValue('phone', order.deliveryphone);
shipaddr.setValue('isresidential', 'T');
shipaddr.setValue('attention', '');
shipaddr.setValue('addressee', order.shippingAddress.addressee);
shipaddr.setValue('addr1', order.shippingAddress.address1);
shipaddr.setValue('city', order.shippingAddress.city);
shipaddr.setValue('state', order.shippingAddress.state);
shipaddr.setValue('zip', order.shippingAddress.postcode);
log.debug('Shipping',shipaddr);
//Create the custom billing address
let billaddr = so.getSubrecord('billingaddress');
billaddr.setValue('country', order.billingAddress.country.id);
billaddr.setValue('phone', order.billingAddress.phone);
billaddr.setValue('isresidential', 'T');
billaddr.setValue('attention', '');
billaddr.setValue('addressee', order.billingAddress.addressee);
billaddr.setValue('addr1', order.billingAddress.address1);
billaddr.setValue('city', order.billingAddress.city);
billaddr.setValue('state', order.billingAddress.state);
billaddr.setValue('zip', order.billingAddress.postcode);
log.debug('Billing',billaddr);

How do I populate a User Story's Revision History in a grid

I found an answer related to Revision History "Querying for User Story revisions in Rally"
I am having trouble determining how to populate a grid with it.
Can I use the model and populate a story that the gird references?
Here is a working example, using other examples.
I had to populate an array with revision history info and add it to a story.
Then the story populated the grid.
// Also referenced
// https://stackoverflow.com/questions/22334745/does-rally-data-custom-store-have-magic-uniqueness
//
Ext.define('CustomApp',
{
extend: 'Rally.app.App',
componentCls: 'app',
launch: function()
{
var panel = Ext.create('Ext.panel.Panel',
{
layout: 'hbox',
itemId: 'parentPanel',
componentCls: 'panel',
items: [
{
xtype: 'panel',
title: 'Artifacts updated in the last two days',
width: 600,
itemId: 'childPanel1'
},
{
xtype: 'panel',
title: 'Last Revision',
width: 600,
itemId: 'childPanel2'
}]
});
this.add(panel);
var artifacts = Ext.create('Rally.data.wsapi.artifact.Store',
{
models: ['UserStory','Defect', 'TestCase'],
fetch: ['Owner', 'FormattedID','Name','ScheduleState','RevisionHistory','Revisions','Description','CreationDate','User'],
autoLoad: true,
listeners:
{
load: this._onDataLoaded,
scope: this
}
});
},
_onDataLoaded: function(store, data)
{
this._customRecords = [];
_.each(data, function(artifact, index)
{
this._customRecords.push(
{
_ref: artifact.get('_ref'),
FormattedID: artifact.get('FormattedID'),
Name: artifact.get('Name'),
RevisionID: Rally.util.Ref.getOidFromRef(artifact.get('RevisionHistory')),
RevisionNumber: 'not loaded'
});
}, this);
this._createGrid(store,data);
},
_createGrid: function(store,data)
{
var that = this;
var g = Ext.create('Rally.ui.grid.Grid',
{
itemId: 'g',
store: store,
enableEditing: false,
showRowActionsColumn: false,
columnCfgs:
[{text: 'Formatted ID', dataIndex: 'FormattedID'},
{text: 'Name', dataIndex: 'Name'},
{text: 'ScheduleState', dataIndex: 'ScheduleState'},
{text: 'Last Revision',
renderer: function (v, m, r)
{
var id = Ext.id();
Ext.defer(function ()
{
Ext.widget('button',
{
renderTo: id,
text: 'see',
width: 50,
handler: function ()
{
that._getRevisionHistory(data, r.data);
}
});
}, 50);
return Ext.String.format('<div id="{0}"></div>', id);
}
}], height: 400,
});
this.down('#childPanel1').add(g);
},
_getRevisionHistory: function(artifactList, artifact)
{
this._artifact = artifact;
this._revisionModel = Rally.data.ModelFactory.getModel(
{
type: 'RevisionHistory',
scope: this,
success: this._onModelCreated
});
},
_onModelCreated: function(model)
{
model.load(Rally.util.Ref.getOidFromRef(this._artifact.RevisionHistory._ref),
{
scope: this,
success: this._onModelLoaded
});
},
_onModelLoaded: function(record, operation)
{
var list = [];
record.getCollection('Revisions').load(
{
fetch: true,
scope: this,
callback: function(revisions, operation, success)
{
_.each(revisions, function(artifact, index)
{
var creationdate;
if (Rally.environment.useSystemTimezone || Rally.environment.useWorkspaceTimeZone)
{
creationdate = Rally.util.DateTime.formatDate(artifact.data.CreationDate, true);
}
else
{
creationdate = Rally.util.DateTime.formatWithDefaultDateTime(artifact.data.CreationDate);
}
var nodedata =
{
rev_num: artifact.data.RevisionNumber,
descript: artifact.data.Description,
author: artifact.data.User._refObjectName,
creationdate: creationdate
};
if(nodedata.descript.indexOf('SCHEDULE STATE') > -1)
{
list.push(nodedata);
}
else
{
if(nodedata.descript .indexOf('PLAN ESTIMATE') > -1)
{
list.push(nodedata);
}
}
}, this);
var myStore = Ext.create("Rally.data.custom.Store",
{
autoLoad: true,
data : list,
});
var revGrid = Ext.create('Rally.ui.grid.Grid',
{
itemId: 'revGrid ',
store: myStore,
enableEditing: false,
showRowActionsColumn: false,
height: 400,
columnCfgs:
[
{text: 'Rev #', dataIndex: 'rev_num'},
{text: 'Description', dataIndex: 'descript'},
{text: 'Author', dataIndex: 'author'},
{text: 'Change Date', dataIndex: 'creationdate'}
]
});
this.down('#childPanel2').add(revGrid);
}
});
},
});

Resources