Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 additions & 11 deletions Core/Controller/DocumentStitcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
use FacturaScripts\Core\Base\Controller;
use FacturaScripts\Core\Base\ControllerPermissions;
use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
use FacturaScripts\Core\DataSrc\FormasPago;
use FacturaScripts\Core\Model\Base\TransformerDocument;
use FacturaScripts\Core\Response;
use FacturaScripts\Core\Tools;
use FacturaScripts\Dinamic\Lib\BusinessDocumentGenerator;
use FacturaScripts\Dinamic\Lib\ListFilter\PeriodFilter;
use FacturaScripts\Dinamic\Lib\ListFilter\SelectFilter;
use FacturaScripts\Dinamic\Model\CodeModel;
use FacturaScripts\Dinamic\Model\EstadoDocumento;
use FacturaScripts\Dinamic\Model\User;
Expand All @@ -35,6 +38,7 @@
*
* @author Carlos García Gómez <carlos@facturascripts.com>
* @author Francesc Pineda Segarra <francesc.pineda.segarra@gmail.com>
* @author Daniel Fernández Giménez <hola@danielfg.es>
*/
class DocumentStitcher extends Controller
{
Expand All @@ -46,12 +50,21 @@ class DocumentStitcher extends Controller
/** @var TransformerDocument[] */
public $documents = [];

/** @var array */
public $filters = [];

/** @var string */
public $modelName;

/** @var TransformerDocument[] */
public $moreDocuments = [];

/** @var bool */
public $showFilters = false;

/** @var array */
public $where = [];

public function getAvailableStatus(): array
{
$status = [];
Expand Down Expand Up @@ -93,6 +106,7 @@ public function getSeries(): array
public function privateCore(&$response, $user, $permissions)
{
parent::privateCore($response, $user, $permissions);
$action = $this->request->request->get('action', '');

$this->codes = $this->getCodes();
$this->modelName = $this->getModelName();
Expand All @@ -104,6 +118,11 @@ public function privateCore(&$response, $user, $permissions)
}

$this->loadDocuments();
$this->addFilters();
if ('search' === $action) {
$this->processFormDataLoad();
}

$this->loadMoreDocuments();

$statusCode = $this->request->input('status', '');
Expand All @@ -123,6 +142,22 @@ public function privateCore(&$response, $user, $permissions)
}
}

protected function addFilters(): void
{
$payMethods = [];
foreach (FormasPago::all() as $payMethod) {
if ($payMethod->idempresa == $this->documents[0]->idempresa) {
$payMethods[$payMethod->id()] = $payMethod->descripcion;
}
}

if (count($payMethods) > 2) {
$this->filters['codpago'] = new SelectFilter('codpago', 'codpago', 'payment-method', CodeModel::array2codeModel($payMethods));
}

$this->filters['fecha'] = new PeriodFilter('fecha', 'fecha', 'date');
}

