function getActionIds(processes, formCode) {
  let result = [];

  function search(p) {
    p.forEach(function(process) {
      if (process.completionFormCode == formCode && process.finished) {
        result.push(process);
      }
      if (process.subProcesses.length > 0) search(process.subProcesses);
    });
  }
  search(processes);

  return result.sort(function(a, b) {
    return UTILS.parseDateTime(b.finished) - UTILS.parseDateTime(a.finished);
  }).map(function(item) {
    return {actionID: item.actionID, finished: item.finished};
  });
};

//Сопоставление из дин.таблицы в дин.таблицу
function matchingTables(id, completionFormData, currentFormData, currentFormDescription) {
  let tableFromData = UTILS.getValue(completionFormData, id.from.split('.')[0]);
  let tableData = UTILS.getValue(currentFormData, id.to.split('.')[0]);
  let fromCmpID = id.from.split('.')[1];
  let currentCmpID = id.to.split('.')[1];

  if(!tableData || !tableData.hasOwnProperty('data')) tableData = {id: id.to.split('.')[0], type: 'appendable_table', data: []}

  if(tableFromData && tableFromData.hasOwnProperty('data')) {
    tableFromData.data.forEach(function(item){
      if(item.id.substring(0, item.id.indexOf('-b')) == fromCmpID) {
        let field = UTILS.createField({
          id: currentCmpID + "-b" + UTILS.getTableBlockIndex(tableData, currentCmpID),
          type: UTILS.getCmpType(currentFormDescription, currentCmpID)
        });
        for(let key in item) {
          if(key === 'id' || key === 'type') continue;
          field[key] = item[key];
        }

        tableData.data.push(field);
      }
    });
  }
}

// сопоставление из компонента в дин.таблицу
function matchingCmpToTable(id, fromData, currentFormData, currentFormDescription) {
  let tableID = id.to.split('.')[0];
  let cmpID = id.to.split('.')[1];
  let tableData = UTILS.getValue(currentFormData, tableID);

  if(!tableData || !tableData.hasOwnProperty('data')) tableData = {id: tableID, type: 'appendable_table', data: []}

  let field = UTILS.createField({
    id: cmpID + "-b" + UTILS.getTableBlockIndex(tableData, cmpID),
    type: UTILS.getCmpType(currentFormDescription, cmpID)
  });

  for(let key in fromData) {
    if(key === 'id' || key === 'type') continue;
    field[key] = fromData[key];
  }

  tableData.data.push(field);
}

var result = true;
var message = "ok";

try {
  let formCodeCompletion = 'work_completion_form_orders'; // код формы завершения

  let matching = [];
  matching.push({from: 'files', to: 'files'}); //это таблицы, если таблицы одинаковые можно просто указать их айдишники

  // matching.push({from: 'cmp_from', to: 'cmp_to'}); // сопоставление из компонента в компонент
  // matching.push({from: 'cmp1', to: 'table2.cmp2'}); // сопоставление из компонента в компонент динамической таблицы
  // matching.push({from: 'table1.cmp1', to: 'table2.cmp2'}); // сопоставление из компонента дин.таблицы в компонент дин.таблицы

  let processes = API.getProcesses(documentID);
  let actions = getActionIds(processes, formCodeCompletion);

  let completionFormDataUUID = actions.map(function(item) {
    return API.getWorkCompletionData(item.actionID).result.dataUUID;
  }).filter(function(dataUUID){ return dataUUID != null})[0];

  if(!completionFormDataUUID) throw new Error('Не найдена форма завершения');

  let completionFormData = API.getFormData(completionFormDataUUID);
  let currentFormData = API.getFormData(dataUUID);
  let currentFormDescription = API.getFormDescription(currentFormData.form);

  matching.forEach(function(id) {
    if(id.from.indexOf('.') != -1) {
      matchingTables(id, completionFormData, currentFormData, currentFormDescription);
    } else {
      let fromData = UTILS.getValue(completionFormData, id.from);
      if(fromData) {
        if(id.to.indexOf('.') == -1) {
           UTILS.setValue(currentFormData, id.to, fromData);
        } else {
          matchingCmpToTable(id, fromData, currentFormData, currentFormDescription);
        }
      }
    }
  });

  API.saveFormData(currentFormData);

} catch (err) {
  log.error(err.message);
  message = err.message;
}
