From 12e348544d09826711e8a05057a037a8f74fa974 Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Tue, 21 Jul 2020 16:11:52 +0200 Subject: [PATCH] invoice: increase number, customer specific counter (#1836) --- .../ConfigurableNumberGenerator.php | 56 ++++++++++++++----- src/Repository/InvoiceRepository.php | 28 +++++++--- .../ConfigurableNumberGeneratorTest.php | 20 +++++++ 3 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/Invoice/NumberGenerator/ConfigurableNumberGenerator.php b/src/Invoice/NumberGenerator/ConfigurableNumberGenerator.php index caf00712..f72db9e2 100644 --- a/src/Invoice/NumberGenerator/ConfigurableNumberGenerator.php +++ b/src/Invoice/NumberGenerator/ConfigurableNumberGenerator.php @@ -62,16 +62,26 @@ final class ConfigurableNumberGenerator implements NumberGeneratorInterface preg_match_all('/{[^}]*?}/', $format, $matches); foreach ($matches[0] as $part) { - $formatter = null; + $formatterLength = null; + $increaseBy = 1; + $tmp = str_replace(['{', '}'], '', $part); - // number format - if (substr_count($tmp, ',') !== 0) { - $parts = explode(',', $tmp); - $tmp = $parts[0]; - $formatter = \intval($parts[1]); - if ((string) $formatter !== $parts[1]) { - $formatter = null; + $parts = preg_split('/[,]+/', $tmp); + $tmp = $parts[0]; + if (\count($parts) === 2) { + $formatterLength = \intval($parts[1]); + if ((string) $formatterLength !== $parts[1]) { + $formatterLength = null; + } + } + + $parts = preg_split("/[\+]+/", $tmp); + $tmp = $parts[0]; + if (\count($parts) === 2) { + $increaseBy = \intval($parts[1]); + if ($increaseBy <= 0) { + $increaseBy = 1; } } @@ -104,28 +114,46 @@ final class ConfigurableNumberGenerator implements NumberGeneratorInterface $partialResult = $invoiceDate->format('ymd'); break; + // for customer + case 'cc': + $partialResult = $this->repository->getCounterForAllTime($invoiceDate, $this->model->getCustomer()) + 1; + break; + + case 'ccy': + $partialResult = $this->repository->getCounterForYear($invoiceDate, $this->model->getCustomer()) + 1; + break; + + case 'ccm': + $partialResult = $this->repository->getCounterForMonth($invoiceDate, $this->model->getCustomer()) + 1; + break; + + case 'ccd': + $partialResult = $this->repository->getCounterForDay($invoiceDate, $this->model->getCustomer()) + 1; + break; + + // across all invoices case 'c': - $partialResult = $this->repository->getCounterForAllTime($invoiceDate) + 1; + $partialResult = $this->repository->getCounterForAllTime($invoiceDate) + $increaseBy; break; case 'cy': - $partialResult = $this->repository->getCounterForYear($invoiceDate) + 1; + $partialResult = $this->repository->getCounterForYear($invoiceDate) + $increaseBy; break; case 'cm': - $partialResult = $this->repository->getCounterForMonth($invoiceDate) + 1; + $partialResult = $this->repository->getCounterForMonth($invoiceDate) + $increaseBy; break; case 'cd': - $partialResult = $this->repository->getCounterForDay($invoiceDate) + 1; + $partialResult = $this->repository->getCounterForDay($invoiceDate) + $increaseBy; break; default: $partialResult = $part; } - if (null !== $formatter) { - $partialResult = str_pad($partialResult, $formatter, '0', STR_PAD_LEFT); + if (null !== $formatterLength) { + $partialResult = str_pad($partialResult, $formatterLength, '0', STR_PAD_LEFT); } $result = str_replace($part, $partialResult, $result); diff --git a/src/Repository/InvoiceRepository.php b/src/Repository/InvoiceRepository.php index 44769b47..3df27e92 100644 --- a/src/Repository/InvoiceRepository.php +++ b/src/Repository/InvoiceRepository.php @@ -9,6 +9,7 @@ namespace App\Repository; +use App\Entity\Customer; use App\Entity\Invoice; use App\Entity\User; use App\Repository\Loader\InvoiceLoader; @@ -35,7 +36,7 @@ class InvoiceRepository extends EntityRepository $entityManager->flush(); } - private function getCounterFor(\DateTime $start, \DateTime $end): int + private function getCounterFor(\DateTime $start, \DateTime $end, ?Customer $customer = null): int { $qb = $this->getEntityManager()->createQueryBuilder(); $qb->select('count(i.createdAt) as counter') @@ -46,6 +47,13 @@ class InvoiceRepository extends EntityRepository ->setParameter('end', $end) ; + if (null !== $customer) { + $qb + ->andWhere($qb->expr()->eq('i.customer', ':customer')) + ->setParameter('customer', $customer) + ; + } + $result = $qb->getQuery()->getOneOrNullResult(); if ($result === null) { @@ -55,32 +63,36 @@ class InvoiceRepository extends EntityRepository return $result['counter']; } - public function getCounterForDay(\DateTime $date): int + public function getCounterForDay(\DateTime $date, ?Customer $customer = null): int { $start = (clone $date)->setTime(0, 0, 0); $end = (clone $date)->setTime(23, 59, 59); - return $this->getCounterFor($start, $end); + return $this->getCounterFor($start, $end, $customer); } - public function getCounterForMonth(\DateTime $date): int + public function getCounterForMonth(\DateTime $date, ?Customer $customer = null): int { $start = (clone $date)->setDate((int) $date->format('Y'), (int) $date->format('n'), 1)->setTime(0, 0, 0); $end = (clone $date)->setDate((int) $date->format('Y'), (int) $date->format('n'), (int) $date->format('t'))->setTime(23, 59, 59); - return $this->getCounterFor($start, $end); + return $this->getCounterFor($start, $end, $customer); } - public function getCounterForYear(\DateTime $date): int + public function getCounterForYear(\DateTime $date, ?Customer $customer = null): int { $start = (clone $date)->setDate((int) $date->format('Y'), 1, 1)->setTime(0, 0, 0); $end = (clone $date)->setDate((int) $date->format('Y'), 12, 31)->setTime(23, 59, 59); - return $this->getCounterFor($start, $end); + return $this->getCounterFor($start, $end, $customer); } - public function getCounterForAllTime(\DateTime $date): int + public function getCounterForAllTime(\DateTime $date, ?Customer $customer = null): int { + if (null !== $customer) { + return $this->count(['customer' => $customer]); + } + return $this->count([]); } diff --git a/tests/Invoice/NumberGenerator/ConfigurableNumberGeneratorTest.php b/tests/Invoice/NumberGenerator/ConfigurableNumberGeneratorTest.php index 96a3a963..443bd072 100644 --- a/tests/Invoice/NumberGenerator/ConfigurableNumberGeneratorTest.php +++ b/tests/Invoice/NumberGenerator/ConfigurableNumberGeneratorTest.php @@ -10,6 +10,7 @@ namespace App\Tests\Invoice\NumberGenerator; use App\Configuration\SystemConfiguration; +use App\Entity\Customer; use App\Invoice\InvoiceModel; use App\Invoice\NumberGenerator\ConfigurableNumberGenerator; use App\Repository\InvoiceRepository; @@ -55,6 +56,7 @@ class ConfigurableNumberGeneratorTest extends TestCase return [ // simple tests for single calls + ['my-{date} is+cool,really', 'my-' . $invoiceDate->format('ymd') . ' is+cool,really', $invoiceDate], ['{date}', $invoiceDate->format('ymd'), $invoiceDate], ['{Y}', $invoiceDate->format('Y'), $invoiceDate], ['{y}', $invoiceDate->format('y'), $invoiceDate], @@ -73,10 +75,27 @@ class ConfigurableNumberGeneratorTest extends TestCase ['{M,3}', '0' . $invoiceDate->format('m'), $invoiceDate], ['{M,#}', $invoiceDate->format('m'), $invoiceDate], // invalid formatter length ['{D,3}', '0' . $invoiceDate->format('d'), $invoiceDate], + // counter across all invoices ['{c,2}', '02', $invoiceDate], ['{cy,2}', '02', $invoiceDate], ['{cm,2}', '02', $invoiceDate], ['{cd,2}', '02', $invoiceDate], + // customer specific + ['{cc,2}', '02', $invoiceDate], + ['{ccy,2}', '02', $invoiceDate], + ['{ccm,2}', '02', $invoiceDate], + ['{ccd,2}', '02', $invoiceDate], + // with incrementing counter + ['{c+13,2}', '14', $invoiceDate], + ['{ccy+1,2}', '02', $invoiceDate], + ['{cm+-1,2}', '02', $invoiceDate], // negative is not allowed and set to 1 + ['{cm+0,2}', '02', $invoiceDate], // zero is not allowed and set to 1 + ['{cd+111,2}', '112', $invoiceDate], + ['{c+13}', '14', $invoiceDate], + ['{cy+1}', '2', $invoiceDate], + ['{cm+-1}', '2', $invoiceDate], // negative is not allowed and set to 1 + ['{cm+0}', '2', $invoiceDate], // zero is not allowed and set to 1 + ['{cd+111}', '112', $invoiceDate], // mixing identifiers ['{Y}{cy}', $invoiceDate->format('Y') . '2', $invoiceDate], ['{Y}{cy}{m}', $invoiceDate->format('Y') . '2' . $invoiceDate->format('n'), $invoiceDate], @@ -95,6 +114,7 @@ class ConfigurableNumberGeneratorTest extends TestCase $sut = $this->getSut($format); $model = new InvoiceModel(new DebugFormatter()); $model->setInvoiceDate($invoiceDate); + $model->setCustomer(new Customer()); $sut->setModel($model); $this->assertEquals($expectedInvoiceNumber, $sut->getInvoiceNumber());