У комерційній пропозиції більша частина роботи повторюється: підставити компанію, контакт, послуги, ціну, строк дії та менеджера. Тому автоматизація комерційних пропозицій починається не з ШІ, а з контрольованого шаблону й чітких статусів.

Автоматизація комерційних пропозицій: дані, шаблон документа, погодження та відправлення
Автоматизація комерційних пропозицій: дані, шаблон документа, погодження та відправлення

Процес можна зібрати на Google Sheets, Docs, Drive та Gmail. Менеджер готує дані, Apps Script створює копію документа, PDF і чернетку листа. Відправлення дозволяється після погодження. Це продовжує CRM автоматизацію з чистими лідами: спочатку впорядковуємо контакт, потім створюємо документ.

Чому менеджери витрачають час на КП

Проблема з'являється, коли кожен менеджер зберігає власний шаблон і копіює попередню пропозицію. У новому PDF може залишитися чуже ім'я, стара ціна або строк дії.

Типові симптоми:

  • файли називаються КПfinal, КПnew і КПfinal2;
  • невідомо, яка версія була відправлена клієнту;
  • ціна в документі відрізняється від погодженої в таблиці;
  • лист відправили, але поле sent_at ніде не зафіксували;

Ціну, юридичні умови й склад послуг підтверджує людина. Скрипт лише переносить затверджені поля.

Які дані потрібні для генерації

Для першої версії достатньо одного аркуша Proposals:

ПолеПризначення
proposal_idстабільний номер пропозиції
client_nameім'я контактної особи
companyназва компанії
emailадреса одержувача
servicesпогоджений перелік робіт
priceзатверджена сума
currencyвалюта
valid_untilстрок дії пропозиції
managerвідповідальний
statusпоточний стан
document_urlпосилання на Google Docs
pdf_urlпосилання на збережений PDF
sent_atдата й час відправлення

proposal_id не варто прив'язувати до номера рядка: таблицю можуть сортувати. Підійде значення PROP-20260607-A4F2. Дані з AI-помічника менеджера перед дзвінком можна використати для КП, але модель не повинна вигадувати ціну.

Шаблон Google Docs із плейсхолдерами

Процес генерації комерційної пропозиції зі структурованих даних і шаблону
Процес генерації комерційної пропозиції зі структурованих даних і шаблону

У шаблоні зручно використовувати маркери:

Компанія: {{COMPANY}}
Контакт: {{CLIENT_NAME}}
Послуги: {{SERVICES}}
Вартість: {{PRICE}} {{CURRENCY}}
Пропозиція дійсна до: {{VALID_UNTIL}}
Менеджер: {{MANAGER}}

Apps Script може створити копію шаблону через Drive, а потім відкрити її через DocumentApp. Офіційний Document service підтримує відкриття й редагування Google Docs, а replaceText() працює з регулярними виразами.

function createProposalFromTemplate(data) {
  const templateId = getSetting("PROPOSAL_TEMPLATE_ID");
  const folderId = getSetting("PROPOSALS_FOLDER_ID");
  const folder = DriveApp.getFolderById(folderId);

  const name = `${data.proposal_id} - ${data.company}`;
  const copy = DriveApp.getFileById(templateId).makeCopy(name, folder);
  const doc = DocumentApp.openById(copy.getId());

  replaceProposalPlaceholders(doc, data);
  doc.saveAndClose();

  return {
    fileId: copy.getId(),
    documentUrl: copy.getUrl()
  };
}

Кожна генерація створює окремий файл і не перезаписує шаблон.

function replaceProposalPlaceholders(doc, data) {
  const body = doc.getBody();
  const values = {
    COMPANY: data.company,
    CLIENT_NAME: data.client_name,
    SERVICES: data.services,
    PRICE: formatMoney(data.price),
    CURRENCY: data.currency,
    VALID_UNTIL: data.valid_until,
    MANAGER: data.manager
  };

  Object.entries(values).forEach(([key, value]) => {
    body.replaceText(`\\{\\{${key}\\}\\}`, String(value || ""));
  });
}

Порожній email або нульова ціна мають переводити рядок у error.

Як створити PDF і підготувати лист

Google Docs можна отримати як PDF через офіційний Drive service. Для контрольованого процесу спочатку краще створювати чернетку.

