Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
58 changes: 47 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\BusinessDocumentLine;
use FacturaScripts\Core\Model\Base\TransformerDocument;
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 @@ -36,6 +39,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 @@ -47,12 +51,18 @@ class DocumentStitcher extends Controller
/** @var TransformerDocument[] */
public $documents = [];

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

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

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

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

public function getAvailableStatus(): array
{
$status = [];
Expand Down Expand Up @@ -94,6 +104,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 @@ -105,6 +116,11 @@ public function privateCore(&$response, $user, $permissions)
}

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

$this->loadMoreDocuments();

$statusCode = $this->request->request->get('status', '');
Expand All @@ -124,6 +140,16 @@ public function privateCore(&$response, $user, $permissions)
}
}

protected function addFilters()
{
$payMethods = FormasPago::codeModel(true, $this->documents[0]->idempresa);
if (count($payMethods) > 2) {
$this->filters['codpago'] = new SelectFilter('codpago', 'codpago', 'payment-method', $payMethods);
}

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

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

$this->pipe('addInfoLine', $infoLine);
$newLines[] = $infoLine;
}
Expand Down Expand Up @@ -408,21 +435,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->primaryColumnValue(), $this->getCodes())) {
$this->moreDocuments[] = $doc;
}
}
}

protected function processFormDataLoad()
{
// 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.
}
}
}
}
14 changes: 10 additions & 4 deletions Core/DataSrc/FormasPago.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace FacturaScripts\Core\DataSrc;

use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
use FacturaScripts\Dinamic\Model\CodeModel;
use FacturaScripts\Dinamic\Model\FormaPago;

Expand All @@ -29,11 +30,11 @@ final class FormasPago implements DataSrcInterface
/**
* @return FormaPago[]
*/
public static function all(): array
public static function all(array $where = []): array
{
if (!isset(self::$list)) {
$model = new FormaPago();
self::$list = $model->all([], [], 0, 0);
self::$list = $model->all($where, [], 0, 0);
}

return self::$list;
Expand All @@ -49,10 +50,15 @@ public static function clear(): void
*
* @return array
*/
public static function codeModel(bool $addEmpty = true): array
public static function codeModel(bool $addEmpty = true, ?int $idempresa = null): array
{
$where = [];
if (false === is_null($idempresa)) {
$where[] = new DataBaseWhere('idempresa', $idempresa);
}

$codes = [];
foreach (self::all() as $formaPago) {
foreach (self::all($where) as $formaPago) {
$codes[$formaPago->codpago] = $formaPago->descripcion;
}

Expand Down
56 changes: 40 additions & 16 deletions Core/View/DocumentStitcher.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,48 @@
</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-toggle="collapse" data-target="#moreDocsCollapse" aria-expanded="false">
<i class="fas 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-toggle="collapse"
data-target="#moreDocsCollapse" aria-expanded="{{ fsc.showFilters is same as(true) ? 'true' : 'false' }}">
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.

Bootstrap 4 attributes (data-toggle, data-target) are used here, but the rest of the template uses Bootstrap 5 attributes (data-bs-toggle, data-bs-target on lines 64 and 94). For consistency and to ensure proper functionality with Bootstrap 5, these should be changed to data-bs-toggle and data-bs-target.

Suggested change
<button class="btn btn-sm btn-outline-success" type="button" data-toggle="collapse"
data-target="#moreDocsCollapse" aria-expanded="{{ fsc.showFilters is same as(true) ? 'true' : 'false' }}">
<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' }}">

Copilot uses AI. Check for mistakes.
<i class="fas 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"
style="{{ divFiltersStyle }}">

{% 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="fas 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 +210,9 @@
{{ trans('add') }}
</button>
</div>
</div>
</form>
</div>
</form>
</div>
</div>
</div>
</div>
Expand Down