added freelancer invoice template (#254)
This commit is contained in:
@@ -92,23 +92,55 @@ class InvoiceController extends AbstractController
|
||||
|
||||
$query = $this->getDefaultQuery();
|
||||
$form = $this->getToolbarForm($query);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
/** @var InvoiceQuery $query */
|
||||
$query = $form->getData();
|
||||
$query->setResultType(TimesheetQuery::RESULT_TYPE_QUERYBUILDER);
|
||||
|
||||
if (null !== $query->getCustomer()) {
|
||||
$query->getBegin()->setTime(0, 0, 0);
|
||||
$query->getEnd()->setTime(23, 59, 59);
|
||||
|
||||
$queryBuilder = $this->timesheetRepository->findByQuery($query);
|
||||
$entries = $queryBuilder->getQuery()->getResult();
|
||||
}
|
||||
$entries = $this->getEntries($query);
|
||||
}
|
||||
|
||||
$model = $this->prepareModel($query, $entries);
|
||||
|
||||
$action = null;
|
||||
if ($query->getTemplate() !== null) {
|
||||
$action = $this->service->getRendererActionByName($query->getTemplate()->getRenderer());
|
||||
}
|
||||
|
||||
return $this->render('invoice/index.html.twig', [
|
||||
'model' => $model,
|
||||
'action' => $action,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceQuery $query
|
||||
* @return Timesheet[]
|
||||
*/
|
||||
protected function getEntries(InvoiceQuery $query)
|
||||
{
|
||||
if (null === $query->getCustomer()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query->setResultType(TimesheetQuery::RESULT_TYPE_QUERYBUILDER);
|
||||
$query->getBegin()->setTime(0, 0, 0);
|
||||
$query->getEnd()->setTime(23, 59, 59);
|
||||
|
||||
$queryBuilder = $this->timesheetRepository->findByQuery($query);
|
||||
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceQuery $query
|
||||
* @param array $entries
|
||||
* @return InvoiceModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareModel(InvoiceQuery $query, array $entries)
|
||||
{
|
||||
$model = new InvoiceModel();
|
||||
$model->setQuery($query);
|
||||
$model->setEntries($entries);
|
||||
@@ -129,14 +161,9 @@ class InvoiceController extends AbstractController
|
||||
$model->setTemplate($query->getTemplate());
|
||||
$model->setCalculator($calculator);
|
||||
$model->setNumberGenerator($generator);
|
||||
$action = $this->service->getRendererActionByName($query->getTemplate()->getRenderer());
|
||||
}
|
||||
|
||||
return $this->render('invoice/index.html.twig', [
|
||||
'model' => $model,
|
||||
'action' => $action,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +256,7 @@ class InvoiceController extends AbstractController
|
||||
try {
|
||||
$this->invoiceRepository->saveTemplate($template);
|
||||
$this->flashSuccess('action.update.success');
|
||||
|
||||
return $this->redirectToRoute('admin_invoice_template');
|
||||
} catch (\Exception $ex) {
|
||||
$this->flashError('action.update.error', ['%reason%' => $ex->getMessage()]);
|
||||
@@ -241,28 +269,6 @@ class InvoiceController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceModel $model
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function invoiceAction(InvoiceModel $model)
|
||||
{
|
||||
return $this->render('invoice/renderer/print.html.twig', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceModel $model
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function timesheetAction(InvoiceModel $model)
|
||||
{
|
||||
return $this->render('invoice/renderer/timesheet.html.twig', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceQuery $query
|
||||
* @return \Symfony\Component\Form\FormInterface
|
||||
|
||||
54
src/Controller/InvoicePrintController.php
Normal file
54
src/Controller/InvoicePrintController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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\Controller;
|
||||
|
||||
use App\Model\InvoiceModel;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
|
||||
/**
|
||||
* Controller used to print invoices.
|
||||
*
|
||||
* @Security("is_granted('ROLE_TEAMLEAD')")
|
||||
*/
|
||||
class InvoicePrintController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @param InvoiceModel $model
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function printInvoice(InvoiceModel $model)
|
||||
{
|
||||
return $this->render('invoice/renderer/invoice.html.twig', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceModel $model
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function printTimesheet(InvoiceModel $model)
|
||||
{
|
||||
return $this->render('invoice/renderer/timesheet.html.twig', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InvoiceModel $model
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function printFreelancer(InvoiceModel $model)
|
||||
{
|
||||
return $this->render('invoice/renderer/freelancer.html.twig', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,15 @@ class InvoiceFixtures extends Fixture
|
||||
*/
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$this->loadInvoiceTemplates($manager);
|
||||
$this->loadInvoiceTemplate($manager);
|
||||
$this->loadFreelancerTemplate($manager);
|
||||
$this->loadTimesheetTemplate($manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
*/
|
||||
private function loadInvoiceTemplates(ObjectManager $manager)
|
||||
private function loadInvoiceTemplate(ObjectManager $manager)
|
||||
{
|
||||
$faker = Factory::create();
|
||||
|
||||
@@ -44,7 +46,10 @@ class InvoiceFixtures extends Fixture
|
||||
->setTitle('Your company name')
|
||||
->setCompany($faker->company)
|
||||
->setVat(19)
|
||||
->setDueDays(14)
|
||||
->setDueDays(30)
|
||||
->setRenderer('default')
|
||||
->setCalculator('default')
|
||||
->setNumberGenerator('default')
|
||||
->setPaymentTerms(
|
||||
'I would like to thank you for your confidence and will gladly be there for you in the future.' .
|
||||
PHP_EOL .
|
||||
@@ -62,4 +67,68 @@ class InvoiceFixtures extends Fixture
|
||||
$manager->persist($template);
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
*/
|
||||
private function loadFreelancerTemplate(ObjectManager $manager)
|
||||
{
|
||||
$faker = Factory::create();
|
||||
|
||||
$template = new InvoiceTemplate();
|
||||
$template
|
||||
->setName('Freelancer')
|
||||
->setTitle('Rechnung')
|
||||
->setCompany($faker->company)
|
||||
->setVat(19)
|
||||
->setDueDays(14)
|
||||
->setRenderer('freelancer')
|
||||
->setCalculator('short')
|
||||
->setNumberGenerator('default')
|
||||
->setPaymentTerms(
|
||||
'Bitte überweisen Sie den Gesamtbetrag innerhalb von 14 Tagen nach Erhalt der Rechnung auf das unten genannte Konto. Verwenden Sie bitte als Betreff Ihrer Überweisung die Rechnungsnummer.' .
|
||||
PHP_EOL .
|
||||
PHP_EOL .
|
||||
'Ich bedanke mich für das entgegengebrachte Vertrauen. Gerne bin ich auch künftig für Sie da.' .
|
||||
PHP_EOL .
|
||||
PHP_EOL .
|
||||
'Mit freundlichen Grüßen,' .
|
||||
PHP_EOL .
|
||||
'Max Müller'
|
||||
)
|
||||
->setAddress(
|
||||
$faker->name . ' - ' . $faker->streetAddress . '-' . $faker->postcode . ' ' . $faker->city
|
||||
)
|
||||
;
|
||||
|
||||
$manager->persist($template);
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
*/
|
||||
private function loadTimesheetTemplate(ObjectManager $manager)
|
||||
{
|
||||
$faker = Factory::create();
|
||||
|
||||
$template = new InvoiceTemplate();
|
||||
$template
|
||||
->setName('Timesheet')
|
||||
->setTitle('Stundenzettel')
|
||||
->setCompany($faker->company)
|
||||
->setVat(19)
|
||||
->setDueDays(14)
|
||||
->setRenderer('timesheet')
|
||||
->setCalculator('default')
|
||||
->setNumberGenerator('default')
|
||||
->setPaymentTerms('')
|
||||
->setAddress(
|
||||
$faker->name . ' - ' . $faker->streetAddress . '-' . $faker->postcode . ' ' . $faker->city
|
||||
)
|
||||
;
|
||||
|
||||
$manager->persist($template);
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +58,18 @@ interface CalculatorInterface
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrency(): string;
|
||||
|
||||
/**
|
||||
* Returns the percentage for the value-added tax (VAT) calculation.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getVat(): ?float;
|
||||
|
||||
/**
|
||||
* Returns the total amount of worked time in seconds.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeWorked(): int;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class DefaultCalculator implements CalculatorInterface
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getVat()
|
||||
public function getVat(): ?float
|
||||
{
|
||||
return $this->model->getTemplate()->getVat();
|
||||
}
|
||||
@@ -97,4 +97,19 @@ class DefaultCalculator implements CalculatorInterface
|
||||
{
|
||||
return $this->model->getCustomer()->getCurrency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total amount of worked time in seconds.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeWorked(): int
|
||||
{
|
||||
$time = 0;
|
||||
foreach ($this->model->getEntries() as $entry) {
|
||||
$time += $entry->getDuration();
|
||||
}
|
||||
|
||||
return $time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,16 @@ class ShortInvoiceCalculator extends DefaultCalculator
|
||||
foreach ($this->model->getEntries() as $entry) {
|
||||
$timesheet->setRate($timesheet->getRate() + $entry->getRate());
|
||||
$timesheet->setDuration($timesheet->getDuration() + $entry->getDuration());
|
||||
$timesheet->setBegin($entry->getBegin());
|
||||
if (null === $timesheet->getActivity()) {
|
||||
$timesheet->setActivity($entry->getActivity());
|
||||
$timesheet->setEnd($entry->getEnd());
|
||||
}
|
||||
$timesheet->setBegin($entry->getBegin());
|
||||
}
|
||||
|
||||
if (null !== $this->model->getQuery()->getActivity()) {
|
||||
$timesheet->setDescription($this->model->getQuery()->getActivity()->getName());
|
||||
} elseif (null !== $this->model->getQuery()->getProject()) {
|
||||
$timesheet->setDescription($this->model->getQuery()->getProject()->getName());
|
||||
}
|
||||
|
||||
return [$timesheet];
|
||||
|
||||
@@ -34,7 +34,7 @@ class InvoiceModel
|
||||
/**
|
||||
* @var Timesheet[]
|
||||
*/
|
||||
protected $entries;
|
||||
protected $entries = [];
|
||||
|
||||
/**
|
||||
* @var InvoiceTemplate
|
||||
|
||||
@@ -37,6 +37,7 @@ class Markdown
|
||||
public function toHtml(string $text, bool $safe = true): string
|
||||
{
|
||||
$this->parser->setSafeMode($safe);
|
||||
|
||||
return $this->parser->text($text);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user