From d21ff3437f479348b0b561fb2f89d23995263e2f Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev <572431+veikab@users.noreply.github.com> Date: Mon, 4 May 2026 10:58:06 +0700 Subject: [PATCH] Use Typst as source for specification PDF --- docs/scripts/build-typst-tz.mjs | 299 +--- docs/tz-fregat.typ | 2922 +++++++++++++++++++++++++++++++ 2 files changed, 2927 insertions(+), 294 deletions(-) create mode 100644 docs/tz-fregat.typ diff --git a/docs/scripts/build-typst-tz.mjs b/docs/scripts/build-typst-tz.mjs index c865b6d..c87897e 100644 --- a/docs/scripts/build-typst-tz.mjs +++ b/docs/scripts/build-typst-tz.mjs @@ -1,313 +1,25 @@ -import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import { mkdir } from 'node:fs/promises'; import { dirname, join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; import { spawnSync } from 'node:child_process'; // Usage: node docs/scripts/build-typst-tz.mjs -// Output: docs/export/tz-fregat.typ and docs/export/tz-fregat.pdf +// Source: docs/tz-fregat.typ +// Output: docs/export/tz-fregat.pdf const __dirname = dirname(fileURLToPath(import.meta.url)); const docsDir = join(__dirname, '..'); -const sourceFile = join(docsDir, 'index.md'); +const sourceFile = join(docsDir, 'tz-fregat.typ'); const exportDir = join(docsDir, 'export'); -const typstFile = join(exportDir, 'tz-fregat.typ'); const pdfFile = join(exportDir, 'tz-fregat.pdf'); -const includePattern = /^$/gm; - -async function readMarkdownWithIncludes(filePath, seen = new Set()) { - if (seen.has(filePath)) { - throw new Error(`Circular include detected: ${filePath}`); - } - - seen.add(filePath); - - let content = await readFile(filePath, 'utf8'); - const replacements = []; - - for (const match of content.matchAll(includePattern)) { - const includePath = join(dirname(filePath), match[1]); - const includeContent = await readMarkdownWithIncludes(includePath, seen); - replacements.push([match[0], includeContent.trim()]); - } - - for (const [needle, replacement] of replacements) { - content = content.replace(needle, replacement); - } - - seen.delete(filePath); - - return content; -} - -function escapeTypstString(value) { - return value.replaceAll('\\', '\\\\').replaceAll('"', '\\"'); -} - -function escapeContentBlock(value) { - return value - .replaceAll('\\', '\\\\') - .replaceAll('[', '\\[') - .replaceAll(']', '\\]') - .replaceAll('*', '\\*') - .replaceAll('#', '\\#') - .replaceAll('@', '\\@'); -} - -function inlineTypst(value) { - let text = value.trim(); - - text = text.replaceAll('
', ' '); - text = text.replaceAll('
', ' '); - text = text.replaceAll(' ', ' '); - text = text.replace(/\*\*([^*]+)\*\*/g, '$1'); - text = text.replace(/`([^`]+)`/g, '$1'); - text = text.replaceAll('*', '\\*'); - text = text.replaceAll('@', '\\@'); - text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label, href) => { - if (href.startsWith('http://') || href.startsWith('https://')) { - return `#link("${escapeTypstString(href)}")[${escapeContentBlock(label)}]`; - } - - return label; - }); - - return text; -} - -function parseTableRow(line) { - const trimmed = line.trim(); - const withoutEdges = trimmed.replace(/^\|/, '').replace(/\|$/, ''); - - return withoutEdges.split('|').map((cell) => inlineTypst(cell)); -} - -function isTableSeparator(line) { - return /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(line); -} - -function renderTable(lines, startIndex) { - const rows = []; - let index = startIndex; - - while (index < lines.length && /^\s*\|/.test(lines[index])) { - if (!isTableSeparator(lines[index])) { - rows.push(parseTableRow(lines[index])); - } - - index += 1; - } - - const columnCount = Math.max(...rows.map((row) => row.length)); - const normalizedRows = rows.map((row) => { - if (row.length >= columnCount) { - return row; - } - - return [...row, ...Array.from({ length: columnCount - row.length }, () => '')]; - }); - - const cells = normalizedRows.flatMap((row, rowIndex) => row.map((cell) => { - const content = escapeContentBlock(cell); - return rowIndex === 0 ? `[*${content}*]` : `[${content}]`; - })); - - const columns = Array.from({ length: columnCount }, () => '1fr').join(', '); - - return { - nextIndex: index, - typst: [ - '#text(size: 7.6pt)[', - ' #table(', - ` columns: (${columns}),`, - ' stroke: rgb("#d0d7de"),', - ' inset: 4pt,', - ' align: horizon + left,', - ` ${cells.join(',\n ')}`, - ' )', - ']', - '', - ].join('\n'), - }; -} - -function renderImage(line) { - const match = line.match(/^!\[([^\]]*)\]\(([^)]+)\)$/); - - if (!match) { - return null; - } - - const [, alt, src] = match; - const imagePath = src.startsWith('/') - ? `..${src.replace(/^\//, '/public/')}` - : src; - - return [ - '#figure(', - ` image("${escapeTypstString(imagePath)}", width: 100%),`, - ` caption: [${escapeContentBlock(alt)}],`, - ')', - '', - ].join('\n'); -} - -function markdownToTypst(markdown) { - const lines = markdown - .replace(/\r\n/g, '\n') - .replace(/^---[\s\S]*?---\n/, '') - .split('\n'); - - const output = []; - let inFence = false; - - for (let index = 0; index < lines.length;) { - const line = lines[index]; - const trimmed = line.trim(); - - if (trimmed.startsWith('```')) { - inFence = !inFence; - output.push(line); - index += 1; - continue; - } - - if (inFence) { - output.push(line); - index += 1; - continue; - } - - if (!trimmed) { - output.push(''); - index += 1; - continue; - } - - if (/^\s*\|/.test(line) && index + 1 < lines.length && isTableSeparator(lines[index + 1])) { - const table = renderTable(lines, index); - output.push(table.typst); - index = table.nextIndex; - continue; - } - - const image = renderImage(trimmed); - - if (image) { - output.push(image); - index += 1; - continue; - } - - const heading = line.match(/^(#{1,6})\s+(.+)$/); - - if (heading) { - const level = heading[1].length; - const title = inlineTypst(heading[2]); - - if (level === 1 && title === 'Техническое задание на разработку программного продукта') { - index += 1; - continue; - } - - if (level === 1 && output.some((item) => item.trim())) { - output.push('#pagebreak(weak: true)'); - } - - output.push(`${'='.repeat(level)} ${title}`); - output.push(''); - index += 1; - continue; - } - - const bullet = line.match(/^(\s*)-\s+(.+)$/); - - if (bullet) { - output.push(`${bullet[1]}- ${inlineTypst(bullet[2])}`); - index += 1; - continue; - } - - const ordered = line.match(/^(\s*)\d+\.\s+(.+)$/); - - if (ordered) { - output.push(`${ordered[1]}+ ${inlineTypst(ordered[2])}`); - index += 1; - continue; - } - - output.push(inlineTypst(line)); - index += 1; - } - - return output.join('\n'); -} - -function typstDocument(body) { - return `#set document(title: "Техническое задание на разработку программного продукта") -#set page( - paper: "a4", - margin: (left: 20mm, right: 18mm, top: 18mm, bottom: 18mm), - numbering: "1", - header: align(right)[#text(size: 8pt, fill: rgb("#667085"))[Личный кабинет Фрегат]], - footer: align(center)[#text(size: 8pt, fill: rgb("#667085"))[#context counter(page).display("1")]], -) -#set text(font: "Times New Roman", size: 10.5pt, lang: "ru") -#set par(justify: true, leading: 0.58em, first-line-indent: 0pt) -#set list(indent: 13pt, body-indent: 5pt) -#show link: underline -#show raw: set text(font: "Times New Roman") -#show heading.where(level: 1): set text(size: 16pt, weight: "bold") -#show heading.where(level: 2): set text(size: 13pt, weight: "bold") -#show heading.where(level: 3): set text(size: 11.5pt, weight: "bold") -#show heading: it => block(above: 1.15em, below: 0.55em, it) - -#align(center)[ - #text(size: 18pt, weight: "bold")[Техническое задание] - - #v(5mm) - #text(size: 14pt)[на разработку программного продукта] - - #v(3mm) - #text(size: 14pt, weight: "bold")[«Личный кабинет Фрегат»] -] - -#v(12mm) - -#align(center)[ - #table( - columns: (40%, 60%), - stroke: rgb("#d0d7de"), - inset: 6pt, - [Заказчик], [ООО «Фрегат Групп»], - [Исполнитель], [ИП Бакиев Р.Ш.], - [Основание], [Договор №28/04-26ПО от 28.04.2026], - [Формат], [Техническое задание], - ) -] - -#pagebreak() - -#outline(title: [Содержание], depth: 2, indent: auto) - -#pagebreak() - -${body} -`; -} - await mkdir(exportDir, { recursive: true }); -const markdown = await readMarkdownWithIncludes(sourceFile); -const typst = typstDocument(markdownToTypst(markdown)); - -await writeFile(typstFile, typst, 'utf8'); - const compileResult = spawnSync('typst', [ 'compile', '--root', '.', - relative(docsDir, typstFile), + relative(docsDir, sourceFile), relative(docsDir, pdfFile), ], { cwd: docsDir, @@ -320,5 +32,4 @@ if (compileResult.status !== 0) { throw new Error('Typst PDF build failed'); } -process.stdout.write(`Generated ${relative(docsDir, typstFile)}\n`); process.stdout.write(`Generated ${relative(docsDir, pdfFile)}\n`); diff --git a/docs/tz-fregat.typ b/docs/tz-fregat.typ new file mode 100644 index 0000000..3267c2d --- /dev/null +++ b/docs/tz-fregat.typ @@ -0,0 +1,2922 @@ +#set document(title: "Техническое задание на разработку программного продукта") +#set page( + paper: "a4", + margin: (left: 20mm, right: 18mm, top: 18mm, bottom: 18mm), + numbering: "1", + header: align(right)[#text(size: 8pt, fill: rgb("#667085"))[Личный кабинет Фрегат]], + footer: align(center)[#text(size: 8pt, fill: rgb("#667085"))[#context counter(page).display("1")]], +) +#set text(font: "Times New Roman", size: 10.5pt, lang: "ru") +#set par(justify: true, leading: 0.58em, first-line-indent: 0pt) +#set list(indent: 13pt, body-indent: 5pt) +#show link: underline +#show raw: set text(font: "Times New Roman") +#show heading.where(level: 1): set text(size: 16pt, weight: "bold") +#show heading.where(level: 2): set text(size: 13pt, weight: "bold") +#show heading.where(level: 3): set text(size: 11.5pt, weight: "bold") +#show heading: it => block(above: 1.15em, below: 0.55em, it) + +#align(center)[ + #text(size: 18pt, weight: "bold")[Техническое задание] + + #v(5mm) + #text(size: 14pt)[на разработку программного продукта] + + #v(3mm) + #text(size: 14pt, weight: "bold")[«Личный кабинет Фрегат»] +] + +#v(12mm) + +#align(center)[ + #table( + columns: (40%, 60%), + stroke: rgb("#d0d7de"), + inset: 6pt, + [Заказчик], [ООО «Фрегат Групп»], + [Исполнитель], [ИП Бакиев Р.Ш.], + [Основание], [Договор №28/04-26ПО от 28.04.2026], + ) +] + +#pagebreak() + +#outline(title: [Содержание], depth: 2, indent: auto) + +#pagebreak() + + += 1. Введение, основание, цель и состав проекта + + +Настоящее техническое задание описывает разработку программного продукта Личный кабинет Фрегат для поддержки клиентских, менеджерских, заказных, бонусных и интеграционных сценариев в едином веб-интерфейсе. + +Документ используется для согласования состава работ, функциональных и технических требований, этапов разработки, требований к программной документации, порядка приемки и гарантийного сопровождения. + +== 1.1 Основание для разработки + + +Разработка программного продукта выполняется на основании следующих документов и материалов: + +- договор на разработку программного продукта №28/04-26ПО от 28 апреля 2026 года +- приложение №1 к договору: спецификация основных требований к программному обеспечению Личный кабинет Фрегат +- согласованные требования заказчика к клиентскому, менеджерскому, бонусному и интеграционному контурам + +== 1.2 Цель разработки + + +Программный продукт Личный кабинет Фрегат предназначен для организации единого цифрового канала взаимодействия между ООО Фрегат Групп и B2B-клиентами компании. + +Система должна обеспечивать: + +- подключение и регистрацию клиентов +- выбор готовой продукции из каталога +- подачу заявок на заказ готовой продукции +- подачу заявок на расчет продукции с индивидуальными параметрами +- согласование стоимости и условий поставки +- сопровождение заказов по статусам +- отправку клиентских уведомлений +- ведение бонусной и реферальной программы + +== 1.3 Объект автоматизации + + +Объектом автоматизации являются процессы клиентского обслуживания и внутренней обработки заявок, выполняемые менеджерами ООО Фрегат Групп при работе с готовой и индивидуальной продукцией. + +== 1.4 Состав системы + + +В состав программного продукта входят: + +- клиентский веб-интерфейс +- менеджерский веб-интерфейс +- серверная бизнес-логика +- база данных +- модуль синхронизации с внешними системами +- модуль уведомлений +- модуль бонусной программы +- модуль административных настроек + +== 1.5 Границы реализации + + +В состав программного продукта входят следующие функциональные области: + +- регистрация и подключение клиента +- профиль клиента и данные компании +- каталог готовой продукции +- карточка товара и выбор параметров +- корзина и заявка на заказ +- заявка на расчет индивидуальной продукции +- обработка заявок менеджером +- список заказов и карточка заказа +- уведомления +- бонусный кабинет +- административные настройки + +Программный продукт не предназначен для выполнения следующих функций: + +- самостоятельного ценообразования клиентом +- ведения бухгалтерского учета +- выполнения функций публичного B2C-магазина +- прямого редактирования клиентом внутренних бизнес-правил компании +- замены учетной системы 1С как первичного источника учетных данных + +== 1.6 Основные принципы работы + + +Система должна обеспечивать следующие базовые принципы: + +- доступ к функциям и данным определяется ролью пользователя +- клиент работает только в пределах собственных данных и данных своего контрагента +- стоимость товара и условия поставки публикуются только после обработки менеджером +- история изменений по заявкам, заказам и бонусным операциям фиксируется в системе +- сведения о товарах, остатках, заказах и статусах могут обновляться из внешней учетной системы + +#pagebreak(weak: true) += 2. Основания для разработки и нормативные материалы + + +== 2.1 Основания для разработки + + +Разработка программного продукта выполняется на основании следующих документов: + +- договор на разработку программного продукта №28/04-26ПО от 28 апреля 2026 года +- приложение №1 к договору: спецификация основных требований к программному обеспечению Личный кабинет Фрегат +- согласованные требования заказчика к клиентскому, менеджерскому, бонусному и интеграционному контурам + +== 2.2 Нормативные и методические материалы + + +Настоящее техническое задание подготовлено как документ для согласования требований к разработке веб-программного продукта. + +Настоящий документ устанавливает требования к программному продукту применительно к современному веб-решению с разграничением ролей, интеграцией с учетной системой, журналированием событий и поддержкой клиентских и менеджерских сценариев. + +== 2.3 Исходные материалы для детализации требований + + +При разработке технического задания использованы следующие исходные материалы: + +- договорная документация заказчика +- согласованные бизнес-сценарии работы клиента и менеджера +- перечень разделов личного кабинета +- перечень основных товарных направлений и параметров каталога +- требования к обмену данными с учетной системой 1С +- требования к уведомлениям, бонусной программе и административным настройкам + +== 2.4 Назначение настоящего документа + + +Настоящий документ предназначен для: + +- фиксации полного объема требований к программному продукту +- определения состава реализуемых функций +- определения состава данных и интеграционных точек +- определения требований к пользовательским и административным интерфейсам +- определения критериев приемки результата работ +- определения состава артефактов, передаваемых заказчику + +#pagebreak(weak: true) += 3. Назначение и границы программного продукта + + +== 3.1 Назначение системы + + +Программный продукт Личный кабинет Фрегат предназначен для организации единого цифрового канала взаимодействия между ООО Фрегат Групп и клиентами компании. + +Система должна обеспечивать: + +- подключение новых клиентов и ведение клиентских учетных записей +- предоставление клиенту каталога готовой продукции без публичного отображения цены +- прием заявок на заказ готовой продукции +- прием заявок на расчет продукции с индивидуальными параметрами +- обработку заявок менеджером с публикацией стоимости и условий поставки +- сопровождение заказов по статусам +- информирование клиентов о значимых изменениях +- ведение бонусной и реферальной программы + +== 3.2 Границы программного продукта + + +В состав программного продукта входят следующие функциональные области: + +- регистрация и подключение клиента +- профиль клиента и данные компании +- каталог готовой продукции +- карточка товара и выбор параметров +- корзина и заявка на заказ +- заявка на расчет индивидуальной продукции +- обработка заявок менеджером +- список заказов и карточка заказа +- уведомления +- бонусный кабинет +- административные настройки + +== 3.3 Функции, не входящие в состав программного продукта + + +Программный продукт не предназначен для выполнения следующих функций: + +- самостоятельного ценообразования клиентом +- ведения бухгалтерского учета +- выполнения функций публичного B2C-магазина +- прямого редактирования клиентом внутренних бизнес-правил компании +- замены учетной системы 1С как первичного источника учетных данных + +== 3.4 Пользовательские контуры + + +В системе должны быть предусмотрены следующие пользовательские контуры: + +- клиентский контур +- менеджерский контур +- административный контур суперменеджера + +Клиентский контур предназначен для работы клиента с каталогом, заявками, заказами, уведомлениями и бонусным кабинетом. + +Менеджерский контур предназначен для обработки клиентских заявок, публикации коммерческих условий, сопровождения заказов, работы с клиентскими карточками и бонусными операциями. + +Административный контур предназначен для управления настройками каталога, уведомлений, интеграционных параметров и отдельных сервисных настроек системы. + +== 3.5 Основные бизнес-сценарии + + +=== 3.5.1 Подключение клиента + + ++ Потенциальный клиент получает приглашение на регистрацию либо подает заявку на подключение самостоятельно. ++ Менеджер проверяет сведения о клиенте и принимает решение о подтверждении либо отклонении заявки. ++ При положительном решении клиенту предоставляется доступ к завершению регистрации. ++ После завершения регистрации клиент получает доступ к личному кабинету. + +=== 3.5.2 Заказ готовой продукции + + ++ Клиент открывает каталог готовой продукции. ++ Клиент выбирает товарное направление. ++ Клиент выбирает параметры товара. ++ Клиент просматривает доступные варианты и остатки. ++ Клиент добавляет выбранные позиции в корзину. ++ Клиент отправляет заявку на заказ. ++ Менеджер указывает стоимость, условия поставки и комментарий. ++ Система публикует обновленные условия клиенту. + +=== 3.5.3 Заявка на расчет индивидуальной продукции + + ++ Клиент переходит в режим расчета индивидуальной продукции. ++ Клиент указывает параметры требуемого изделия. ++ Клиент направляет заявку менеджеру. ++ Менеджер подготавливает коммерческие условия и публикует их клиенту. + +=== 3.5.4 Сопровождение заказа + + ++ Заказ получает уникальный идентификатор и статус. ++ Данные по заказу обновляются в системе по мере обработки. ++ Клиент отслеживает состав, статус, сроки и иные существенные сведения. ++ При изменении статуса либо условий система направляет уведомления. + +=== 3.5.5 Бонусная и реферальная программа + + ++ Для клиента фиксируются правила участия в бонусной программе и, при наличии, реферальные связи. ++ Система ведет учет начислений, списаний и остатка бонусов. ++ Клиент получает доступ к истории бонусных операций. ++ Менеджер обрабатывает заявки, связанные с использованием либо выводом бонусов, в пределах установленных правил. + +#pagebreak(weak: true) += 4. Функциональные требования + + +== 4.1 Требования к регистрации и подключению клиентов + + +Система должна поддерживать два базовых сценария подключения клиента: + +- регистрация по персональному приглашению +- самостоятельная заявка на подключение + +Функциональные требования: + ++ Менеджер должен иметь возможность направить клиенту приглашение на регистрацию по электронной почте. ++ Клиент должен иметь возможность завершить регистрацию по персональной ссылке. ++ Клиент должен иметь возможность подать заявку на подключение через публичную форму. ++ Самостоятельная заявка должна поступать в менеджерский контур на рассмотрение. ++ Менеджер должен иметь возможность подтвердить либо отклонить заявку на подключение. ++ При подтверждении заявки система должна предоставить клиенту возможность завершить регистрацию. ++ После завершения регистрации клиент должен получить доступ к личному кабинету. ++ Система должна поддерживать подключение доступных каналов уведомлений для клиентской учетной записи. + +== 4.2 Требования к каталогу готовой продукции + + +Система должна предоставлять клиенту каталог готовой продукции без отображения цены до обработки менеджером. + +Функциональные требования: + ++ Система должна отображать список товарных направлений. ++ Для каждого товарного направления система должна предоставлять отдельную карточку товара. ++ В карточке товара система должна отображать параметры выбора, применимые к данному типу продукции. ++ В карточке товара система должна отображать доступные стандартные варианты. ++ Для каждой доступной позиции система должна отображать складские остатки. ++ Система должна позволять клиенту выбрать параметры и добавить позицию в корзину. ++ Система должна исключать отображение стоимости до момента публикации условий менеджером. ++ Для параметров товара система должна отображать пояснения, помогающие клиенту понять назначение параметра и ограничения выбора. + +== 4.3 Требования к параметрам каталога и кастомизации + + +Система должна поддерживать настройку параметров по каждому товарному направлению. + +Функциональные требования: + ++ Для каждого типа продукции должен задаваться перечень стандартных параметров выбора. ++ Для параметров длины должна поддерживаться настройка доступных стандартных значений. ++ Для параметров длины должна поддерживаться возможность индивидуального значения при наличии соответствующего разрешения. ++ Для параметров втулки должна поддерживаться возможность заказа втулки с логотипом при наличии соответствующего разрешения. ++ Для параметров надписи должна поддерживаться возможность заказа индивидуального нанесения при наличии соответствующего разрешения. ++ Наборы стандартных параметров должны редактироваться в административном контуре. ++ Изменение набора стандартных параметров не должно приводить к потере уже сохраненных заказных данных. + +== 4.4 Требования к корзине и заявке на заказ + + +Система должна позволять клиенту собрать корзину и направить заявку на заказ. + +Функциональные требования: + ++ Клиент должен видеть перечень выбранных позиций. ++ Для каждой позиции клиент должен иметь возможность изменить количество. ++ Клиент должен иметь возможность удалить позицию из корзины. ++ Клиент должен иметь возможность направить заявку менеджеру. ++ После отправки заявки система должна зафиксировать состав, параметры и количество позиций. ++ Для заявки должны сохраняться дата создания, инициатор и закрепленный менеджер. ++ До обработки менеджером стоимость в заявке не должна отображаться клиенту. + +== 4.5 Требования к обработке заявки менеджером + + +Менеджер должен иметь возможность обработать клиентскую заявку вручную. + +Функциональные требования: + ++ Менеджер должен видеть состав заявки и параметры заказанных позиций. ++ Менеджер должен видеть карточку клиента и сведения о контрагенте. ++ Менеджер должен иметь возможность указать стоимость. ++ Менеджер должен иметь возможность указать условия поставки и доставки. ++ Менеджер должен иметь возможность оставить комментарий к заявке. ++ Менеджер должен иметь возможность опубликовать согласованные условия клиенту. ++ До перевода заявки в работу менеджер должен иметь возможность скорректировать опубликованные условия. ++ Менеджер должен иметь возможность перевести заявку в работу. ++ Менеджер должен иметь возможность отменить заявку с фиксацией основания отмены. + +== 4.6 Требования к заявке на расчет индивидуальной продукции + + +Система должна поддерживать отдельный сценарий расчета продукции с индивидуальными параметрами. + +Функциональные требования: + ++ Клиент должен иметь возможность перейти из каталога в сценарий расчета индивидуальной продукции. ++ Клиент должен иметь возможность указать параметры изделия. ++ Клиент должен иметь возможность приложить комментарий к заявке. ++ Клиент должен иметь возможность направить заявку менеджеру. ++ Менеджер должен иметь возможность обработать такую заявку по правилам, аналогичным заявке на заказ. ++ Стоимость и условия поставки должны публиковаться клиенту только после ручной обработки менеджером. + +Минимальный состав параметров расчетной заявки должен поддерживать: + +- тип продукции +- ширину +- длину +- толщину +- цвет +- надпись или маркировку +- иные параметры в зависимости от вида продукции +- текстовый комментарий клиента + +== 4.7 Требования к статусам заявок + + +Система должна обеспечивать сквозное сопровождение заявок по статусам. + +Для заявок на заказ и заявок на расчет должны поддерживаться следующие базовые статусы: + +- создана +- направлена менеджеру +- обработана менеджером +- условия опубликованы +- в работе +- отменена + +Для каждого изменения статуса система должна сохранять: + +- предыдущее состояние +- новое состояние +- дату и время изменения +- пользователя или источник, выполнивший изменение +- комментарий, если он предусмотрен сценарием + +== 4.8 Требования к заказам и их сопровождению + + +Система должна предоставлять клиенту и менеджеру доступ к списку заказов, карточке каждого заказа и актуальным учетным сведениям, полученным из 1С. + +Функциональные требования: + ++ Система должна отображать перечень заказов клиента. ++ Система должна поддерживать фильтрацию заказов по периоду и статусу. ++ Для каждого заказа система должна предоставлять отдельную карточку. ++ В карточке заказа должны отображаться состав, статус, стоимость, условия поставки и история изменений. ++ В карточке заказа должна отображаться дата актуальности данных. ++ При наличии обновлений из внешней системы сведения по заказу должны синхронизироваться и отображаться пользователю. ++ Система должна отображать текущую задолженность клиента, если такие сведения получены из 1С. ++ Для задолженности должна отображаться дата актуальности данных. + +== 4.9 Требования к уведомлениям + + +Система должна поддерживать уведомления по нескольким каналам связи. + +Поддерживаемые каналы: + +- электронная почта +- Telegram +- Max + +Система должна поддерживать уведомления по следующим событиям: + +- приглашение к регистрации +- подтверждение либо отклонение заявки на подключение +- публикация условий по заявке +- изменение статуса заказа +- изменение бонусного баланса +- обработка заявки на использование либо вывод бонусов + +== 4.10 Требования к бонусной и реферальной программе + + +Система должна включать бонусный контур как самостоятельную функциональную область с отдельным пользовательским интерфейсом. + +Функциональные требования: + ++ Система должна хранить правила участия клиента в бонусной программе. ++ Система должна поддерживать фиксацию реферальных связей. ++ Система должна хранить начисления, списания и текущий остаток бонусов. ++ Клиент должен видеть текущий бонусный баланс. ++ Клиент должен видеть историю бонусных операций. ++ Клиент должен иметь возможность использовать бонусы в пределах установленных правил. ++ Клиент должен иметь возможность подать заявку на вывод либо иную операцию, если это предусмотрено правилами программы. ++ Менеджер должен иметь возможность обрабатывать операции бонусного контура. ++ Система должна уведомлять клиента об изменениях бонусного состояния. + +== 4.11 Требования к административным настройкам + + +Система должна содержать административные разделы для управления следующими объектами: + +- параметрами каталога +- пользовательскими описаниями параметров +- шаблонами уведомлений +- параметрами синхронизации +- отдельными настройками бонусного контура + +#pagebreak(weak: true) += 5. Требования к ролям и правам доступа + + +== 5.1 Состав ролей + + +В системе должны быть предусмотрены следующие роли пользователей: + +- клиент +- менеджер +- суперменеджер + +== 5.2 Роль клиента + + +Пользователь с ролью Клиент представляет организацию-контрагента и работает только с данными своей компании. + +Клиенту должны быть доступны следующие действия: + +- завершение регистрации по персональному приглашению +- подача заявки на подключение +- просмотр и изменение разрешенных профильных данных +- подключение доступных каналов уведомлений +- просмотр каталога готовой продукции +- выбор параметров товара +- добавление позиций в корзину +- отправка заявки на заказ +- отправка заявки на расчет +- просмотр списка заявок и заказов +- просмотр карточки заявки и карточки заказа +- просмотр истории уведомлений +- просмотр бонусного баланса и истории бонусных операций +- подача заявки на использование либо вывод бонусов при наличии соответствующих правил + +== 5.3 Роль менеджера + + +Пользователь с ролью Менеджер представляет сотрудника компании, закрепленного за клиентами. + +Менеджеру должны быть доступны следующие действия: + +- рассмотрение заявок на подключение клиентов +- подтверждение либо отклонение заявок на подключение +- привязка клиента к контрагенту и назначение ответственного сопровождения +- просмотр и обработка заявок на заказ +- просмотр и обработка заявок на расчет +- указание стоимости, условий поставки и сопроводительного комментария +- публикация условий клиенту +- перевод заявки в работу +- отмена заявки при наличии оснований +- просмотр карточек клиентов, заявок и заказов +- выполнение операций в бонусном контуре в пределах полномочий + +== 5.4 Роль суперменеджера + + +Пользователь с ролью Суперменеджер обладает всеми правами менеджера и дополнительными административными полномочиями. + +Суперменеджеру должны быть доступны следующие действия: + +- доступ ко всем клиентам, заявкам и заказам +- управление параметрами каталога +- управление описаниями и наборами параметров товаров +- управление настройками уведомлений +- управление параметрами интеграции и синхронизации +- расширенное управление бонусным и реферальным контуром + +== 5.5 Матрица доступа + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Действие*], + [*Клиент*], + [*Менеджер*], + [*Суперменеджер*], + [Завершение регистрации], + [Да], + [Нет], + [Нет], + [Подача заявки на подключение], + [Да], + [Нет], + [Нет], + [Просмотр каталога], + [Да], + [Да], + [Да], + [Выбор параметров и добавление в корзину], + [Да], + [Нет], + [Нет], + [Отправка заявки на заказ], + [Да], + [Нет], + [Нет], + [Отправка заявки на расчет], + [Да], + [Нет], + [Нет], + [Назначение стоимости и условий поставки], + [Нет], + [Да], + [Да], + [Публикация условий клиенту], + [Нет], + [Да], + [Да], + [Перевод заявки в работу], + [Нет], + [Да], + [Да], + [Отмена заявки], + [Нет], + [Да], + [Да], + [Управление параметрами каталога], + [Нет], + [Нет], + [Да], + [Управление уведомлениями], + [Нет], + [Нет], + [Да], + [Управление параметрами синхронизации], + [Нет], + [Нет], + [Да], + [Управление бонусными правилами], + [Нет], + [Да], + [Да] + ) +] + + +== 5.6 Ограничения доступа и требования к безопасности + + +Система должна обеспечивать: + +- раздельные интерфейсы для клиентского и менеджерского контуров +- доступ клиента только к данным собственного контрагента +- ограничение административных функций в соответствии с ролью +- журналирование значимых пользовательских действий +- хранение истории изменения статусов, условий заявок и бонусных операций + +#pagebreak(weak: true) += 6. Требования к данным и сущностям + + +== 6.1 Общие требования к данным + + +Основное хранилище данных программного продукта реализуется на PostgreSQL. Прикладной доступ к данным осуществляется через Prisma ORM. + +Система должна обеспечивать хранение: + +- пользователей и ролей +- компаний и профилей контрагентов +- адресов доставки +- каталога и складских остатков +- корзины и ее позиций +- заказов и расчетных заявок +- событий изменения статусов +- подключений мессенджеров +- бонусных и реферальных сущностей + +В прикладной реализации должны использоваться фактические сущности базы данных, определенные в schema.prisma. Наименование сущностей в документации и в базе данных должно сопоставляться однозначно. + +== 6.2 Справочник сущностей базы данных + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Модель в базе данных*], + [*Русское наименование*], + [*Назначение*], + [Company], + [Компания], + [Клиентская организация], + [User], + [Пользователь], + [Учетная запись клиента, менеджера или суперменеджера], + [DeliveryAddress], + [Адрес доставки], + [Справочник адресов доставки клиента], + [CounterpartyProfile], + [Профиль контрагента], + [Юридические и банковские реквизиты клиента], + [RegistrationRequest], + [Заявка на подключение], + [Самостоятельная заявка клиента на подключение], + [Invitation], + [Приглашение], + [Менеджерское приглашение на регистрацию], + [MessengerConnection], + [Подключение мессенджера], + [Связка пользователя с Telegram или MAX], + [Product], + [Товар], + [Карточка товарной позиции каталога], + [CatalogProductTypeSetting], + [Настройки типа товара], + [Правила параметров и кастомизации по товарному направлению], + [Cart], + [Корзина], + [Корзина клиента], + [CartItem], + [Позиция корзины], + [Конкретный выбранный товар в корзине], + [Warehouse], + [Склад], + [Справочник складов], + [ProductStock], + [Складской остаток], + [Остаток товара на складе], + [Order], + [Заказ / заявка], + [Единая заказная сущность для готовой продукции и расчета], + [OrderItem], + [Позиция заказа], + [Состав заказа], + [OrderStatusEvent], + [Событие статуса заказа], + [История изменения статусов], + [ReferralLink], + [Реферальная связь], + [Связь между рекомендателем и приглашенным клиентом], + [BonusTransaction], + [Бонусная транзакция], + [Начисление или списание бонусов], + [RewardWithdrawalRequest], + [Заявка на вывод бонусов], + [Заявка клиента на использование или вывод бонусов] + ) +] + + +== 6.3 Служебные перечисления и статусы + + +В модели данных используются следующие перечисления: + +- UserRole: CLIENT, MANAGER, SUPER_MANAGER +- RegistrationStatus: PENDING, APPROVED, REJECTED +- MessengerType: TELEGRAM, MAX +- OrderKind: READY, CALCULATION +- OrderStatus: NEW, MANAGER_PROCESSING, WAITING_DOUBLE_CONFIRM, CLIENT_REJECTED, MANAGER_REJECTED, MANAGER_BLOCKED, CONFIRMED, IN_PROGRESS, COMPLETED +- WithdrawalStatus: PENDING, APPROVED, REJECTED + +== 6.4 Пользователи и компании + + +=== 6.4.1 Company + + +Русское наименование: Компания + +Назначение: + +- хранение клиентской организации +- объединение пользователей одной компании + +Основные поля: + +- id +- name +- inn +- createdAt +- updatedAt + +Связи: + +- одна компания связана со многими пользователями + +=== 6.4.2 User + + +Русское наименование: Пользователь + +Назначение: + +- хранение клиентской, менеджерской или административной учетной записи +- связывание пользователя с заказами, корзиной, бонусами и адресами + +Основные поля: + +- id +- email +- fullName +- role +- companyId +- defaultDeliveryAddressId +- createdAt +- updatedAt + +Связи: + +- пользователь может быть связан с компанией +- пользователь может иметь профиль контрагента +- пользователь может иметь адреса доставки +- пользователь может иметь корзину +- пользователь может выступать клиентом или менеджером в заказах +- пользователь может иметь бонусные операции и заявки на вывод + +=== 6.4.3 DeliveryAddress + + +Русское наименование: Адрес доставки + +Назначение: + +- хранение адресов доставки клиента +- выбор адреса по умолчанию для корзины и заказов + +Основные поля: + +- id +- userId +- label +- address +- unrestrictedValue +- fiasId +- createdAt +- updatedAt + +=== 6.4.4 CounterpartyProfile + + +Русское наименование: Профиль контрагента + +Назначение: + +- хранение полных реквизитов клиента для договоров, счетов и поставки + +Основные поля: + +- id +- userId +- companyName +- companyFullName +- inn +- kpp +- ogrn +- legalAddress +- bankName +- bik +- correspondentAccount +- checkingAccount +- signerFullName +- signerPosition +- signerBasis +- createdAt +- updatedAt + +=== 6.4.5 RegistrationRequest + + +Русское наименование: Заявка на подключение + +Назначение: + +- хранение самостоятельной заявки клиента на подключение + +Основные поля: + +- id +- companyName +- inn +- contactName +- email +- status +- rejectionReason +- requesterId +- reviewedById +- createdAt +- updatedAt + +=== 6.4.6 Invitation + + +Русское наименование: Приглашение + +Назначение: + +- хранение менеджерского приглашения клиента на регистрацию + +Основные поля: + +- id +- token +- email +- companyName +- managerId +- acceptedById +- expiresAt +- acceptedAt +- createdAt + +=== 6.4.7 MessengerConnection + + +Русское наименование: Подключение мессенджера + +Назначение: + +- хранение подключенного Telegram или MAX-канала пользователя + +Основные поля: + +- id +- userId +- type +- channelId +- displayName +- username +- avatarFileId +- avatarFileUniqueId +- isActive +- createdAt + +== 6.5 Каталог и складской контур + + +=== 6.5.1 Product + + +Русское наименование: Товар + +Назначение: + +- хранение карточки товарной позиции каталога +- хранение параметров товара и признаков кастомизации + +Основные поля: + +- id +- sku +- name +- productType +- widthMm +- lengthM +- thicknessMicron +- sleeveBrand +- quantityPerBox +- tags +- description +- isCustomizable +- isActive +- createdAt +- updatedAt + +=== 6.5.2 CatalogProductTypeSetting + + +Русское наименование: Настройки типа товара + +Назначение: + +- хранение правил параметров по товарному направлению +- хранение разрешений на кастомизацию + +Основные поля: + +- id +- productType +- showQuantityPerBox +- allowCustomLength +- customLengthMinM +- customLengthMaxM +- customLengthStepM +- allowCustomSleeveBrand +- allowCustomLabel +- widthOptionsMm +- lengthOptionsM +- thicknessOptionsMicron +- sleeveOptions +- colorOptions +- labelOptions +- createdAt +- updatedAt + +=== 6.5.3 Warehouse + + +Русское наименование: Склад + +Назначение: + +- хранение справочника складов + +Основные поля: + +- id +- code +- name +- createdAt +- updatedAt + +=== 6.5.4 ProductStock + + +Русское наименование: Складской остаток + +Назначение: + +- хранение остатка товара на конкретном складе + +Основные поля: + +- id +- productId +- warehouseId +- availableQty +- updatedAt + +== 6.6 Корзина, заявки и заказы + + +=== 6.6.1 Cart + + +Русское наименование: Корзина + +Назначение: + +- хранение текущего набора выбранных клиентом позиций + +Основные поля: + +- id +- userId +- deliveryAddressId +- createdAt +- updatedAt + +=== 6.6.2 CartItem + + +Русское наименование: Позиция корзины + +Назначение: + +- хранение одной выбранной клиентом позиции с параметрами и количеством + +Основные поля: + +- id +- cartId +- productId +- productName +- sku +- isCustomizable +- quantity +- parameters +- createdAt +- updatedAt + +=== 6.6.3 Order + + +Русское наименование: Заказ / заявка + +Назначение: + +- хранение готовой заказной заявки и расчетной заявки в единой сущности +- хранение согласованных менеджером условий и статуса работы + +Основные поля: + +- id +- code +- kind +- customerId +- deliveryAddressId +- deliveryAddress +- managerId +- status +- clientApproved +- managerApproved +- blockReason +- deliveryTerms +- deliveryFee +- totalPrice +- calculationPayload +- createdAt +- updatedAt + +Комментарий к модели: + +- kind = READY означает сценарий заказа готовой продукции +- kind = CALCULATION означает сценарий расчета индивидуальной продукции +- поле calculationPayload хранит параметры расчетной заявки + +=== 6.6.4 OrderItem + + +Русское наименование: Позиция заказа + +Назначение: + +- хранение состава заказа + +Основные поля: + +- id +- orderId +- productId +- productName +- quantity +- unitPrice +- createdAt + +=== 6.6.5 OrderStatusEvent + + +Русское наименование: Событие статуса заказа + +Назначение: + +- хранение истории изменения статусов заказа или заявки + +Основные поля: + +- id +- orderId +- status +- actorUserId +- note +- createdAt + +== 6.7 Бонусный и реферальный контур + + +=== 6.7.1 ReferralLink + + +Русское наименование: Реферальная связь + +Назначение: + +- фиксация связи между рекомендателем и приглашенным клиентом + +Основные поля: + +- id +- referrerId +- refereeId +- createdById +- bonusPercent +- createdAt + +=== 6.7.2 BonusTransaction + + +Русское наименование: Бонусная транзакция + +Назначение: + +- хранение начисления или списания бонусов + +Основные поля: + +- id +- userId +- amount +- reason +- orderId +- referralLinkId +- createdAt + +=== 6.7.3 RewardWithdrawalRequest + + +Русское наименование: Заявка на вывод бонусов + +Назначение: + +- хранение заявки клиента на использование или вывод бонусов + +Основные поля: + +- id +- requesterId +- amount +- status +- reviewedById +- reviewComment +- createdAt +- updatedAt + +== 6.8 Основные связи между сущностями + + +Укрупненная структура связей определяется следующими правилами: + +- Company объединяет пользователей одной клиентской организации +- User связан с CounterpartyProfile, DeliveryAddress, MessengerConnection, Cart, Order, BonusTransaction и RewardWithdrawalRequest +- Cart содержит набор CartItem, привязанных к конкретным Product +- Order содержит набор OrderItem и историю OrderStatusEvent +- Product связан с остатками ProductStock, распределенными по сущностям Warehouse +- настройки параметров по товарному направлению хранятся в CatalogProductTypeSetting +- реферальные связи реализуются через ReferralLink, связывающий одного пользователя с другим пользователем + +#pagebreak(weak: true) += 7. Требования к интерфейсу и прототипам + + +== 7.1 Карта экранов + + +Ниже приведен базовый состав экранов, подлежащих реализации и сопровождению в рамках программного продукта. + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Раздел*], + [*Маршрут*], + [*Роль*], + [*Назначение*], + [Главная страница], + [/], + [клиент], + [стартовая точка, быстрые действия, актуальные события], + [Каталог], + [/products], + [клиент], + [выбор товарного направления], + [Карточка товара], + [/products/\[slug\]], + [клиент], + [выбор параметров, просмотр вариантов, добавление в корзину], + [Корзина], + [/cart], + [клиент], + [формирование и отправка заявки], + [Список заказов клиента], + [/client-orders], + [клиент], + [просмотр истории заявок и заказов], + [Карточка заказа клиента], + [/client-orders/\[id\]], + [клиент], + [просмотр статуса, состава, условий и истории], + [Профиль], + [/profile], + [клиент], + [базовые данные учетной записи], + [Контрагент], + [/profile/counterparty], + [клиент], + [реквизиты и юридические данные], + [Адреса доставки], + [/profile/addresses], + [клиент], + [адресный справочник], + [Уведомления], + [/notifications], + [клиент], + [история уведомлений], + [Бонусный кабинет], + [/bonus-program], + [клиент], + [баланс, история и бонусные действия], + [Список клиентов], + [/clients], + [менеджер], + [клиентская база], + [Карточка клиента], + [/clients/\[id\]], + [менеджер], + [данные компании, заказы, бонусы], + [Приглашение клиента], + [/clients/invite], + [менеджер], + [выдача приглашения на регистрацию], + [Список заказов], + [/orders], + [менеджер], + [обработка заказного контура], + [Карточка заказа], + [/orders/\[id\]], + [менеджер], + [обработка условий, статуса и доставки], + [Настройки каталога], + [/catalog-settings], + [суперменеджер], + [параметры товарных направлений], + [Настройки синхронизации], + [/settings-sync], + [суперменеджер], + [мониторинг и управление обменом], + [Бонусная система], + [/bonus-system/\\\*], + [менеджер/суперменеджер], + [рефералы, транзакции, выводы] + ) +] + + +== 7.2 Маршруты и экранные формы + + +Ниже приведен перечень экранных форм, предусмотренных в составе frontend-контура программного продукта. + +=== 7.2.1 Публичные и клиентские страницы + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Маршрут*], + [*Экран*], + [*Назначение*], + [/], + [Главная страница], + [Стартовая страница личного кабинета], + [/login], + [Вход], + [Вход и первичный сценарий доступа], + [/products], + [Каталог продукции], + [Список товарных направлений], + [/products/\[slug\]], + [Карточка товара], + [Выбор параметров, просмотр вариантов, добавление в корзину], + [/cart], + [Корзина], + [Состав выбранных позиций и отправка заявки], + [/client-orders], + [Список заказов клиента], + [История заявок и заказов клиента], + [/client-orders/\[id\]], + [Карточка заказа клиента], + [Детали конкретного заказа клиента], + [/notifications], + [Уведомления], + [Список системных уведомлений], + [/bonus-program], + [Бонусный кабинет], + [Бонусный баланс, подарочные карты и бонусные действия] + ) +] + + +=== 7.2.2 Профиль клиента + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Маршрут*], + [*Экран*], + [*Назначение*], + [/profile], + [Профиль], + [Основные данные пользователя], + [/profile/counterparty], + [Реквизиты контрагента], + [Юридические и банковские данные], + [/profile/addresses], + [Адреса доставки], + [Список адресов доставки], + [/profile/addresses/new], + [Новый адрес доставки], + [Создание адреса доставки], + [/profile/notifications], + [Настройки уведомлений], + [Подключение и настройка каналов уведомлений], + [/profile/notifications/success], + [Успешное подключение уведомлений], + [Финальный экран сценария подключения канала] + ) +] + + +=== 7.2.3 Менеджерские и административные страницы + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Маршрут*], + [*Экран*], + [*Назначение*], + [/clients], + [Клиенты], + [Список клиентских компаний и пользователей], + [/clients/\[id\]], + [Карточка клиента], + [Детали клиента, его заказы и бонусные данные], + [/clients/invite], + [Пригласить клиента], + [Создание приглашения на регистрацию], + [/orders], + [Список заказов], + [Очередь заказов и заявок для менеджера], + [/orders/\[id\]], + [Карточка заказа], + [Обработка стоимости, условий поставки и статуса], + [/catalog-settings], + [Настройки каталога], + [Параметры товарных направлений и кастомизации], + [/settings-sync], + [1С / синхронизация], + [Управление и мониторинг синхронизации], + [/messages], + [Сообщения], + [Шаблоны и тексты менеджерских сообщений] + ) +] + + +=== 7.2.4 Бонусный менеджерский контур + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Маршрут*], + [*Экран*], + [*Назначение*], + [/bonus-system], + [Бонусная система], + [Список клиентов и бонусных сущностей], + [/bonus-system/\[userId\]], + [Карточка бонусного счета клиента], + [История и состояние бонусного счета], + [/bonus-system/referrals/new], + [Создать бонусный счет], + [Создание реферальной связи], + [/bonus-system/transactions/new], + [Добавить бонусную транзакцию], + [Ручное начисление или списание], + [/bonus-system/withdrawals/\[id\]], + [Проверка заявки на вывод], + [Рассмотрение заявки клиента на вывод бонусов] + ) +] + + +== 7.3 Общие требования к экранным формам + + +Экранные формы должны обеспечивать: + +- однозначное понимание текущего объекта работы +- явное отображение статуса объекта +- соответствие доступных действий роли пользователя +- единый визуальный подход для клиентского и менеджерского контуров +- понятное отображение параметров товара, условий заказа и бонусных операций + +Для экранов, связанных с товарами, заявками и заказами, должны выполняться дополнительные требования: + +- цена не отображается клиенту до публикации условий менеджером +- остатки и доступные варианты отображаются в наглядном виде +- пользователь понимает ограничения выбора и возможность кастомизации + +Ниже приведены низкодетализированные wireframe-прототипы. Они используются как визуальная фиксация состава страниц, ключевых блоков и пользовательских действий. + +== 7.4 Клиентские экранные формы + + +=== 7.4.1 Главная страница клиента + + +Назначение страницы: + +- вход в основные разделы личного кабинета +- отображение актуальных действий и событий + +Состав страницы: + +- верхняя навигация +- быстрые переходы по основным разделам +- блок актуальных заказов и заявок +- блок последних уведомлений +- блок бонусной информации при наличии подключенного бонусного контура +- индикатор статуса заполненности профиля клиента + +Wireframe-прототип: + +#figure( + image("public/prototypes/dashboard.svg", width: 100%), + caption: [Прототип главной страницы клиента], +) + + +=== 7.4.2 Каталог продукции + + +Назначение страницы: + +- отображение товарных направлений +- переход к карточке выбранного типа товара + +Состав страницы: + +- заголовок раздела +- поиск при необходимости +- сетка карточек товарных направлений +- карточка каждого товарного направления с изображением и наименованием +- переход в карточку выбранного товарного направления + +Wireframe-прототип: + +#figure( + image("public/prototypes/catalog-grid.svg", width: 100%), + caption: [Прототип каталога продукции], +) + + +=== 7.4.3 Карточка товара + + +Назначение страницы: + +- выбор параметров товара +- просмотр стандартных вариантов +- просмотр складских остатков +- добавление выбранной позиции в корзину + +Состав страницы: + +- заголовок товара +- изображение товара +- блок выбора параметров +- блок пояснений по параметрам +- блок индивидуальных возможностей, если они разрешены +- блок добавления в корзину +- таблица доступных вариантов +- блок навигации к соседним товарным направлениям + +Маршрут страницы: + +- /products/[slug] + +Wireframe-прототип: + +#figure( + image("public/prototypes/product-card.svg", width: 100%), + caption: [Прототип карточки товара], +) + + +Состав блока выбора параметров: + +- ширина +- длина +- толщина +- тип втулки +- цвет +- надпись +- индивидуальные опции при наличии разрешения + +Состав блока пояснений: + +- описание каждого параметра простым деловым языком +- ограничения по индивидуальной длине +- правила по втулке с логотипом +- правила по нанесению индивидуальной надписи + +=== 7.4.4 Корзина + + +Назначение страницы: + +- просмотр выбранных позиций +- изменение количества +- удаление позиции +- отправка заявки на заказ + +Состав страницы: + +- список позиций +- параметры и количество +- комментарий клиента +- действие отправки заявки +- выбранный адрес доставки +- итоговая сводка по количеству позиций + +Wireframe-прототип: + +#figure( + image("public/prototypes/cart.svg", width: 100%), + caption: [Прототип корзины], +) + + +=== 7.4.5 Карточка заявки или заказа + + +Назначение страницы: + +- просмотр состава +- просмотр статуса +- просмотр стоимости и условий поставки после публикации +- просмотр истории изменений + +Wireframe-прототип: + +#figure( + image("public/prototypes/client-order.svg", width: 100%), + caption: [Прототип карточки заявки или заказа], +) + + +Состав страницы: + +- номер документа +- статус +- состав позиций +- стоимость после публикации менеджером +- условия поставки и доставки +- история статусов +- системные комментарии + +=== 7.4.6 Страница логина и регистрации + + +Назначение страницы: + +- запуск входа в систему +- запуск самостоятельной заявки на подключение +- запуск сценариев входа через мессенджеры + +Состав страницы: + +- форма запроса кода входа +- выбор канала входа +- ссылка на самостоятельную заявку на подключение +- блок пояснения по дальнейшему сценарию доступа + +Wireframe-прототип: + +#figure( + image("public/prototypes/login.svg", width: 100%), + caption: [Прототип страницы логина и подключения], +) + + +=== 7.4.7 Список заказов + + +Назначение страницы: + +- просмотр текущих и архивных заказов +- фильтрация по периоду и статусу + +Состав страницы: + +- фильтры +- таблица заказов +- переход в карточку конкретного заказа + +=== 7.4.8 Уведомления + + +Назначение страницы: + +- просмотр истории уведомлений по заказам, заявкам и бонусным операциям + +=== 7.4.9 Бонусный кабинет + + +Назначение страницы: + +- просмотр текущего бонусного баланса +- просмотр истории операций +- инициирование действий, допускаемых правилами бонусной программы + +Состав страницы: + +- текущий баланс +- история начислений и списаний +- связанные реферальные сведения +- форма подачи заявки на использование либо вывод бонусов +- правила бонусной программы + +Wireframe-прототип: + +#figure( + image("public/prototypes/bonus-cabinet.svg", width: 100%), + caption: [Прототип бонусного кабинета], +) + + +== 7.5 Менеджерские экранные формы + + +=== 7.5.1 Список клиентов + + +Назначение страницы: + +- просмотр клиентской базы +- переход в карточку конкретного клиента + +Состав страницы: + +- поиск и фильтры +- таблица клиентов +- индикаторы активности и количества заказов +- действие приглашения нового клиента + +Wireframe-прототип: + +#figure( + image("public/prototypes/client-list.svg", width: 100%), + caption: [Прототип списка клиентов], +) + + +=== 7.5.2 Карточка клиента + + +Назначение страницы: + +- просмотр сведений о компании +- просмотр истории заявок и заказов +- просмотр бонусных и реферальных данных + +Состав страницы: + +- карточка компании и контактных данных +- реквизиты контрагента +- список заказов клиента +- список бонусных операций +- связанные рефералы + +Wireframe-прототип: + +#figure( + image("public/prototypes/client-card.svg", width: 100%), + caption: [Прототип карточки клиента], +) + + +=== 7.5.3 Карточка обработки заявки + + +Назначение страницы: + +- просмотр состава заявки +- ввод коммерческих условий +- публикация условий клиенту +- перевод заявки в работу либо отмена + +Wireframe-прототип: + +#figure( + image("public/prototypes/manager-order.svg", width: 100%), + caption: [Прототип карточки обработки заявки], +) + + +Состав страницы: + +- клиент и контрагент +- состав позиции или расчетный payload +- стоимость +- доставка +- комментарий менеджера +- история изменений +- блок действий со статусом + +=== 7.5.4 Список заказов менеджера + + +Назначение страницы: + +- просмотр заказов по клиентам +- фильтрация по статусам +- переход к обработке конкретного заказа + +Wireframe-прототип: + +#figure( + image("public/prototypes/manager-orders.svg", width: 100%), + caption: [Прототип списка заказов менеджера], +) + + +=== 7.5.5 Настройки каталога + + +Назначение страницы: + +- управление параметрами товарных направлений +- управление стандартными значениями параметров +- управление возможностями кастомизации +- управление описаниями параметров + +Состав страницы: + +- список товарных направлений +- карточка настроек конкретного направления +- чекбоксы разрешений кастомизации +- списки стандартных параметров +- единое действие сохранения настроек + +Wireframe-прототип: + +#figure( + image("public/prototypes/catalog-settings.svg", width: 100%), + caption: [Прототип настроек каталога], +) + + +=== 7.5.6 Настройки синхронизации и уведомлений + + +Назначение страницы: + +- управление шаблонами уведомлений +- управление параметрами интеграционного обмена + +Состав страницы: + +- список шаблонов уведомлений +- каналы отправки +- статусы последних синхронизаций +- диагностическая информация по обмену + +Wireframe-прототип: + +#figure( + image("public/prototypes/sync-settings.svg", width: 100%), + caption: [Прототип настроек синхронизации], +) + + +== 7.6 Дополнительные профильные и сервисные страницы + + +Помимо основных клиентских и менеджерских экранов, программный продукт включает дополнительные экранные формы: + +- профиль пользователя +- реквизиты контрагента +- список адресов доставки +- создание нового адреса доставки +- настройки уведомлений пользователя +- экран успешного подключения канала уведомлений +- менеджерский экран сообщений +- бонусная система для менеджера +- карточка бонусного счета клиента +- создание реферальной связи +- создание бонусной транзакции +- проверка заявки на вывод бонусов + +Прототипы служебных и дополнительных экранов: + +#figure( + image("public/prototypes/profile.svg", width: 100%), + caption: [Прототип профиля клиента], +) + + +#figure( + image("public/prototypes/bonus-manager.svg", width: 100%), + caption: [Прототип бонусной системы менеджера], +) + + +#pagebreak(weak: true) += 8. Требования к интеграции с 1С и внешним интерфейсам + + +== 8.1 Общие требования к интеграционному контуру + + +Интеграционный слой должен обеспечивать обмен данными между личным кабинетом и внешними системами без потери целостности внутренних сущностей и статусов. + +Интеграционный контур должен обеспечивать: + +- получение данных из 1С +- прием событий от 1С +- передачу во внешние системы данных, необходимых для сопровождения заказов и клиентов, если такой обмен согласован сторонами +- сопоставление внутренних идентификаторов и идентификаторов внешних систем +- регистрацию входящих и исходящих операций обмена +- повторную обработку неуспешных сообщений +- хранение истории обновлений по интеграционным операциям + +== 8.2 Интеграция с 1С + + +Интеграция с 1С должна обеспечивать обмен данными, необходимыми для сопровождения каталога, заказов, статусов, остатков и сведений о задолженности клиента. + +Система должна обеспечивать получение из 1С следующих данных: + +- каталог товаров +- характеристики товаров +- складские остатки +- сведения о заказах +- статусы заказов +- изменения состава, стоимости, доставки и иных существенных параметров заказа +- текущая задолженность клиента +- дата актуальности сведений, полученных из 1С + +1С рассматривается как первичный источник учетных данных по заказам, складам, статусам, стоимости, доставке и задолженности. Личный кабинет отображает эти сведения и фиксирует дату их актуальности. + +== 8.3 События от 1С + + +Система должна поддерживать прием webhook-событий от 1С в согласованном формате. + +Минимальный состав событий: + +- создание нового заказа +- изменение информации по заказу +- изменение статуса заказа +- изменение сроков, условий или параметров доставки +- изменение состава заказа +- изменение сведений о задолженности клиента, если такие данные передаются событийно + +Для каждого события должны фиксироваться: + +- тип события +- внешний идентификатор объекта 1С +- внутренний идентификатор объекта, если сопоставление выполнено +- дата и время события +- источник события +- статус обработки +- текст ошибки при неуспешной обработке + +Система должна защищаться от повторной обработки дублей webhook-событий. + +== 8.4 Методы получения данных из 1С + + +Система должна поддерживать получение данных из 1С через согласованные методы. + +Минимальный состав методов: + +- получение заказов клиента +- получение товарного каталога +- получение характеристик товаров +- получение доступных остатков по складам +- получение статусов и изменений по заказам +- получение текущей задолженности клиента и даты актуальности этих сведений + +Точный набор методов, параметры запросов, формат ответов и ограничения по частоте вызовов фиксируются в интеграционной спецификации. + +== 8.5 Требования к структурам обмена + + +Входные и выходные данные интеграционного слоя должны описываться в структурированном виде и позволять однозначно восстанавливать: + +- тип объекта обмена +- идентификатор объекта +- дату и время события +- полезную нагрузку объекта +- статус обработки +- источник изменения + +Для обмена должны использоваться структурированные payload-форматы, пригодные для сериализации в JSON. + +Точная структура payload, схема подписи запросов и набор обязательных полей согласуются сторонами до начала этапа интеграции с 1С. + +== 8.6 Интеграционные поля и служебные атрибуты + + +Для сущностей, участвующих в обмене, должны поддерживаться: + +- внешний идентификатор учетной системы +- дата последней синхронизации +- источник последнего обновления +- признак успешной или неуспешной обработки +- журнал интеграционных ошибок при наличии +- технический идентификатор последнего обработанного события, если он передается 1С + +== 8.7 Журналирование интеграционных операций + + +Для ключевых операций обмена система должна сохранять: + +- тип объекта +- идентификатор объекта +- предыдущее состояние +- новое состояние +- дату и время изменения +- пользователя либо внешний источник, выполнивший изменение +- статус обработки сообщения +- текст ошибки при наличии + +== 8.8 Требования к защите интеграционного обмена + + +Интеграционные запросы должны выполняться с использованием согласованного механизма авторизации или подписи. + +Система должна отклонять интеграционные запросы, если: + +- отсутствуют обязательные параметры авторизации +- подпись или токен не прошли проверку +- payload не соответствует согласованной структуре +- невозможно определить тип события или объект обработки + +Секреты, используемые для интеграции с 1С, должны храниться только в Vault и передаваться сервисам через runtime-конфигурацию. + +== 8.9 Критерии приемки интеграции с 1С + + +Интеграция с 1С считается готовой в согласованном объеме, если: + +- каталог и характеристики товаров получаются и отображаются в личном кабинете +- остатки по складам отображаются в карточках товаров +- заказы клиента получаются и отображаются с актуальными статусами +- изменения заказа из 1С отображаются в карточке заказа +- текущая задолженность клиента и дата актуальности данных отображаются в предусмотренных интерфейсах +- webhook-события не обрабатываются повторно при дублях +- ошибки интеграционного обмена фиксируются в журнале +- неуспешные сообщения могут быть проанализированы и повторно обработаны в согласованном порядке + +#pagebreak(weak: true) += 9. Техническая архитектура, стек, компоненты и эксплуатационный контур + + +== 9.1 Общая архитектурная схема + + +Программный продукт реализуется по клиент-серверной модели и включает веб-клиент, сервер бизнес-логики, базу данных, модуль интеграции и вспомогательные сервисы уведомлений. + +#figure( + image("public/diagrams/architecture-overview.svg", width: 100%), + caption: [Общая архитектурная схема], +) + + +== 9.2 Состав прикладных сервисов + + +Согласно действующей карте деплоя в составе проекта используются следующие сервисы: + +- web-frontend — клиентский и менеджерский веб-интерфейс +- apollo-backend — сервер GraphQL и бизнес-логика +- vault — централизованное хранилище секретов +- tg-bot — Telegram-контур +- max-bot — MAX-контур +- bonus-bot — бонусный мессенджерный контур + +Основные прикладные сервисы web-frontend и apollo-backend разворачиваются через dokploy_webhook на сервере main. + +== 9.3 Технологический стек фронтенда + + +Клиентская часть программного продукта реализуется на следующих технологиях: + +- Nuxt 4 — прикладной веб-фреймворк +- Vue 3 — библиотека пользовательского интерфейса +- \@nuxtjs/apollo и \@vue/apollo-composable — работа с GraphQL +- GraphQL Code Generator — генерация типизированных GraphQL-документов +- Tailwind CSS и daisyUI — базовая стилизация интерфейсов +- Storybook — контур изоляционного просмотра компонентов +- VitePress — подготовка проектной документации + +== 9.4 Технологический стек серверной части + + +Серверная часть программного продукта реализуется на следующих технологиях: + +- Node.js — среда выполнения +- Express 5 — HTTP-сервер +- Apollo Server 5 — GraphQL-сервер +- Prisma 7 — доступ к данным и ORM-слой +- PostgreSQL — основное хранилище данных +- Zod — валидация структур данных в прикладных сценариях +- Nodemailer — отправка уведомлений по электронной почте + +== 9.5 Архитектура клиентской части + + +Клиентская часть организована по следующим слоям: + +- страницы app/pages — входные экранные формы +- компоненты app/components — переиспользуемые элементы интерфейса +- composables app/composables — клиентская логика и представление данных +- GraphQL-документы graphql/operations — отдельные запросы и мутации +- сгенерированная типизированная схема app/composables/graphql/generated.ts +- серверные proxy и интеграционные обработчики server/api + +Ключевые экранные маршруты текущей реализации: + +- /products и /products/[slug] — каталог и карточка товара +- /cart — корзина +- /client-orders и /client-orders/[id] — клиентские заявки и заказы +- /clients и /clients/[id] — менеджерский контур клиентов +- /orders и /orders/[id] — менеджерский контур заказов +- /catalog-settings — административные настройки каталога +- /bonus-program, /bonus-system/\* — бонусный контур + +== 9.6 Карта слоев и компонентов + + +#figure( + image("public/diagrams/component-map.svg", width: 100%), + caption: [Карта слоев и компонентов], +) + + +== 9.7 Архитектура серверной части + + +Серверная часть организована по следующим основным модулям: + +- src/server.js — инициализация HTTP-сервера и GraphQL-сервера +- src/schema.graphql — контракт GraphQL API +- src/resolvers.js — реализация GraphQL-операций +- src/context.js — построение контекста запроса +- src/auth.js — аутентификация и токены доступа +- src/access.js — правила авторизации и проверки ролей +- src/prisma-client.js — точка подключения Prisma +- src/messenger\*.js, src/telegram\*.js, src/max-mini-app.js — мессенджерный контур и мини-приложения + +== 9.8 Взаимодействие фронтенда и backend + + +Взаимодействие клиентской и серверной части строится через GraphQL API. + +На стороне Nuxt используется серверный proxy-маршрут /api/graphql, который: + +- принимает запросы браузера +- прокидывает cookie и авторизационные заголовки +- перенаправляет запрос в apollo-backend +- возвращает результат в клиентское приложение + +Такой подход позволяет: + +- изолировать прямой backend endpoint от браузерного клиента +- централизованно передавать авторизационные данные +- поддерживать единый клиентский GraphQL endpoint + +== 9.9 Интеграционные и вспомогательные HTTP-точки + + +Помимо GraphQL API, во фронтенд-контуре реализованы вспомогательные серверные маршруты: + +- /api/graphql — proxy в backend GraphQL API +- /api/auth/messenger-start — запуск сценариев messenger login / connect +- /api/dadata/address — подсказки адресов +- /api/dadata/bank — подсказки банковских реквизитов +- /api/dadata/party — подсказки контрагентов +- /api/messenger-avatar/[connectionId] — выдача изображений, связанных с мессенджерными подключениями + +== 9.10 Компонентные требования к реализации + + +Архитектура программного продукта должна сохранять следующие правила: + +- экранная логика должна находиться на уровне страниц и composables +- переиспользуемые элементы интерфейса должны быть вынесены в компоненты +- каждый GraphQL-документ должен храниться в отдельном .graphql файле +- клиентский код должен использовать сгенерированные типизированные документы +- серверная логика доступа к данным должна проходить через Prisma +- бизнес-правила доступа должны контролироваться серверной частью, а не только интерфейсом + +== 9.11 Требования к конфигурации и секретам + + +Сервисы программного продукта должны получать прикладные секреты из Vault. + +В конфигурации сервисов допускается хранение только bootstrap-параметров для подключения к Vault. Бизнес-секреты, ключи интеграций и иные чувствительные данные должны загружаться из Vault при старте приложения. + +== 9.12 Инфраструктура, деплой и эксплуатационный контур + + +Текущая инфраструктурная схема проекта включает прикладные сервисы, сервис секретов, мессенджерные сервисы и вспомогательный worker-контур. + +#figure( + image("public/diagrams/infrastructure-topology.svg", width: 100%), + caption: [Инфраструктура, деплой и эксплуатационный контур], +) + + +Сервисы проекта и способ их развёртывания: + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Сервис*], + [*Путь в репозитории*], + [*Роль*], + [*Deploy mode*], + [*Сервер*], + [web-frontend], + [web-frontend], + [клиентский и менеджерский веб-интерфейс], + [dokploy_webhook], + [main], + [apollo-backend], + [apollo-backend], + [GraphQL API и бизнес-логика], + [dokploy_webhook], + [main], + [hatchet-worker], + [hatchet-worker], + [фоновый worker-контур], + [dokploy_webhook], + [main], + [tg-bot], + [tg-bot], + [Telegram-контур], + [dokploy_webhook], + [main], + [max-bot], + [max-bot], + [MAX-контур], + [dokploy_webhook], + [main], + [bonus-bot], + [bonus-bot], + [бонусный сервис], + [dokploy_webhook], + [main], + [vault], + [vault], + [сервис секретов], + [dokploy_webhook], + [main] + ) +] + + +Серверная карта текущего проекта: + +- сервер main +- Tailscale user: root +- Tailscale host: dsrptlab + +Эксплуатационные операции доступа и диагностики выполняются через Tailscale SSH. + +== 9.13 Dokploy и цепочка развёртывания + + +Для основных сервисов проекта используется режим dokploy_webhook. + +Это означает следующую последовательность: + ++ изменения фиксируются в Git-репозитории; ++ изменения публикуются в main; ++ Dokploy получает webhook-событие; ++ Dokploy выполняет сборку соответствующего сервиса; ++ сервис перезапускается с загрузкой секретов из Vault; ++ после старта выполняются bootstrap-действия, предусмотренные образом и entrypoint-командой. + +Текущие особенности прикладных сервисов: + +- web-frontend стартует через загрузку Vault env и запуск .output/server/index.mjs +- apollo-backend стартует через загрузку Vault env, prisma migrate deploy и запуск src/server.js +- bot-сервисы стартуют через общий паттерн загрузки Vault env и запуск node src/server.js + +== 9.14 Vault и хранение секретов + + +Сервис vault развернут как отдельное приложение на базе образа hashicorp/vault:1.21.3. + +Текущие инфраструктурные правила работы Vault: + +- используется raft storage +- данные Vault сохраняются в /vault/data +- конфигурация сервиса хранится в vault/config/vault.hcl +- при старте выполняется проверка и, при необходимости, автоматический unseal из переменных окружения +- прикладные сервисы подключаются к Vault через bootstrap-переменные VAULT_ADDR, VAULT_TOKEN, VAULT_KV_MOUNT, VAULT_SHARED_PATH, VAULT_PROJECT_PATH, VAULT_ENABLED + +Прикладные сервисы используют общий shell-bootstrap load-vault-env.sh, который: + +- ожидает доступность Vault по health endpoint +- загружает shared secrets +- загружает project secrets +- экспортирует секреты в runtime environment процесса + +== 9.15 Структура сервисных каталогов + + +Текущая сервисная структура репозитория: + +- web-frontend — Nuxt-приложение, GraphQL operations, VitePress-документация +- apollo-backend — Apollo Server, Prisma schema, миграции, импорт каталога +- tg-bot — Telegram-сервис +- max-bot — MAX-сервис +- bonus-bot — бонусный сервис +- hatchet-worker — worker-контур +- vault — Dockerfile, конфигурация и entrypoint Vault +- hatchet — docker-compose инфраструктурного контура Hatchet + +== 9.16 Контур фоновых процессов + + +В проекте присутствует отдельный контур фонового исполнения задач: + +- hatchet-worker как прикладной worker +- hatchet-engine как движок исполнения +- hatchet-dashboard как интерфейс мониторинга +- отдельный postgres для Hatchet-контура + +Конфигурация этого контура находится в hatchet/docker-compose.yml. + +== 9.17 Зафиксированные runtime-версии и технологические зависимости + + +=== Базовые runtime и контейнерные образы + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Компонент*], + [*Текущая версия*], + [Node base image для web/backend/bots], + [node:22-bookworm-slim], + [Vault image], + [hashicorp/vault:1.21.3], + [Hatchet Postgres], + [postgres:15.6], + [Nuxt], + [4.4.2], + [Vue], + [3.5.30], + [Apollo Server], + [5.5.0], + [Prisma / Prisma Client], + [7.6.0], + [Mermaid], + [11.14.0], + [VitePress], + [1.6.4] + ) +] + + +=== Основные зависимости фронтенда + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Библиотека*], + [*Версия*], + [*Назначение*], + [\\\@nuxtjs/apollo], + [5.0.0-alpha.16], + [GraphQL-клиентский слой], + [\\\@vue/apollo-composable], + [4.2.2], + [composable API для GraphQL], + [\\\@apollo/client], + [3.14.1], + [Apollo client runtime], + [\\\@fullcalendar/core], + [6.1.20], + [calendar runtime], + [\\\@fullcalendar/daygrid], + [6.1.20], + [calendar day grid], + [\\\@fullcalendar/vue3], + [6.1.20], + [Vue integration for calendar], + [\\\@nuxt/eslint], + [1.15.2], + [linting Nuxt-проекта], + [\\\@nuxtjs/tailwindcss], + [6.14.0], + [Tailwind integration], + [daisyui], + [5.5.19], + [UI primitives], + [graphql], + [16.13.2], + [GraphQL runtime], + [mermaid], + [11.14.0], + [diagrams in documentation], + [\\\@sentry/vue], + [10.46.0], + [error tracking], + [storybook], + [8.6.14], + [UI component review], + [vue-router], + [5.0.4], + [Vue routing runtime] + ) +] + + +=== Основные зависимости backend + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Библиотека*], + [*Версия*], + [*Назначение*], + [\\\@apollo/server], + [5.5.0], + [GraphQL server], + [\\\@as-integrations/express5], + [1.1.2], + [Apollo + Express integration], + [express], + [5.2.1], + [HTTP server], + [\\\@prisma/client], + [7.6.0], + [data access], + [\\\@prisma/adapter-pg], + [7.6.0], + [Prisma adapter], + [pg], + [8.20.0], + [PostgreSQL driver], + [graphql], + [16.13.2], + [GraphQL runtime], + [zod], + [4.3.6], + [validation], + [nodemailer], + [8.0.4], + [email notifications], + [dotenv], + [17.3.1], + [env bootstrap in local/runtime layers] + ) +] + + +=== Основные зависимости worker-контура + + +#text(size: 7.6pt)[ + #table( + columns: (1fr, 1fr, 1fr), + stroke: rgb("#d0d7de"), + inset: 4pt, + align: horizon + left, + [*Библиотека*], + [*Версия*], + [*Назначение*], + [\\\@hatchet-dev/typescript-sdk], + [1.19.0], + [worker runtime], + [dotenv], + [17.3.1], + [env bootstrap in local/runtime layers] + ) +] + + +== 9.18 Технические конфигурационные файлы + + +Ключевые технические файлы текущей реализации: + +- deploy-map.toml — карта сервисов, deploy mode и серверов +- web-frontend/nuxt.config.ts — конфигурация Nuxt и Apollo +- web-frontend/codegen.ts — конфигурация GraphQL codegen +- apollo-backend/prisma.config.ts — конфигурация Prisma +- apollo-backend/prisma/schema.prisma — модель данных +- web-frontend/scripts/load-vault-env.sh — Vault bootstrap frontend +- apollo-backend/scripts/load-vault-env.sh — Vault bootstrap backend +- vault/config/vault.hcl — конфигурация Vault +- vault/entrypoint.sh — startup/unseal логика Vault + +#pagebreak(weak: true) += 10. Нефункциональные требования + + +== 10.1 Общие требования к архитектуре + + +Программный продукт должен быть реализован как веб-система с разделением клиентского и менеджерского контуров, серверной бизнес-логикой, постоянным хранением данных и возможностью интеграционного обмена с внешними системами. + +== 10.2 Требования к доступности интерфейсов + + +Система должна обеспечивать корректную работу: + +- в десктопных браузерах +- в мобильных браузерах +- на основных пользовательских разрешениях экрана + +Интерфейсы должны сохранять работоспособность и читаемость при адаптивном отображении. + +== 10.3 Требования к производительности + + +При штатной эксплуатации система должна обеспечивать: + +- приемлемое время открытия основных экранов +- приемлемое время отправки заявок и выполнения пользовательских действий +- отображение каталогов, карточек и заказов без заметных задержек при типовом объеме данных + +Точные количественные показатели производительности подлежат фиксации в рабочей документации по инфраструктуре и тестированию. + +== 10.4 Требования к безопасности + + +Система должна обеспечивать: + +- аутентификацию пользователей +- авторизацию по ролям +- ограничение доступа клиента только к данным своего контрагента +- хранение и передачу чувствительных данных с использованием защищенных механизмов +- исключение несанкционированного доступа к административным функциям + +== 10.5 Требования к надежности и журналированию + + +Система должна обеспечивать: + +- сохранность пользовательских данных +- сохранность истории изменений по заявкам, заказам и бонусным операциям +- фиксацию ошибок интеграционного обмена +- фиксацию значимых системных и пользовательских событий + +== 10.6 Требования к сопровождаемости + + +Реализация должна обеспечивать возможность: + +- сопровождения и развития клиентского контура +- сопровождения и развития менеджерского контура +- изменения параметров каталога и уведомлений без переработки базовой структуры системы +- расширения интеграционного обмена с 1С и иными внешними системами + +== 10.7 Требования к данным и актуальности сведений + + +Система должна обеспечивать: + +- хранение актуального состояния пользовательских данных +- отображение даты актуальности сведений, полученных из внешних систем, когда это применимо +- защиту от потери данных при обновлении параметров каталога и заказных сущностей + +== 10.8 Требования к документации + + +По результатам выполнения работ должна быть сформирована документация, достаточная для: + +- приемки результата работ +- дальнейшего сопровождения программного продукта +- понимания состава функций, данных, ролей и интеграций + +#pagebreak(weak: true) += 11. Требования к программной документации + + +== 11.1 Общий подход + + +Настоящее техническое задание является основным техническим документом программного продукта. + +В составе настоящего технического задания фиксируются: + +- назначение и границы продукта +- функциональные требования +- роли пользователей и права доступа +- требования к данным, сущностям и модели базы данных +- требования к интерфейсам +- требования к интеграциям +- архитектура, стек, компоненты и эксплуатационный контур +- нефункциональные требования +- порядок контроля, приемки и гарантийного сопровождения + +Отдельные документы не должны дублировать техническое задание. Дополнительная документация должна описывать только то, что необходимо для использования, эксплуатации или интеграции программного продукта и не раскрыто в настоящем документе в достаточном объеме. + +== 11.2 Пользовательская документация + + +Пользовательская документация должна быть подготовлена в объеме, достаточном для работы пользователей в предусмотренных ролях: + +- клиент +- менеджер +- суперменеджер + +Пользовательская документация должна описывать: + +- вход в личный кабинет и завершение регистрации +- работу с профилем и каналами уведомлений +- просмотр каталога готовой продукции +- добавление товаров в корзину и отправку заявки +- создание заявки на расчет индивидуальной продукции +- просмотр заказов, статусов, условий и истории изменений +- работу с бонусным кабинетом, бонусным балансом и заявками на вывод +- действия менеджера по обработке клиентов, заявок, заказов и бонусных операций +- действия суперменеджера в административных разделах, если они отличаются от действий менеджера + +Документация должна быть написана прикладным языком и ориентирована на выполнение пользовательских сценариев, а не на описание внутренней реализации. + +== 11.3 Эксплуатационная документация + + +Эксплуатационная документация должна быть подготовлена в объеме, достаточном для сопровождения программного продукта после передачи результата работ. + +Эксплуатационная документация должна описывать: + +- состав сервисов и их назначение +- порядок запуска и перезапуска сервисов через согласованный контур деплоя +- используемые окружения и общие принципы конфигурации +- порядок загрузки секретов из Vault +- порядок просмотра логов и диагностики типовых сбоев +- порядок проверки работоспособности клиентского, менеджерского и интеграционного контуров +- порядок обновления приложения через Git и Dokploy +- перечень технических контактов или зон ответственности, если они согласованы сторонами + +Эксплуатационная документация не должна содержать бизнес-секреты, токены, пароли и иные чувствительные значения. Для секретов указываются только имена переменных, назначение и источник получения. + +== 11.4 Интеграционная документация + + +Для интеграции с 1С должна быть подготовлена интеграционная спецификация либо отдельный раздел настоящего технического задания, если к моменту согласования ТЗ формат обмена уже определен. + +Интеграционная документация должна описывать: + +- состав событий, передаваемых из 1С +- состав методов получения данных из 1С +- структуру payload для каждого события и метода +- обязательные и необязательные поля +- правила сопоставления идентификаторов +- требования к авторизации, подписи или иному механизму защиты запросов +- порядок обработки дублей +- порядок фиксации ошибок и повторной обработки сообщений +- критерии приемки интеграционного обмена + +Если точный формат обмена с 1С не определен на момент утверждения ТЗ, он фиксируется отдельной согласованной интеграционной спецификацией до начала завершающего этапа интеграции. + +== 11.5 Перечень сторонних компонентов + + +Перечень сторонних компонентов формируется на основании фактических файлов проекта, включая package.json, lock-файлы, Dockerfile и конфигурационные файлы сервисов. + +Перечень должен содержать: + +- наименование компонента +- версию или диапазон версий +- назначение компонента в продукте +- источник установки или репозиторий, если он отличается от стандартного пакетного менеджера + +Ключевые сторонние компоненты, используемые в текущей реализации, перечислены в разделе технической архитектуры настоящего технического задания. + +#pagebreak(weak: true) += 12. Технико-экономические показатели + + +== 12.1 Назначение показателей + + +Технико-экономические показатели используются для фиксации ожидаемого прикладного эффекта от разработки программного продукта. + +Расчет финансовой эффективности, окупаемости или экономического эффекта в денежном выражении не входит в состав настоящего технического задания, если стороны не согласуют такой расчет отдельно. + +== 12.2 Ожидаемый прикладной эффект + + +Разработка программного продукта должна обеспечить: + +- снижение объема ручной коммуникации при приеме и сопровождении заказов +- единый интерфейс для клиента, менеджера и суперменеджера +- ускорение обработки заявок за счет фиксации состава, параметров и статусов в системе +- снижение риска потери информации по заказам, заявкам и бонусным операциям +- повышение прозрачности статусов заказов и актуальности данных для клиента +- централизованное хранение истории изменений +- возможность дальнейшего развития клиентского, менеджерского, бонусного и интеграционного контуров + +== 12.3 Ограничения + + +Программный продукт не заменяет учетную систему 1С и не является первичным источником бухгалтерских, складских или финансовых данных. + +Экономический эффект зависит от полноты внедрения продукта в рабочие процессы заказчика, качества данных 1С, доступности внешних каналов уведомлений и соблюдения эксплуатационных требований. + +#pagebreak(weak: true) += 13. Стадии и этапы разработки + + +== 13.1 Общий порядок выполнения работ + + +Работы выполняются поэтапно, чтобы согласовывать ключевые решения до перехода к следующей части реализации. + +Переход к следующему этапу выполняется после согласования сторонами результата предыдущего этапа либо после фиксации замечаний, не препятствующих продолжению работ. + +== 13.2 Этап 1. Разработка и согласование технического задания + + +На этапе разрабатывается и согласуется настоящее техническое задание. + +Результат этапа: + +- согласованная редакция технического задания +- зафиксированные границы продукта +- зафиксированный состав пользовательских ролей +- зафиксированные функциональные, интеграционные, технические и эксплуатационные требования + +Критерий завершения этапа: утверждение технического задания сторонами. + +== 13.3 Этап 2. UX/UI и согласование визуального подхода + + +На этапе подготавливаются 2-3 сверстанные страницы личного кабинета с основными элементами интерфейса. + +В состав страниц для согласования могут входить: + +- страница входа или регистрации +- каталог либо карточка товара +- корзина либо карточка заявки +- менеджерская карточка клиента или заказа + +Результат этапа: + +- согласованный визуальный подход +- согласованные базовые интерфейсные элементы +- подтверждение применимости выбранного подхода для клиентского и менеджерского контуров + +Критерий завершения этапа: согласование визуального подхода сторонами. + +== 13.4 Этап 3. Функциональная реализация без интеграции с 1С + + +На этапе реализуются основные пользовательские и менеджерские сценарии без подключения обмена с 1С. + +В состав этапа входят: + +- регистрация и подключение клиентов +- роли и разграничение доступа +- каталог готовой продукции +- корзина и заявки на заказ +- заявки на расчет индивидуальной продукции +- обработка заявок менеджером +- статусы и история изменений +- уведомления в согласованном объеме +- бонусный и реферальный контур +- административные настройки, необходимые для работы продукта + +Результат этапа: + +- работоспособный программный продукт с основным функционалом +- возможность проверки клиентских, менеджерских и бонусных сценариев без обмена с 1С + +Критерий завершения этапа: готовность и приемка основного функционала без интеграции с 1С. + +== 13.5 Этап 4. Интеграция с 1С и отладка обмена + + +На этапе выполняются подключение, настройка и отладка интеграции с 1С. + +В состав этапа входят: + +- согласование или уточнение интеграционной спецификации +- настройка приема webhook-событий от 1С +- настройка получения данных из 1С через согласованные методы +- сопоставление внутренних идентификаторов и идентификаторов 1С +- проверка получения каталога, остатков, заказов, статусов и задолженности +- проверка обработки дублей и ошибок обмена +- проверка отображения даты актуальности данных + +Результат этапа: + +- работоспособный интеграционный обмен с 1С в согласованном объеме +- журналирование ключевых интеграционных событий +- подтвержденная работоспособность сценариев, зависящих от данных 1С + +Критерий завершения этапа: подтвержденная сторонами работоспособность сценариев с 1С в согласованном объеме. + +== 13.6 Этап 5. Передача результата и приемка + + +На этапе выполняются итоговая проверка, устранение критичных замечаний и передача результата работ. + +Результат этапа: + +- размещенный программный продукт в согласованном эксплуатационном контуре +- согласованная редакция технического задания +- пользовательская и эксплуатационная документация в согласованном объеме +- перечень ключевых сторонних компонентов +- акт приемки выполненных работ + +Критерий завершения этапа: подписание акта приемки либо наступление условий приемки, предусмотренных договором. + +#pagebreak(weak: true) += 14. Порядок контроля, приемки и гарантийного сопровождения + + +== 14.1 Общие положения приемки + + +Приемка результата работ должна подтверждать соответствие программного продукта требованиям настоящего технического задания, условиям договора и согласованным требованиям заказчика. + +При приемке подлежат проверке: + +- клиентский контур +- менеджерский контур +- каталог готовой продукции +- сценарии заявок на заказ +- сценарии заявок на расчет +- сопровождение заказов +- уведомления +- бонусный и реферальный контур +- интеграционный обмен с 1С в согласованном объеме +- пользовательская и эксплуатационная документация в согласованном объеме + +== 14.2 Виды проверок + + +Для контроля результата работ используются следующие виды проверок: + +- функциональная проверка основных пользовательских сценариев +- проверка разграничения ролей и прав доступа +- проверка корректности данных, статусов и истории изменений +- проверка интерфейсов на desktop и mobile +- проверка уведомлений по согласованным каналам +- проверка интеграционного обмена с 1С +- проверка запуска и работы сервисов в согласованном эксплуатационном контуре + +== 14.3 Критерии приемки + + +Программный продукт считается соответствующим требованиям, если: + +- обязательные пользовательские сценарии выполняются корректно +- разграничение ролей и прав доступа реализовано корректно +- заявкам, заказам и бонусным операциям присваиваются и отображаются корректные статусы +- каталог и остатки отображаются корректно +- цена не отображается клиенту до публикации условий менеджером +- менеджер имеет возможность обработать заявку и опубликовать условия +- история изменений сохраняется и доступна в предусмотренных сценариях +- сведения из 1С отображаются в согласованном объеме +- текущая задолженность клиента и дата актуальности данных отображаются при наличии этих сведений из 1С +- критичные дефекты, препятствующие выполнению основных сценариев, устранены до передачи результата + +== 14.4 Передаваемые материалы + + +В состав передаваемых заказчику материалов входят: + +- программный продукт, размещенный в согласованном эксплуатационном контуре +- исходный код разработанных компонентов в репозитории проекта +- согласованная редакция настоящего технического задания +- пользовательская документация в согласованном объеме +- эксплуатационная документация в согласованном объеме +- интеграционная спецификация 1С, если точные форматы обмена фиксируются отдельно от настоящего технического задания +- перечень ключевых сторонних компонентов, сформированный на основании фактических файлов проекта + +Технические схемы, модель данных, роли, архитектура, стек, состав сервисов и требования к интеграциям являются частью настоящего технического задания и не дублируются в отдельных документах без отдельного согласования сторон. + +== 14.5 Порядок фиксации замечаний + + +Каждое замечание, выявленное при приемке, должно содержать: + +- описание проблемы +- сценарий воспроизведения +- ожидаемый результат +- фактический результат +- уровень критичности +- статус устранения + +Замечания, не препятствующие выполнению основных пользовательских и интеграционных сценариев, могут быть зафиксированы сторонами для последующего устранения в согласованном порядке. + +== 14.6 Гарантийный срок + + +Гарантийный срок на разработанные модули, сервисы и дополнительный функционал составляет 6 месяцев с даты подписания акта приемки выполненных работ, если иной порядок не согласован сторонами. + +Гарантия распространяется на дефекты разработанного программного продукта, проявившиеся при штатной эксплуатации и относящиеся к функционалу, реализованному исполнителем. + +== 14.7 Порядок гарантийного обращения + + +Гарантийное обращение должно быть передано исполнителю в письменной форме или иным согласованным сторонами способом. + +В обращении должны быть указаны: + +- описание дефекта +- пользовательская роль или контур, в котором проявляется дефект +- шаги воспроизведения +- ожидаемый результат +- фактический результат +- дата и время обнаружения +- дополнительные материалы, если они нужны для диагностики + +Исполнитель выполняет диагностику дефекта и, если дефект относится к гарантийной зоне ответственности, устраняет его без дополнительной оплаты. + +Срок устранения гарантийного дефекта составляет не более 3 дней с даты получения обращения либо иной срок, согласованный сторонами с учетом критичности и характера дефекта. + +== 14.8 Ограничения гарантийного сопровождения + + +Гарантийное сопровождение не распространяется на случаи, когда некорректная работа вызвана: + +- самостоятельным изменением программного продукта заказчиком или третьими лицами без согласования с исполнителем +- ошибками сервера, хостинга, инфраструктуры или базы данных, не связанными с разработанным функционалом +- атакой, компрометацией доступа или нарушением требований информационной безопасности со стороны заказчика +- некорректной работой стороннего программного обеспечения +- недоступностью или некорректной работой внешних систем, включая 1С, Telegram, Max, почтовые сервисы и иные внешние API +- изменением форматов или правил работы внешних систем без предварительного согласования и обновления интеграционной спецификации + +Если дефект связан с внешней системой или инфраструктурой, исполнитель фиксирует результат диагностики и передает заказчику сведения, достаточные для дальнейшего устранения причины на стороне соответствующей системы или поставщика.