Действие "Парсер писем (данные из писем)"
Для выбранной сделки находит письма и выбирает из них данные, такие как телефон, email, товарная позиция и т.п.
Полученные данные записываются в комментарий сделки.
Это активити ведет учет обработанных писем, поэтому каждое письмо обрабатывается только один раз.
Параметр stripHtml будет полезен, если письма приходят в формате HTML и нужно убрать теги, оставив только текст
Входные параметры
  • dealId: числовой ID сделки
  • stripHtml: Y - удалять HTML-теги из тела письма, N - оставить тело письма без изменения
Выходные параметры
-
Исходный код

console.log(`dealId: "${dealId}", stripHtml: "${stripHtml}"`);

const ENTITY_NAME = "parsedEmailsId"
createHelperEntityIfNotExists();

const patterns = {
  "email": "Email:[\\s\\r\\n]*([a-zA-Z0-9._]+@[a-zA-Z0-9._]+)",
  "phone": "Телефон:[\\s\\r\\n]*([+0-9 ]+)",
  "orderItem": "Заказ:[\\s\\r\\n]*(.+)",
}

const activities = bx24.callMethod('crm.activity.list',
	{ 
      filter:
      { 
        "OWNER_TYPE_ID": 2, 
        "OWNER_ID": dealId,
        "PROVIDER_TYPE_ID": "EMAIL"
      },
      select:[ "ID", "SUBJECT", "DESCRIPTION" ]
  }
);

for(let i = 0; i < activities.length; i++) {
  const activity = activities[i];
  const activityId = activities[i].ID;
  if (isAlreadyParsed(activityId)) {
    console.log(`activityId=${activityId}: ` + 
                `пропускаем письмо "${activity.SUBJECT}" (уже было обработано)`)
  } else {
    const body = prepareBody(activity.DESCRIPTION);
    console.log("body", body);

    const result = {}
    result.phone = matchResult(body, "phone");
    result.orderItem = matchResult(body, "orderItem");
    result.email = matchResult(body, "email");

    console.log(`result: ${JSON.stringify(result)}`)
    
    bx24.callMethod(
    	"crm.timeline.comment.add",
    	{
    		fields:
    		{
    			"ENTITY_ID": dealId,
    			"ENTITY_TYPE": "deal",
    			"COMMENT": `Телефон: ${result.phone}\n` +
            `Email: ${result.email}\nЗаказ: ${result.orderItem}`
    		}
    	}
    );
    markParsed(activityId);
    console.log(`activityId=${activityId}: письмо обработано`)
  }
}

return {
};


// === вспомогательные функции

function isObject(x) {
  return typeof x === 'object' && x !== null
}

function createHelperEntityIfNotExists() {
  const existingEntity = bx24.callMethod('entity.get',
  	{}
  ).find((entity) => entity.ENTITY === ENTITY_NAME);
  if (existingEntity === undefined) {
    bx24.callMethod('entity.add', 
       {'ENTITY': ENTITY_NAME, 
        'NAME': ENTITY_NAME, 
       }
    );
  }
}

function isAlreadyParsed(activityId) {
  const alreadyParsed = bx24.callMethod('entity.item.get', {
    ENTITY: ENTITY_NAME,
    FILTER: {
      '=CODE': activityId
    }
  });
  return alreadyParsed.length !== 0;
}

function markParsed(activityId) {
  bx24.callMethod('entity.item.add', {
    ENTITY: ENTITY_NAME,
    NAME: activityId,
    CODE: activityId
  });
}

function prepareBody(body) {
  let result = body;
  if (stripHtml) {
    result = result.replace(/<[^>]*>/g, '\n');
  }
  result = result.replace(/\u00A0/g, ' '); // &nbsp
  return result;
}

function matchResult(body, patternName) {
  let result = body.match(patterns[patternName]);
  if (result !== null) {
    result = result[1]; // 1-я группа, а не весь результат
  }
  return result;
}