Этот код машинописи выдает ошибку «Ошибка диапазона: превышен максимальный размер стека вызовов», но только при наличии нескольких элементов

#typescript #netsuite #suitescript2.0

Вопрос:

Мне было любопытно, сталкивался ли кто-нибудь с этой проблемой. Я предполагаю, что это может быть какая-то рекурсия, связанная с увольнением функции sublistChanged (), но я не могу понять, как это исправить.

 export function sublistChanged (ctx: EntryPoints.Client.sublistChangedContext) {
    const rec = X.getTx(ctx)
    const total = _.sumBy(rec.item, (line: POItemSublist | TOItemSublist) => line.quantity * line.custcol_atlas_item_weight!)
    rec.custbody_totalitemweightorder = total
  }
 

Комментарии:

1. Это, вероятно, артефакт любой библиотеки, которую вы используете. Поскольку вы в конечном итоге попадаете в пользовательское поле тела, вы не повторно запускаете событие изменения подсписка, если только при обновлении поля тела событие там не попытается обновить строки.

Ответ №1:

Похоже, вы используете машинописный текст с подчеркиванием и какую-то другую библиотеку.

Усилия IMO по превращению Netsuite в более «традиционную» среду довольно сложны.

Большинством описаний списков довольно легко управлять с помощью более удобного итератора Netsuite. У меня есть это в виде фрагмента:

 function iter(rec:record.Record, listName, cb, doReverse? :boolean){
    
    var i = 0;
    var getV = function (fld){
        return rec.getSublistValue({sublistId:listName, fieldId:fld, line:i});
    };
    if(doReverse){
        i = rec.getLineCount({sublistId:listName}) - 1;
        for(; i>= 0; i--){
            cb(i, getV);
        }
    }else{
        var lim = rec.getLineCount({sublistId:listName});
        for(; i< lim; i  ){
            cb(i, getV);
        }
    }
}
 

таким образом, ваш код может выглядеть следующим образом:

 export function sublistChanged (ctx: EntryPoints.Client.sublistChangedContext) {
    const rec = ctx.currentRecord;
    let total = 0;
    iter(rec, 'item', (idx, getV)=>{
        total  = getV('quantity') * getV('custcol_atlas_item_weight')!;
    });
    rec.setValue({fieldId:'custbody_totalitemweightorder' ,value:total, ignoreFieldChange:true, forceSyncSourcing: true});
  }
 

ignoreFieldChange можно пропустить, если вы хотите, чтобы запускалась обычная обработка событий по потоку, но это может потребоваться в том случае, если настройка поля «Общий вес» также обычно запускает сценарий.

forceSyncSourcing заставляет действие setValue полностью завершиться до того, как произойдет следующее действие.