added freelancer invoice template (#254)

This commit is contained in:
Kevin Papst
2018-09-02 21:29:49 +02:00
committed by GitHub
parent ee4df36735
commit a636faa4ab
41 changed files with 1105 additions and 145 deletions

View File

@@ -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

View 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,
]);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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];

View File

@@ -34,7 +34,7 @@ class InvoiceModel
/**
* @var Timesheet[]
*/
protected $entries;
protected $entries = [];
/**
* @var InvoiceTemplate

View File

@@ -37,6 +37,7 @@ class Markdown
public function toHtml(string $text, bool $safe = true): string
{
$this->parser->setSafeMode($safe);
return $this->parser->text($text);
}
}