Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e1ac9d3
Allow template overwrite from console invoice creation command
kernie Feb 6, 2025
7c50afb
Add template logic to method createInvoicesForCustomer
kernie Feb 6, 2025
9e9e0e2
Added message for invalid template parameter
kernie Feb 6, 2025
e420eed
Fix wrong apostrophe syntax in warning
kernie Feb 6, 2025
b76c22f
Fix missing return value
kernie Feb 6, 2025
de2d452
Adapt code checking
kernie Feb 6, 2025
a4afd44
Fix adaption of phpstanf
kernie Feb 6, 2025
bbf20fe
Adapt test to template overwrite
kernie Feb 7, 2025
448580e
Remove customer argument of template method
kernie Feb 7, 2025
972b0cb
Fix code for test
kernie Feb 7, 2025
25adc4d
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Feb 8, 2025
b7062fc
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Feb 10, 2025
8965c8b
Add additional test for coverage
kernie Feb 11, 2025
3963d75
Merge remote-tracking branch 'refs/remotes/origin/feature-console-tem…
kernie Feb 11, 2025
a28a6b7
Adapt test to CI screen output size
kernie Feb 11, 2025
f96615b
Again adaption for CI screen output
kernie Feb 11, 2025
787ec47
Adapt phpstan to test
kernie Feb 12, 2025
c292609
Add test for templateId
kernie Feb 12, 2025
1e91b78
Add assertion, adapt phpstan
kernie Feb 16, 2025
f3494f5
Make Command fail when invalid template is given
kernie Feb 17, 2025
0a58255
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Feb 17, 2025
7e4847d
make phpstan happy
kernie Feb 21, 2025
f0413c0
Check option --template for string or int value
kernie Feb 24, 2025
29e74d1
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Feb 25, 2025
236a76b
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Feb 28, 2025
3e4f9df
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Mar 13, 2025
f29d6d4
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Mar 14, 2025
9b6da67
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Apr 23, 2025
33e6410
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie May 18, 2025
cdb6998
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie May 26, 2025
c896822
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie May 28, 2025
97b1faa
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Jun 13, 2025
b38b863
Merge branch 'main' into feature-console-template-parameter-overwrite
kernie Jul 1, 2025
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
53 changes: 37 additions & 16 deletions src/Command/InvoiceCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$searchTerm = new SearchTerm($input->getOption('search'));
}

