Skip to content

Commit

Permalink
1635: Added option to generate one invoice per issue
Browse files Browse the repository at this point in the history
  • Loading branch information
rimi-itk committed Jun 12, 2024
1 parent 87eb3ca commit c3286ae
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 20 deletions.
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ INVOICE_ENTRY_ACCOUNTS='{
"label": "Define INVOICE_ENTRY_ACCOUNTS in .env.local"
}
}'

# If true, project billing will generate one invoice per issue per client.
# Otherwise, all issues will be added to a single invoice per client.
INVOICE_ONE_INVOICE_PER_ISSUE=false
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

* [PR-130](https://github.com/itk-dev/economics/pull/130)
1635: Reduced product invoice entries to a single entry
Reduced product invoice entries to a single entry
Added option to generate one invoice per issue
* NOTE: APP_DEFAULT_PLANNING_DATA_PROVIDER has been changed to APP_DEFAULT_DATA_PROVIDER. This has to be changed when releasing.
* [PR-117](https://github.com/itk-dev/economics/pull/117)
1211: Added hour report
Expand Down
2 changes: 1 addition & 1 deletion config/packages/twig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ twig:
format: 'd.m.Y'
globals:
view_controller: '@App\Controller\ViewController'
invoice_entry_helper: '@App\Service\InvoiceEntryHelper'
invoice_helper: '@App\Service\InvoiceHelper'

when@test:
twig:
Expand Down
3 changes: 2 additions & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ services:
issue_product_type_options:
quantity_scale: '%env(int:PRODUCT_QUANTITY_SCALE)%'

App\Service\InvoiceEntryHelper:
App\Service\InvoiceHelper:
arguments:
$options:
accounts: '%env(json:INVOICE_ENTRY_ACCOUNTS)%'
one_invoice_per_issue: '%env(bool:INVOICE_ONE_INVOICE_PER_ISSUE)%'
4 changes: 2 additions & 2 deletions src/Controller/InvoiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use App\Repository\InvoiceRepository;
use App\Service\BillingService;
use App\Service\ClientHelper;
use App\Service\InvoiceEntryHelper;
use App\Service\InvoiceHelper;
use App\Service\ViewService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
Expand All @@ -38,7 +38,7 @@ public function __construct(
private readonly BillingService $billingService,
private readonly TranslatorInterface $translator,
private readonly ViewService $viewService,
private readonly InvoiceEntryHelper $invoiceEntryHelper,
private readonly InvoiceHelper $invoiceEntryHelper,
) {
}

Expand Down
6 changes: 3 additions & 3 deletions src/Controller/InvoiceEntryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use App\Repository\InvoiceEntryRepository;
use App\Service\BillingService;
use App\Service\ClientHelper;
use App\Service\InvoiceEntryHelper;
use App\Service\InvoiceHelper;
use App\Service\ViewService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
Expand All @@ -28,7 +28,7 @@ public function __construct(
private readonly TranslatorInterface $translator,
private readonly ViewService $viewService,
private readonly ClientHelper $clientHelper,
private readonly InvoiceEntryHelper $invoiceEntryHelper,
private readonly InvoiceHelper $invoiceHelper,
) {
}

Expand Down Expand Up @@ -93,7 +93,7 @@ public function edit(Request $request, Invoice $invoice, InvoiceEntry $invoiceEn
$options['disabled'] = true;
}

$accounts = $this->invoiceEntryHelper->getAccountOptions($invoiceEntry->getAccount());
$accounts = $this->invoiceHelper->getAccountOptions($invoiceEntry->getAccount());
if (!empty($accounts)) {
$options['invoice_entry_accounts'] = $accounts;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class InvoiceEntryHelper
class InvoiceHelper
{
private readonly array $options;

Expand All @@ -17,6 +17,11 @@ public function __construct(
$this->options = $this->resolveOptions($options);
}

public function getOneInvoicePerIssue()
{
return $this->options['one_invoice_per_issue'];
}

/**
* Get all configured accounts.
*
Expand Down Expand Up @@ -99,7 +104,7 @@ public function getAccountInvoiceEntryPrefix(string $account): ?string
/**
* Decide if an invoice entry is editable.
*/
public function isEditable(InvoiceEntry $entry): bool
public function isEntryEditable(InvoiceEntry $entry): bool
{
return null === $entry->getInvoice()?->getProjectBilling()
|| count($this->getAccountOptions(null)) > 1;
Expand Down Expand Up @@ -140,7 +145,8 @@ private function resolveOptions(array $options): array
'invoice_entry_prefix' => null,
])
->setAllowedTypes('default', 'bool')
->setAllowedTypes('product', 'bool');
->setAllowedTypes('product', 'bool')
->setAllowedTypes('invoice_entry_prefix', ['null', 'string']);
})
->setAllowedValues('accounts', function (array $values) {
if (empty($values)) {
Expand Down Expand Up @@ -180,6 +186,9 @@ private function resolveOptions(array $options): array
return $values;
})

->setDefault('one_invoice_per_issue', false)
->setAllowedTypes('one_invoice_per_issue', 'bool')

->resolve($options);
}
}
30 changes: 23 additions & 7 deletions src/Service/ProjectBillingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(
private readonly ClientHelper $clientHelper,
private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
private readonly InvoiceEntryHelper $invoiceEntryHelper,
private readonly InvoiceHelper $invoiceEntryHelper,
) {
}

