{"id":14291,"url":"\/distributions\/14291\/click?bit=1&hash=257d5375fbb462be671b713a7a4184bd5d4f9c6ce46e0d204104db0e88eadadd","hash":"257d5375fbb462be671b713a7a4184bd5d4f9c6ce46e0d204104db0e88eadadd","title":"\u0420\u0435\u043a\u043b\u0430\u043c\u0430 \u043d\u0430 Ozon \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0442\u0430\u043c \u043d\u0435 \u043f\u0440\u043e\u0434\u0430\u0451\u0442","buttonText":"","imageUuid":""}

Печатные формы документов для Eloquent в 0 строчек кода

Недавно в проекте на Laravel+Eloquent понадобилось сделать печатные формы документов — счетов, договоров в формате Word. Так как в системе много разных документов, то решил сделать универсально, чтобы можно было потом использовать и в других проектах.

В итоге получилась реализация, которая требует минимум затрат на интеграцию в проект.

Как я раньше делал печатные формы. Использовал разные подходы

  • В шаблон документа размещал теги и заменял их при генерации.
  • Генерировал текст документа с нуля.
  • Генерировал html и конвертировал его в word.
  • Делал свою систему для генерации документов по аналогии с той, что описана в этой статье, но на других технологиях.

Каждый вариант хорош для своей задачи. Но если у вас Eloquent, то весьма рекомендую вариант, описанный в этой статье.

Итак, подключаем пакет

composer require mnvx/eloquent-print-form

И описываем модели Eloquent, если они еще не описаны. Допустим, есть следующие модели.

use Illuminate\Database\Eloquent\Model; /** * @property string $number * @property string $start_at * @property Customer $customer * @property ContractAppendix[] $appendixes */ class Contract extends Model { public function customer() { return $this->belongsTo(Customer::class); } public function appendixes() { return $this->hasMany(ContractAppendix::class); } } /** * @property string $name * @property CustomerCategory $category */ class Customer extends Model { public function category() { return $this->belongsTo(CustomerCategory::class); } } /** * @property string $number * @property string $date * @property float $tax */ class ContractAppendix extends Model { public function getTaxAttribute() { $tax = 0; foreach ($this->items as $item) { $tax += $item->total_amount * (1 - 100 / (100+($item->taxStatus->vat_rate ?? 0))); } return $tax; } }

Для наглядности, диаграмма связей

Иллюстрация примера моделей

То есть описана таблица с договорами (Contract), у договора может быть заполнен контрагент (Customer), у контрагента может быть заполнена категория. У договора может быть несколько приложений (ContractAppendix).

Все что нужно для генерации печатной формы — описать поля в шаблоне печатной формы. Создаем docx файл с таким содержимым

Привет шаблона документа

В переменных указываем названия полей сущностей Eloquent. Если нужно добраться по связям до соседних таблиц, используем точку, как в примере выше, в ${customer.category.name}.

Если необходимо обработать данные из базы, используем оператор конвейер |, как в примере ${number|placeholder}. Если нужно выполнить несколько обработок, строим цепочку конвейеров, например ${start_at|date|placeholder}.

Примеры готовых операций

  • placeholder — заменяет пустое значение на "____",
  • date — приводит дату к формату 24.12.2020,
  • dateTime — приводит дату-время к формату 24.12.2020 23:11,
  • int — приводит целое число к формату 2`145,
  • decimal — приводит дробное число к формату 2`145.07.

Для заполнения табличных данных вставляем переменные в таблицу как в примере документа выше. Для нумерации строк таблицы можно использовать отдельную конструкцию ${entities.#row_number}.

Теперь, когда документ описан, остается просто запустить генерацию печатной формы

use Mnvx\EloquentPrintForm\PrintFormProcessor; $entity = Contract::find($id); $printFormProcessor = new PrintFormProcessor(); $templateFile = resource_path('path_to_print_forms/your_print_form.docx'); $tempFileName = $printFormProcessor->process($templateFile, $entity);

В сгенерированном файле $tempFileName будет лежать подготовленная печатная форма.

В проекте на Laravel метод контроллера, отвечающий за генерацию печатной формы, может выглядеть так

public function downloadPrintForm(FormRequest $request) { $id = $request->get('id'); $entity = Contract::find($id); $printFormProcessor = new PrintFormProcessor(); $templateFile = resource_path('path_to_print_forms/your_print_form.docx'); $tempFileName = $printFormProcessor->process($templateFile, $entity); $filename = 'contract_' . $id; return response() ->download($tempFileName, $filename . '.docx') ->deleteFileAfterSend(); }

Резюмируя, скажу, что я прилично разгрузил себя, сделав эту небольшую библиотеку в проекте, где довольно много печатных форм. Мне не надо для каждой из них писать свой уникальный код. Я просто описываю переменные как сказано выше и весьма быстро получаю результат. Буду рад, если и вам пакет поможет сэкономить время.

0
Комментарии
-3 комментариев
Раскрывать всегда