if ($input->getOption('preview') !== null) {
if (null !== $input->getOption('preview')) {
$this->previewUniqueFile = (bool) $input->getOption('preview-unique');
$this->previewDirectory = rtrim($input->getOption('preview'), '/') . '/';
if (!is_dir($this->previewDirectory) || !is_writable($this->previewDirectory)) {
Expand All @@ -197,6 +197,23 @@ protected function execute(InputInterface $input, OutputInterface $output): int
@trigger_error('The "set-exported" option of kimai:invoice:create command has no meaning anymore, it will be removed soon', E_USER_DEPRECATED);
}

$overwriteTemplate = null;
if (null !== ($tplOption = $input->getOption('template'))) {
if (\is_string($tplOption) || \is_int($tplOption)){
$tplOption = \strval($tplOption);
$overwriteTemplate = $this->getCommandLineArgumentTemplateForCustomer($tplOption);
if (null === $overwriteTemplate){
$io->error('Invalid invoice template name or id given');

return Command::FAILURE;
}
} else {
$io->error('Option --template must be string or int');

return Command::FAILURE;
}
}

// =============== VALIDATION END ===============

$defaultQuery = new InvoiceQuery();
Expand All @@ -205,6 +222,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$defaultQuery->setCurrentUser($user);
$defaultQuery->setSearchTerm($searchTerm);
$defaultQuery->setExported($exportedFilter);
if (null !== $overwriteTemplate){
$defaultQuery->setTemplate($overwriteTemplate);
$defaultQuery->setAllowTemplateOverwrite(true);
}

/** @var Invoice[] $invoices */
$invoices = [];
Expand Down Expand Up @@ -276,12 +297,15 @@ protected function createInvoicesForProjects(array $projects, InvoiceQuery $defa
$query->addProject($project);
$query->addCustomer($customer);

$tpl = $this->getTemplateForCustomer($input, $customer);
$tpl = $query->getTemplate();
if (null === $tpl) {
$io->warning(\sprintf('Could not find invoice template for project "%s", skipping!', $project->getName()));
continue;
$tpl = $customer->getInvoiceTemplate();
if (null === $tpl) {
$io->warning(\sprintf('Could not find invoice template for project "%s", skipping!', $project->getName()));
continue;
}
$query->setTemplate($tpl);
}
$query->setTemplate($tpl);

try {
$model = $this->serviceInvoice->createModel($query);
Expand Down Expand Up @@ -351,12 +375,15 @@ protected function createInvoicesForCustomer(array $customers, InvoiceQuery $def
$query = clone $defaultQuery;
$query->addCustomer($customer);

$tpl = $this->getTemplateForCustomer($input, $customer);
$tpl = $query->getTemplate();
if (null === $tpl) {
$io->warning(\sprintf('Could not find invoice template for customer "%s", skipping!', $customer->getName()));
continue;
$tpl = $customer->getInvoiceTemplate();
if (null === $tpl) {
$io->warning(\sprintf('Could not find invoice template for customer "%s", skipping!', $customer->getName()));
continue;
}
$query->setTemplate($tpl);
}
$query->setTemplate($tpl);

try {
$model = $this->serviceInvoice->createModel($query);
Expand Down Expand Up @@ -435,14 +462,8 @@ protected function renderInvoiceResult(InputInterface $input, OutputInterface $o
return Command::SUCCESS;
}

private function getTemplateForCustomer(InputInterface $input, Customer $customer): ?InvoiceTemplate
private function getCommandLineArgumentTemplateForCustomer(string $template): ?InvoiceTemplate
{
$template = $input->getOption('template');

if (null === $template) {
return $customer->getInvoiceTemplate();
}

$tpl = $this->invoiceTemplateRepository->find($template);

if (null !== $tpl) {
Expand Down
60 changes: 60 additions & 0 deletions tests/Command/InvoiceCreateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
$commandTester = $this->createInvoice($options);

$output = $commandTester->getDisplay();
self::assertStringContainsString('[ERROR] ' . $errorMessage, $output);

Check failure on line 111 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.3)

Failed asserting that '\n

Check failure on line 111 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.3)

Failed asserting that '\n

Check failure on line 111 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.4)

Failed asserting that '\n

Check failure on line 111 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.4)

Failed asserting that '\n
}

public function testCreateWithUnknownExportFilter(): void
Expand Down Expand Up @@ -305,4 +305,64 @@
$output = $commandTester->getDisplay();
self::assertStringContainsString('Created 1 invoice(s) ', $output);
}

public function testCreateInvoiceWithTemplateOverwrite(): void
{
$start = new \DateTime('-2 months');
$end = new \DateTime();
$this->prepareFixtures($start)[0];

$commandTester = $this->createInvoice(['--user' => UserFixtures::USERNAME_SUPER_ADMIN, '--customer' => 1, '--template' => 'MyInvoice', '--exported' => 'all', '--start' => $start->format('Y-m-d'), '--end' => $end->format('Y-m-d')]);

$output = $commandTester->getDisplay();

self::assertStringContainsString('Created 1 invoice(s) ', $output);

Check failure on line 319 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.3)

Failed asserting that '\n

Check failure on line 319 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.4)

Failed asserting that '\n
self::assertStringContainsString('/tests/_data/invoices/' . ((new \DateTime())->format('Y')) . '-001-Test.pdf |', $output);
}