Expand Down Expand Up @@ -167,17 +167,21 @@ public function createProjectBilling(int $projectBillingId): void
continue;
}

$clientId = $client->getId();
$invoiceKey = $client->getId();

if (null !== $clientId) {
if (!isset($invoices[$clientId])) {
$invoices[$clientId] = [
if (null !== $invoiceKey) {
if ($this->invoiceEntryHelper->getOneInvoicePerIssue()) {
$invoiceKey .= '|||'.$issue->getId();
}

if (!isset($invoices[$invoiceKey])) {
$invoices[$invoiceKey] = [
'client' => $client,
'issues' => [],
];
}

$invoices[$clientId]['issues'][] = $issue;
$invoices[$invoiceKey]['issues'][] = $issue;
}
}

Expand All @@ -202,12 +206,24 @@ public function createProjectBilling(int $projectBillingId): void
/** @var Client $client */
$client = $invoiceArray['client'];

$invoiceName = sprintf('%s: %s (%s - %s)',
$project->getName() ?? '',
$client->getName() ?? '',
$periodStart->format('d/m/Y'),
$periodEnd->format('d/m/Y')
);
if ($this->invoiceEntryHelper->getOneInvoicePerIssue()) {
// We know that we have at least one issue.
$issue = reset($invoiceArray['issues']);
$invoiceName = $issue->getName() . ': ' . $invoiceName;
}

$invoice = new Invoice();
$invoice->setRecorded(false);
$invoice->setProject($projectBilling->getProject());
$invoice->setProjectBilling($projectBilling);
$invoice->setDescription($projectBilling->getDescription());
$invoice->setName($project->getName().': '.$client->getName().' ('.$periodStart->format('d/m/Y').' - '.$periodEnd->format('d/m/Y').')');
$invoice->setName($invoiceName);
$invoice->setPeriodFrom($periodStart);
$invoice->setPeriodTo($periodEnd);
$invoice->setClient($client);
Expand Down
2 changes: 1 addition & 1 deletion templates/invoice_entry/edit.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<div class="grid-split">
<div>
{{ form_widget(form) }}
{% if not invoice.recorded and invoice_entry_helper.isEditable(invoice_entry) %}
{% if not invoice.recorded and invoice_helper.isEntryEditable(invoice_entry) %}
<div class="actions-right">
<button class="button mt-3">{{ 'invoices.action_save_invoice_entry'|trans }}</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/invoices/edit.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
} %}
{% for index, invoice_entry in invoice.invoiceEntries %}
<tr class="{{ index % 2 == 0 ? 'table-tr' : 'table-tr-alt' }}">
<td class="table-td">{{ invoice_entry_helper.getAccountLabel(invoice_entry.account) }}</td>
<td class="table-td">{{ invoice_helper.getAccountLabel(invoice_entry.account) }}</td>
<td class="table-td">{{ invoice_entry.materialNumber.value ?? '' }}</td>
<td class="table-td">{{ invoice_entry.product }}</td>
<td class="table-td">{{ invoice_entry.amount }}</td>
Expand Down

0 comments on commit c3286ae

Please sign in to comment.