/**
* @param array $newLines
* @param TransformerDocument $doc
Expand Down Expand Up @@ -174,6 +209,7 @@ protected function addInfoLine(array &$newLines, $doc): void
'mostrar_cantidad' => false,
'mostrar_precio' => false
]);

$this->pipe('addInfoLine', $infoLine);
$newLines[] = $infoLine;
}
Expand Down Expand Up @@ -406,21 +442,30 @@ protected function loadMoreDocuments(): void

$modelClass = self::MODEL_NAMESPACE . $this->modelName;
$model = new $modelClass();
$where = [
new DataBaseWhere('codalmacen', $this->documents[0]->codalmacen),
new DataBaseWhere('coddivisa', $this->documents[0]->coddivisa),
new DataBaseWhere('codserie', $this->documents[0]->codserie),
new DataBaseWhere('dtopor1', $this->documents[0]->dtopor1),
new DataBaseWhere('dtopor2', $this->documents[0]->dtopor2),
new DataBaseWhere('editable', true),
new DataBaseWhere('idempresa', $this->documents[0]->idempresa),
new DataBaseWhere($model->subjectColumn(), $this->documents[0]->subjectColumnValue())
];
$this->where[] = new DataBaseWhere('codalmacen', $this->documents[0]->codalmacen);
$this->where[] = new DataBaseWhere('coddivisa', $this->documents[0]->coddivisa);
$this->where[] = new DataBaseWhere('codserie', $this->documents[0]->codserie);
$this->where[] = new DataBaseWhere('dtopor1', $this->documents[0]->dtopor1);
$this->where[] = new DataBaseWhere('dtopor2', $this->documents[0]->dtopor2);
$this->where[] = new DataBaseWhere('editable', true);
$this->where[] = new DataBaseWhere('idempresa', $this->documents[0]->idempresa);
$this->where[] = new DataBaseWhere($model->subjectColumn(), $this->documents[0]->subjectColumnValue());
$orderBy = ['fecha' => 'ASC', 'hora' => 'ASC'];
foreach ($model->all($where, $orderBy, 0, 0) as $doc) {
foreach ($model->all($this->where, $orderBy, 0, 0) as $doc) {
if (false === in_array($doc->id(), $this->getCodes())) {
$this->moreDocuments[] = $doc;
}
}
}

protected function processFormDataLoad(): void
{
// filters
foreach ($this->filters as $filter) {
$filter->setValueFromRequest($this->request);
if ($filter->getDataBaseWhere($this->where)) {
$this->showFilters = true;
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property $showFilters is used in the template and set on line 459, but it's not declared as a class property. Add a public property declaration for $showFilters in the class definition (around lines 45-64) to avoid undefined property warnings.

Copilot uses AI. Check for mistakes.
}
}
}
}
55 changes: 39 additions & 16 deletions Core/View/DocumentStitcher.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,47 @@
</div>
</form>

{% if fsc.moreDocuments %}
{% if fsc.moreDocuments or fsc.showFilters is same as(true) %}
<div class="container-fluid">
<div class="row">
<div class="col mt-3">
<form action="{{ fsc.url() }}" method="post" onsubmit="animateSpinner('add')">
{{ formToken() }}
<input type="hidden" name="model" value="{{ fsc.modelName }}">
<input type="hidden" name="codes" value="{{ fsc.codes | join(',') }}">
<div class="card border-success shadow mb-2">
<div class="card-body p-2">
<button class="btn btn-spin-action btn-sm btn-outline-success" type="button"
data-bs-toggle="collapse" data-bs-target="#moreDocsCollapse" aria-expanded="false">
<i class="fa-solid fa-plus-square fa-fw" aria-hidden="true"></i>
{{ trans('more') }}
</button>
&nbsp; {{ trans('group-more-docs-p') }}
<div class="card border-success shadow mb-2">
<div class="card-body p-2">
<button class="btn btn-sm btn-outline-success" type="button" data-bs-toggle="collapse"
data-bs-target="#moreDocsCollapse" aria-expanded="{{ fsc.showFilters is same as(true) ? 'true' : 'false' }}">
<i class="fa-solid fa-plus-square fa-fw" aria-hidden="true"></i>
{{ trans('more') }}
</button>
&nbsp; {{ trans('group-more-docs-p') }}
</div>
<div class="collapse {{ fsc.showFilters is same as(true) ? 'show' : '' }}" id="moreDocsCollapse">
<div class="card-body">
<form action="{{ fsc.url() }}" method="post">
<input type="hidden" name="model" value="{{ fsc.modelName }}">
<input type="hidden" name="codes" value="{{ fsc.codes | join(',') }}">
<input type="hidden" name="action" value="search">
<div id="form{{ fsc.getViewName() }}Filters"
class="form-row align-items-center border-bottom mb-3">

{% for filterName, filter in fsc.filters %}
{{ filter.render() | raw }}
{% endfor %}
{% if fsc.filters|length > 0 %}
<div class="col-auto">
<div class="form-group">
<button type="submit" class="btn btn-secondary" title="{{ trans('search') }}">
<i class="fa-solid fa-search"></i>
</button>
</div>
</div>
{% endif %}
</div>
</form>
</div>
<div class="collapse" id="moreDocsCollapse">
<form action="{{ fsc.url() }}" method="post">
<input type="hidden" name="model" value="{{ fsc.modelName }}">
<input type="hidden" name="codes" value="{{ fsc.codes | join(',') }}">
<input type="hidden" name="action" value="add">
Comment on lines +136 to +161
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new forms for search (line 136) and add (line 159) are missing CSRF protection tokens. These forms should include the formToken() call to prevent CSRF attacks, similar to the main form on line 25. Add {{ formToken() }} after each form opening tag.

Copilot uses AI. Check for mistakes.
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
Expand Down Expand Up @@ -186,9 +209,9 @@
{{ trans('add') }}
</button>
</div>
</div>
</form>
</div>
</form>
</div>
</div>
</div>
</div>
Expand Down
Loading