Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
17 KiB
17 KiB
🔗 АРХИТЕКТУРА: NEXTCLOUD ШАБЛОНЫ + CRM МОДУЛЬ
🎯 КОНЦЕПЦИЯ
Шаблоны хранятся в Nextcloud, метаданные и маппинг - в CRM модуле.
📊 СХЕМА РАБОТЫ
┌─────────────────────────────────────────────────────────────┐
│ NEXTCLOUD │
│ /Templates/ │
│ ├── pretenziya.docx ← ФАЙЛ ШАБЛОНА │
│ ├── iskovoe_zayavlenie.docx ← ФАЙЛ ШАБЛОНА │
│ └── soglashenie.docx ← ФАЙЛ ШАБЛОНА │
└─────────────────────────────────────────────────────────────┘
▲
│ WebDAV GET
│
┌─────────────────────────────────────────────────────────────┐
│ CRM MODULE DocTemplate │
│ │
│ vtiger_doctemplate: │
│ ├── templateid: 1 │
│ ├── templatename: "Претензия" │
│ ├── filename: "pretenziya.docx" ← Ссылка на Nextcloud │
│ ├── module: "Project" │
│ └── mapping: { │
│ "CLIENT_NAME": "$PROJECT_PROJECTNAME$", │
│ "DATE": "$PROJECT_CREATEDTIME$", │
│ "AMOUNT": "$PROJECT_CF_1885$" │
│ } │
│ │
│ vtiger_doctemplate_mappings: │
│ (альтернатива JSON в mapping) │
└─────────────────────────────────────────────────────────────┘
▲
│ Использует маппинг
│
┌─────────────────────────────────────────────────────────────┐
│ ПРОЦЕСС ГЕНЕРАЦИИ │
│ │
│ 1. Пользователь выбирает шаблон в CRM │
│ 2. CRM получает маппинг из БД │
│ 3. CRM скачивает шаблон из Nextcloud (WebDAV) │
│ 4. CRM получает данные записи (CRMEntity) │
│ 5. CRM заполняет переменные по маппингу │
│ 6. CRM сохраняет готовый документ в S3 │
│ 7. CRM открывает документ в OnlyOffice │
└─────────────────────────────────────────────────────────────┘
🔧 КАК ЭТО РАБОТАЕТ
1. Хранение шаблонов
В Nextcloud:
- Физические файлы DOCX хранятся в
/Templates/ - Управление через веб-интерфейс Nextcloud
- Версионирование (если нужно) через Nextcloud
В CRM:
- Метаданные шаблона (название, описание)
- Маппинг переменных (какая переменная → какое поле)
- Настройки (для какого модуля, папка сохранения)
2. Структура таблицы vtiger_doctemplate
CREATE TABLE `vtiger_doctemplate` (
`templateid` int(11) NOT NULL AUTO_INCREMENT,
`templatename` varchar(255) NOT NULL, -- "Претензия"
`filename` varchar(255) NOT NULL, -- "pretenziya.docx" (в Nextcloud)
`module` varchar(100) NOT NULL, -- "Project"
`description` text, -- Описание шаблона
`mapping` longtext, -- JSON маппинг или NULL
`nextcloud_path` varchar(255) DEFAULT '/Templates/', -- Путь в Nextcloud
`is_active` tinyint(1) DEFAULT '1',
`owner` int(11) NOT NULL,
`createdtime` datetime NOT NULL,
`modifiedtime` datetime NOT NULL,
`deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`templateid`)
) ENGINE=InnoDB;
Пример записи:
[
'templateid' => 1,
'templatename' => 'Претензия',
'filename' => 'pretenziya.docx',
'module' => 'Project',
'description' => 'Шаблон претензии для проектов',
'mapping' => json_encode([
'CLIENT_NAME' => '$PROJECT_PROJECTNAME$',
'DATE' => '$PROJECT_CREATEDTIME$',
'AMOUNT' => '$PROJECT_CF_1885$',
'CONTACT_NAME' => '$CONTACTS_LASTNAME$'
]),
'nextcloud_path' => '/Templates/'
]
3. Процесс генерации документа
class DocTemplate_TemplateGenerator_Model {
public function generate($module, $recordId, $templateId) {
// 1. Получить метаданные шаблона из CRM БД
$template = DocTemplate_Template_Model::getInstanceById($templateId);
// 2. Скачать шаблон из Nextcloud
$templateContent = $this->downloadFromNextcloud(
$template->getFilename(),
$template->getNextcloudPath()
);
// 3. Получить данные записи (как PDFMaker)
$focus = CRMEntity::getInstance($module);
$focus->retrieve_entity_info($recordId, $module);
$focus->id = $recordId;
// 4. Получить маппинг из CRM БД
$mapping = $template->getMapping();
// 5. Построить переменные по маппингу
$variables = $this->buildVariables($mapping, $focus, $module);
// 6. Заменить переменные в шаблоне
$content = $this->replaceVariables($templateContent, $variables);
// 7. Сохранить готовый документ в S3
$filePath = $this->saveToS3($content, $module, $recordId, $template);
// 8. Вернуть URL для открытия в OnlyOffice
return $this->getOnlyOfficeUrl($filePath);
}
/**
* Скачивание шаблона из Nextcloud
*/
private function downloadFromNextcloud($filename, $path = '/Templates/') {
$nextcloudUrl = 'https://office.clientright.ru:8443';
$username = 'admin';
$password = 'office';
$webdavUrl = $nextcloudUrl . '/remote.php/dav/files/' .
$username . $path . $filename;
$ch = curl_init($webdavUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("Шаблон не найден в Nextcloud: {$filename}");
}
return $content;
}
}
🎨 UI: УПРАВЛЕНИЕ ШАБЛОНАМИ
Вариант 1: Синхронизация с Nextcloud
Кнопка "Синхронизировать с Nextcloud":
// В DocTemplate/actions/SyncWithNextcloud.php
class DocTemplate_SyncWithNextcloud_Action {
public function process() {
// 1. Получить список файлов из Nextcloud /Templates/
$templates = $this->listNextcloudTemplates();
// 2. Для каждого файла проверить, есть ли запись в CRM
foreach ($templates as $template) {
$existing = $this->findTemplateByFilename($template['name']);
if (!$existing) {
// 3. Создать новую запись в CRM
$this->createTemplateRecord($template);
} else {
// 4. Обновить метаданные (размер, дата изменения)
$this->updateTemplateRecord($existing, $template);
}
}
return ['success' => true, 'synced' => count($templates)];
}
private function listNextcloudTemplates() {
// WebDAV PROPFIND запрос к /Templates/
// Вернуть список файлов
}
}
Вариант 2: Ручное создание записи
В интерфейсе CRM:
- Пользователь создает запись шаблона
- Указывает имя файла в Nextcloud (например,
pretenziya.docx) - Выбирает модуль (Project, HelpDesk, etc.)
- Настраивает маппинг переменных
- Сохраняет
При сохранении:
- Проверяется, существует ли файл в Nextcloud
- Если нет - показывается предупреждение
🔄 ДВА ПОДХОДА К МАППИНГУ
Подход 1: JSON в поле mapping
Плюсы:
- ✅ Простота
- ✅ Гибкость
- ✅ Легко редактировать
Минусы:
- ❌ Сложно искать по маппингу
- ❌ Нет версионирования отдельных переменных
$mapping = json_decode($template->mapping, true);
// [
// 'CLIENT_NAME' => '$PROJECT_PROJECTNAME$',
// 'DATE' => '$PROJECT_CREATEDTIME$'
// ]
Подход 2: Отдельная таблица vtiger_doctemplate_mappings
Плюсы:
- ✅ Легко искать
- ✅ Версионирование
- ✅ Можно редактировать через UI
Минусы:
- ❌ Сложнее структура
CREATE TABLE `vtiger_doctemplate_mappings` (
`mappingid` int(11) NOT NULL AUTO_INCREMENT,
`templateid` int(11) NOT NULL,
`template_variable` varchar(100) NOT NULL, -- CLIENT_NAME
`field_config` varchar(255) NOT NULL, -- $PROJECT_PROJECTNAME$ или JSON
`sequence` int(11) DEFAULT '0',
PRIMARY KEY (`mappingid`),
KEY `templateid` (`templateid`)
) ENGINE=InnoDB;
Рекомендация: Начать с JSON, потом при необходимости перейти на отдельную таблицу.
📋 ПРОЦЕСС СОЗДАНИЯ ШАБЛОНА
Сценарий 1: Шаблон уже есть в Nextcloud
- Пользователь загружает
pretenziya.docxв Nextcloud/Templates/ - В CRM создает запись шаблона:
- Название: "Претензия"
- Файл:
pretenziya.docx - Модуль: Project
- Настраивает маппинг:
CLIENT_NAME→$PROJECT_PROJECTNAME$DATE→$PROJECT_CREATEDTIME$
- Сохраняет
Сценарий 2: Создание нового шаблона
- В CRM создает запись шаблона
- Указывает имя файла (например,
new_template.docx) - Настраивает маппинг
- Сохраняет
- Опционально: Кнопка "Создать пустой шаблон в Nextcloud" - создает пустой DOCX файл
🔍 ПРОВЕРКА СУЩЕСТВОВАНИЯ ШАБЛОНА
class DocTemplate_Template_Model {
/**
* Проверка существования файла в Nextcloud
*/
public function checkNextcloudFile() {
$nextcloudUrl = 'https://office.clientright.ru:8443';
$username = 'admin';
$password = 'office';
$webdavUrl = $nextcloudUrl . '/remote.php/dav/files/' .
$username . $this->getNextcloudPath() .
$this->getFilename();
$ch = curl_init($webdavUrl);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode === 200;
}
}
🎯 ИТОГОВАЯ АРХИТЕКТУРА
┌─────────────────────────────────────────────────────────────┐
│ NEXTCLOUD (/Templates/) │
│ ├── pretenziya.docx ← ФИЗИЧЕСКИЙ ФАЙЛ │
│ ├── iskovoe_zayavlenie.docx ← ФИЗИЧЕСКИЙ ФАЙЛ │
│ └── soglashenie.docx ← ФИЗИЧЕСКИЙ ФАЙЛ │
└─────────────────────────────────────────────────────────────┘
▲
│ WebDAV
│
┌─────────────────────────────────────────────────────────────┐
│ CRM MODULE DocTemplate │
│ │
│ vtiger_doctemplate: │
│ ┌─────────────────────────────────────┐ │
│ │ templateid: 1 │ │
│ │ templatename: "Претензия" │ │
│ │ filename: "pretenziya.docx" ←──────┼─── Ссылка │
│ │ module: "Project" │ │
│ │ mapping: { │ │
│ │ "CLIENT_NAME": "$PROJECT_..." │ │
│ │ } │ │
│ └─────────────────────────────────────┘ │
│ │
│ ПРОЦЕСС: │
│ 1. Получить метаданные из БД │
│ 2. Скачать файл из Nextcloud │
│ 3. Заполнить переменные │
│ 4. Сохранить в S3 │
└─────────────────────────────────────────────────────────────┘
✅ ПРЕИМУЩЕСТВА ТАКОГО ПОДХОДА
- ✅ Шаблоны в одном месте - Nextcloud (удобно редактировать)
- ✅ Метаданные в CRM - маппинг, настройки, права доступа
- ✅ Версионирование - можно через Nextcloud
- ✅ Резервное копирование - шаблоны в Nextcloud/S3
- ✅ Разделение ответственности - файлы там, логика здесь
🚀 ГОТОВ РЕАЛИЗОВАТЬ!
Вопросы для уточнения:
- Синхронизация: Нужна ли автоматическая синхронизация с Nextcloud или ручное создание записей?
- Маппинг: JSON в поле или отдельная таблица?
- Создание шаблонов: Можно ли создавать пустые шаблоны из CRM или только в Nextcloud?
Готов начать реализацию! 🎉