pdf template status

This commit is contained in:
Yuri Kuznetsov
2025-06-10 18:16:06 +03:00
parent dc76b3340e
commit bddbfc33b8
15 changed files with 151 additions and 63 deletions
@@ -30,29 +30,27 @@
namespace Espo\Classes\AppParams;
use Espo\Core\Acl;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\ORM\EntityManager;
use Espo\Core\Select\SelectBuilderFactory;
use Espo\Entities\Template;
use Espo\Tools\App\AppParam;
use RuntimeException;
/**
* Returns a list of entity types for which a PDF template exists.
*
* @noinspection PhpUnused
*/
class TemplateEntityTypeList implements AppParam
{
private Acl $acl;
private SelectBuilderFactory $selectBuilderFactory;
private EntityManager $entityManager;
public function __construct(
Acl $acl,
SelectBuilderFactory $selectBuilderFactory,
EntityManager $entityManager
) {
$this->acl = $acl;
$this->selectBuilderFactory = $selectBuilderFactory;
$this->entityManager = $entityManager;
}
private Acl $acl,
private SelectBuilderFactory $selectBuilderFactory,
private EntityManager $entityManager,
) {}
/**
* @return string[]
@@ -65,14 +63,19 @@ class TemplateEntityTypeList implements AppParam
$list = [];
$query = $this->selectBuilderFactory
->create()
->from(Template::ENTITY_TYPE)
->withAccessControlFilter()
->buildQueryBuilder()
->select(['entityType'])
->group(['entityType'])
->build();
try {
$query = $this->selectBuilderFactory
->create()
->from(Template::ENTITY_TYPE)
->withAccessControlFilter()
->buildQueryBuilder()
->select(['entityType'])
->where(['status' => Template::STATUS_ACTIVE])
->group(['entityType'])
->build();
} catch (BadRequest|Forbidden $e) {
throw new RuntimeException('', 0, $e);
}
$templateCollection = $this->entityManager
->getRDBRepositoryByClass(Template::class)
@@ -0,0 +1,42 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Classes\Select\Template\PrimaryFilters;
use Espo\Core\Select\Primary\Filter;
use Espo\Entities\Template;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
class Active implements Filter
{
public function apply(QueryBuilder $queryBuilder): void
{
$queryBuilder->where(['status' => Template::STATUS_ACTIVE]);
}
}
+7
View File
@@ -36,6 +36,8 @@ class Template extends Entity
{
public const ENTITY_TYPE = 'Template';
public const STATUS_ACTIVE = 'Active';
public function getTargetEntityType(): string
{
$entityType = $this->get('entityType');
@@ -46,4 +48,9 @@ class Template extends Entity
return $entityType;
}
public function isActive(): bool
{
return $this->get('status') === self::STATUS_ACTIVE;
}
}
@@ -453,7 +453,8 @@
"presetFilters": {
"followed": "Followed",
"all": "All",
"starred": "Starred"
"starred": "Starred",
"active": "Active"
},
"massActions": {
"delete": "Delete",
@@ -20,7 +20,8 @@
"pageHeight": "Page Height (mm)",
"fontFace": "Font",
"title": "Title",
"style": "Style"
"style": "Style",
"status": "Status"
},
"links": {
},
@@ -28,6 +29,10 @@
"Create Template": "Create Template"
},
"options": {
"status": {
"Active": "Active",
"Inactive": "Inactive"
},
"pageOrientation": {
"Portrait": "Portrait",
"Landscape": "Landscape"
@@ -1,5 +1,20 @@
[
{"name": "name", "link": true},
{"name": "assignedUser", "width": 20},
{"name": "createdAt", "width": 20}
{
"name": "name",
"link": true
},
{
"name": "assignedUser",
"width": 20
},
{
"name": "oneOff",
"width": 11,
"hidden": true
},
{
"name": "createdAt",
"width": 20,
"hidden": true
}
]
@@ -1,5 +1,4 @@
[
{"name": "name", "link": true},
{"name": "assignedUser", "width": 22},
{"name": "createdAt", "width": 22}
{"name": "assignedUser", "width": 23}
]
@@ -1,21 +1,25 @@
[
{
"label": "",
"rows": [
[
{
"name":"name"
"name": "name"
},
{
"name":"entityType"
"name": "status"
}
],
[{"name":"variables","fullWidth":true, "view": "Template.Fields.Variables"}],
[{"name":"body","fullWidth":true}]
[
{
"name": "entityType"
},
false
],
[{"name": "variables", "view": "views/template/fields/variables"}],
[{"name":"body"}]
]
},
{
"label": "",
"rows": [
[{"name":"pageOrientation"}, {"name":"pageFormat"}],
[{"name":"pageWidth"}, {"name":"pageHeight"}],
@@ -23,7 +27,6 @@
]
},
{
"label": "",
"rows": [
[false, {"name":"topMargin"}, false],
[{"name":"leftMargin"}, false, {"name":"rightMargin"}],
@@ -31,7 +34,6 @@
]
},
{
"label": "",
"rows": [
[{"name": "title"}, false],
[{"name":"printHeader"}, {"name":"headerPosition"}],
@@ -1,10 +1,9 @@
[
{
"label": "",
"rows": [
[{"name":"name"}],
[{"name":"entityType"}, false],
[{"name":"body"}]
[{"name": "name"}],
[{"name": "entityType"}, {"name": "status"}],
[{"name": "body"}]
]
}
]
@@ -1,4 +1,5 @@
[
{"name": "name", "width": 50, "link": true},
{"name": "entityType"}
{"name": "name", "link": true},
{"name": "entityType", "width": 25},
{"name": "status", "width": 25}
]
@@ -5,5 +5,11 @@
"edit": "views/template/record/edit"
},
"mergeDisabled": true,
"filterList": [
"active"
],
"selectDefaultFilters": {
"filter": "active"
},
"iconClass": "fas fa-file-pdf"
}
@@ -24,6 +24,18 @@
"translation": "Global.scopeNames",
"view": "views/template/fields/entity-type"
},
"status": {
"type": "enum",
"options": [
"Active",
"Inactive"
],
"default": "Active",
"style": {
"Inactive": "info"
},
"maxLength": 8
},
"leftMargin": {
"type": "float",
"default": 10
@@ -1,5 +1,8 @@
{
"accessControlFilterClassNameMap": {
"mandatory": "Espo\\Classes\\Select\\Template\\AccessControlFilters\\Mandatory"
},
"primaryFilterClassNameMap": {
"active": "Espo\\Classes\\Select\\Template\\PrimaryFilters\\Active"
}
}
+14 -23
View File
@@ -43,28 +43,14 @@ class Service
{
private const DEFAULT_ENGINE = 'Dompdf';
private EntityManager $entityManager;
private Acl $acl;
private ServiceContainer $serviceContainer;
private DataLoaderManager $dataLoaderManager;
private Config $config;
private Builder $builder;
public function __construct(
EntityManager $entityManager,
Acl $acl,
ServiceContainer $serviceContainer,
DataLoaderManager $dataLoaderManager,
Config $config,
Builder $builder
) {
$this->entityManager = $entityManager;
$this->acl = $acl;
$this->serviceContainer = $serviceContainer;
$this->dataLoaderManager = $dataLoaderManager;
$this->config = $config;
$this->builder = $builder;
}
private EntityManager $entityManager,
private Acl $acl,
private ServiceContainer $serviceContainer,
private DataLoaderManager $dataLoaderManager,
private Config $config,
private Builder $builder,
) {}
/**
* Generate a PDF.
@@ -97,13 +83,18 @@ class Service
throw new NotFound("Record not found.");
}
/** @var ?TemplateEntity $template */
$template = $this->entityManager->getEntityById(TemplateEntity::ENTITY_TYPE, $templateId);
$template = $this->entityManager
->getRDBRepositoryByClass(TemplateEntity::class)
->getById($templateId);
if (!$template) {
throw new NotFound("Template not found.");
}
if (!$template->isActive()) {
throw new Forbidden("Template is not active.");
}
if ($applyAcl && !$this->acl->checkEntityRead($entity)) {
throw new Forbidden("No access to record.");
}
@@ -47,6 +47,8 @@ class SelectTemplateModalView extends SelectRecordsModalView {
});
this.collection.where = this.searchManager.getWhere();
this.collection.data.primaryFilter = 'active';
}
afterRender() {