function exportProposalPdf(fileId, proposalId) {
  const pdfFolder = DriveApp.getFolderById(
    getSetting("PROPOSALS_PDF_FOLDER_ID")
  );

  const blob = DriveApp
    .getFileById(fileId)
    .getAs(MimeType.PDF)
    .setName(`${proposalId}.pdf`);

  const pdfFile = pdfFolder.createFile(blob);

  return {
    blob,
    pdfUrl: pdfFile.getUrl()
  };
}

Менеджер має бачити одержувача, тему й вкладення до відправки. Чернетки та вкладення описані в офіційному Gmail service.

function createProposalDraft(data, pdfBlob) {
  const subject = `Комерційна пропозиція ${data.proposal_id}`;
  const body = [
    `Добрий день, ${data.client_name}!`,
    "",
    "Надсилаю погоджену комерційну пропозицію у вкладенні.",
    `Вона дійсна до ${data.valid_until}.`,
    "",
    `З повагою, ${data.manager}`
  ].join("
");

  return GmailApp.createDraft(data.email, subject, body, {
    attachments: [pdfBlob]
  });
}

Функція відправлення має повторно прочитати рядок і перевірити status === "approved". Як у системі обробки замовлень зі статусами, дія виконується лише з дозволеного стану.

Ручне погодження зупиняє відправлення неперевіреної ціни або застарілої версії
Ручне погодження зупиняє відправлення неперевіреної ціни або застарілої версії
function sendApprovedProposal(proposalId) {
  const data = getProposalById(proposalId);

  if (!data || data.status !== "approved") {
    throw new Error("Proposal must be approved before sending");
  }

  const draft = GmailApp.getDraft(data.draft_id);
  draft.send();

  updateProposalFields(proposalId, {
    status: "sent",
    sent_at: new Date().toISOString()
  });
}

Статуси та версії пропозиції

Реєстр комерційних пропозицій зі статусами, відповідальними та історією версій
Реєстр комерційних пропозицій зі статусами, відповідальними та історією версій

Мінімальна статусна модель:

СтатусЩо відбувається
draftменеджер заповнює дані
readyусі обов'язкові поля пройшли перевірку
approvedвідповідальний підтвердив ціну й умови
sentлист відправлено, sent_at заповнено
expiredстрок дії завершився
errorдокумент або лист не вдалося підготувати

Таблиця зберігає URL документа, PDF і час зміни статусу. Після правок створіть PROP-20260607-A4F2-v2, поверніть статус у ready і погодьте повторно.

Шаблон, PDF і таблицю з комерційними умовами не слід відкривати як Anyone with the link. Для інтеграцій також корисна архітектура Apps Script webhook-сервера.

Як шаблон прибрав помилки у версіях комерційної пропозиції

Менеджер перевіряє ціну й умови комерційної пропозиції перед погодженням
Менеджер перевіряє ціну й умови комерційної пропозиції перед погодженням

У робочому сценарії я почав не з генерації тексту, а з реєстру пропозицій. До цього менеджер копіював попередній Google Docs, змінював видимі поля й експортував PDF. Найнеприємніша помилка була не технічною: у документі могла залишитися стара умова, яку не помітили перед відправленням.

Я виніс ключові значення в окремі колонки, додав proposalid, status, documenturl, pdfurl і sentat. Скрипт перестав редагувати старий файл та почав створювати нову копію шаблону для кожної версії. Перед відправленням залишив ручний approval.

Результат перевіряється фактами: для кожного PDF видно джерельний рядок, актуальну версію, відповідального й дату відправлення. Якщо клієнт просить змінити склад робіт, команда створює v2, а не намагається згадати, який із файлів із назвою final був останнім.

Практичний підсумок

Автоматизація комерційних пропозицій працює, коли дані структуровані, шаблон незмінний, а генерація відокремлена від погодження й відправлення. Google Sheets зберігає стан, Google Docs формує документ, Drive тримає версії та PDF, Gmail готує чернетку.

Почніть з одного шаблону й шести статусів. Не передавайте ШІ право вигадувати ціни або юридичні умови. Нехай скрипт прибирає копіювання, а людина зберігає контроль над комерційним рішенням.