public function testCreateInvoiceWithTemplateId(): void
{
$start = new \DateTime('-2 months');
$end = new \DateTime();
$customer = $this->prepareFixtures($start)[0];
self::assertNotNull($customer);
$customerId = $customer->getId();
$template = $customer->getInvoiceTemplate();
self::assertNotNull($template);
$templateId = $template->getId();
$customer->SetInvoiceTemplate(null);

$commandTester = $this->createInvoice(['--user' => UserFixtures::USERNAME_SUPER_ADMIN, '--customer' => $customerId, '--template' => $templateId, '--exported' => 'all', '--start' => $start->format('Y-m-d'), '--end' => $end->format('Y-m-d')]);

$output = $commandTester->getDisplay();

self::assertStringContainsString('Created 1 invoice(s) ', $output);
}

public function testCreateInvoiceWithTemplateOverwriteProjectIdMissingTemplate(): void
{
$start = new \DateTime('-2 months');
$end = new \DateTime();

$customer = $this->prepareFixtures($start)[0];
$customer->SetInvoiceTemplate(null);

$commandTester = $this->createInvoice(['--user' => UserFixtures::USERNAME_SUPER_ADMIN, '--exported' => 'all', '--project' => '1', '--template' => 'NoInvoice', '--start' => $start->format('Y-m-d'), '--end' => $end->format('Y-m-d')]);
$output = $commandTester->getDisplay();

self::assertStringContainsString('Invalid invoice template name or id given', $output);
}

public function testCreateInvoiceByProjectIdSearchTerm(): void
{
$start = new \DateTime('-2 months');
$end = new \DateTime();

$this->prepareFixtures($start);

$commandTester = $this->createInvoice(['--user' => UserFixtures::USERNAME_SUPER_ADMIN, '--exported' => 'all', '--project' => '1', '--template' => 'Invoice', '--search' => 'wxjehrchskejrht', '--start' => $start->format('Y-m-d'), '--end' => $end->format('Y-m-d')]);
$output = $commandTester->getDisplay();

self::assertStringContainsString('Created 1 invoice(s) ', $output);

Check failure on line 366 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.3)

Failed asserting that '\n

Check failure on line 366 in tests/Command/InvoiceCreateCommandTest.php

View workflow job for this annotation

GitHub Actions / Integration (8.4)

Failed asserting that '\n
}
}
2 changes: 1 addition & 1 deletion tests/Controller/InvoiceControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ public function testDeleteTemplateAction(): void
self::assertTrue($client->getResponse()->isSuccessful());
$this->assertHasFlashSuccess($client);

self::assertEquals(0, $this->getEntityManager()->getRepository(InvoiceTemplate::class)->count([]));
self::assertEquals(1, $this->getEntityManager()->getRepository(InvoiceTemplate::class)->count([]));
}

public function testUploadDocumentAction(): void
Expand Down
28 changes: 27 additions & 1 deletion tests/DataFixtures/InvoiceTemplateFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,36 @@ public function load(ObjectManager $manager): array
$template->setRenderer('invoice');

$manager->persist($template);
$manager->flush();

$created[] = $template;

$template2 = new InvoiceTemplate();

$template2->setName('MyInvoice');
$template2->setTitle('Your company name');
$template2->setCompany($faker->company());
$template2->setVat(19);
$template2->setDueDays(14);
$template2->setPaymentTerms(
'I would like to thank you for your confidence and will gladly be there for you in the future.' .
PHP_EOL .
'Please transfer the total amount within 14 days to the given account and use the invoice number ' .
'as reference.'
);
$template2->setAddress(
$faker->streetAddress() . PHP_EOL .
$faker->city() . ' ' . $faker->postcode() . ', ' . $faker->country() . PHP_EOL .
'Phone: ' . $faker->phoneNumber() . PHP_EOL .
'Email: ' . $faker->safeEmail()
);
$template2->setLanguage('en');
$template2->setRenderer('default');

$manager->persist($template2);
$manager->flush();

$created[] = $template2;

return $created;
}
}
Loading