improve error handling during invoice generation (#2932)

* prevent that items will be marked as exported if invoice can not be generated
* check for existing invoice number to prevent that invalid invoices will be generated
* allow to add a unique id to invoice preview files on batch export
* hide delete invoice action with deactivated permission
* try to automatically fix duplicate invoice id
This commit is contained in:
Kevin Papst
2021-11-15 19:21:22 +01:00
committed by GitHub
parent 8978c181ee
commit 5896ae26c6
7 changed files with 58 additions and 18 deletions

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Invoice;
final class DuplicateInvoiceNumberException extends \Exception
{
public function __construct(string $invoiceNumber)
{
parent::__construct('Invoice number "' . $invoiceNumber . '" already existing');
}
}

View File

@@ -58,21 +58,29 @@ final class ConfigurableNumberGenerator implements NumberGeneratorInterface
{
$format = $this->configuration->find('invoice.number_format');
$invoiceDate = $this->model->getInvoiceDate();
$result = $format;
preg_match_all('/{[^}]*?}/', $format, $matches);
foreach ($matches[0] as $part) {
$partialResult = $this->parseReplacer($invoiceDate, $part);
$result = str_replace($part, $partialResult, $result);
}
$loops = 0;
$increaseBy = 0;
do {
$result = $format;
preg_match_all('/{[^}]*?}/', $format, $matches);
foreach ($matches[0] as $part) {
$partialResult = $this->parseReplacer($invoiceDate, $part, $increaseBy);
$result = str_replace($part, $partialResult, $result);
}
$increaseBy++;
} while ($this->repository->hasInvoice($result) && $loops++ < 99);
return (string) $result;
}
private function parseReplacer(\DateTime $invoiceDate, string $originalFormat): string
private function parseReplacer(\DateTime $invoiceDate, string $originalFormat, int $increaseBy): string
{
$formatterLength = null;
$increaseBy = 0;
$formatPattern = str_replace(['{', '}'], '', $originalFormat);
$parts = preg_split('/([+\-,])+/', $formatPattern, -1, PREG_SPLIT_DELIM_CAPTURE);

View File

@@ -366,12 +366,12 @@ final class ServiceInvoice
if ($renderer->supports($document)) {
$dispatcher->dispatch(new InvoicePreRenderEvent($model, $document, $renderer));
$response = $renderer->render($document, $model);
if ($model->getQuery()->isMarkAsExported()) {
$this->markEntriesAsExported($model->getEntries());
if ($this->invoiceRepository->hasInvoice($model->getInvoiceNumber())) {
throw new DuplicateInvoiceNumberException($model->getInvoiceNumber());
}
$response = $renderer->render($document, $model);
$event = new InvoicePostRenderEvent($model, $document, $renderer, $response);
$dispatcher->dispatch($event);
@@ -382,6 +382,10 @@ final class ServiceInvoice
$invoice->setFilename($invoiceFilename);
$this->invoiceRepository->saveInvoice($invoice);
if ($model->getQuery()->isMarkAsExported()) {
$this->markEntriesAsExported($model->getEntries());
}
$dispatcher->dispatch(new InvoiceCreatedEvent($invoice));
return $invoice;