diff --git a/migrations/Version20230705133033.php b/migrations/Version20230705133033.php
new file mode 100644
index 0000000..2c8381f
--- /dev/null
+++ b/migrations/Version20230705133033.php
@@ -0,0 +1,29 @@
+addSql('ALTER TABLE criminal ADD amount_community_work INT AFTER amount_time');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE criminal DROP amount_community_work');
+ }
+}
diff --git a/migrations/Version20230705133715.php b/migrations/Version20230705133715.php
new file mode 100644
index 0000000..9319fa6
--- /dev/null
+++ b/migrations/Version20230705133715.php
@@ -0,0 +1,30 @@
+addSql('ALTER TABLE criminal ADD amount_money_settled DOUBLE PRECISION DEFAULT NULL, ADD amount_time_settled INT DEFAULT NULL, ADD amount_community_work_settled INT DEFAULT NULL');
+ $this->addSql('UPDATE criminal SET amount_money_settled = amount_money, amount_time_settled = amount_time, amount_community_work_settled = amount_community_work');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE criminal DROP amount_money_settled, DROP amount_time_settled, DROP amount_community_work_settled');
+ }
+}
diff --git a/src/Controller/UnsettledSentenceController.php b/src/Controller/UnsettledSentenceController.php
new file mode 100644
index 0000000..5517742
--- /dev/null
+++ b/src/Controller/UnsettledSentenceController.php
@@ -0,0 +1,114 @@
+logger = $logger;
+ }
+
+ #[Route('/list/{type?*}', name: 'list')]
+ public function list(
+ PaginatorInterface $paginator,
+ Request $request,
+ CriminalRepository $CriminalRepository,
+ string $type = 'fine'
+ ): Response {
+
+ $searchForm = $this->createForm(SearchBarType::class);
+ $searchForm->handleRequest($request);
+
+ $pagination = $paginator->paginate(
+ $CriminalRepository->listForUser($this->getUser())
+ ->search((
+ $searchForm->isSubmitted()
+ && $searchForm->isValid()
+ && $searchForm->getData()['subject'] !== null
+ ) ? $searchForm->getData()['subject'] : null)
+ ->limitUnsettled($type)
+ ->order(['createdAt' => 'DESC'])
+ ->getResult(),
+ $request->query->getInt('page', 1)
+ );
+
+ foreach ($pagination as $i => $criminal) {
+ $sentence = new SentenceSettlement($criminal, $type);
+ $form = $this->createForm(
+ SentenceSettlementType::class,
+ $sentence,
+ ['action' => $this->generateUrl('unsettled_sentence_settle'),]
+ );
+ $pagination[$i]->form = $form->createView();
+ }
+
+ return $this->render('sentence/list.html.twig', [
+ 'controller_name' => 'AdminController',
+ 'type' => $type,
+ 'pagination' => $pagination,
+ 'count' => $pagination->getTotalItemCount(),
+ 'searchForm' => $searchForm->createView(),
+ ]);
+ }
+
+ #[Route('/settle', name: 'settle')]
+ public function settle(
+ Request $request,
+ CriminalRepository $CriminalRepository
+ ) {
+ $type = null;
+ $sentenceForm = $this->createForm(SentenceSettlementType::class);
+ $sentenceForm->handleRequest($request);
+
+ if ($sentenceForm->isSubmitted() && $sentenceForm->isValid()) {
+ $formData = $sentenceForm->getData();
+ $type = $formData['type'];
+ $criminal = $CriminalRepository->find($formData['criminal_id']);
+ if (!$criminal) {
+ $sentenceForm->addError(new FormError('error_document_not_found'));
+ } else {
+ try {
+ $criminal->addSettlement($type, $formData['amount']);
+ } catch (\OutOfRangeException $e) {
+ $sentenceForm->addError(new FormError('error_value_out_of_bound'));
+ }
+ }
+ if ($sentenceForm->isValid()) {
+ $entityManager = $this->getDoctrine()->getManager();
+ $entityManager->persist($criminal);
+ try {
+ $entityManager->flush();
+ } catch (\Throwable $th) {
+ if ($_ENV['APP_ENV'] === 'dev') {
+ throw $th; //DEBUG
+ } else {
+ $this->logger->error($th);
+ }
+
+ $this->addFlash('danger', 'alert_error_editing_document');
+ return $this->redirectToRoute($request->getRequestUri());
+ }
+ } else {
+ $this->addFlash('warning', 'alert_error_form_post');
+ }
+ }
+
+ return $this->redirectToRoute('unsettled_sentence_list', ['type' => $type]);
+ }
+}
diff --git a/src/Entity/Criminal.php b/src/Entity/Criminal.php
index 5478f62..025ee24 100644
--- a/src/Entity/Criminal.php
+++ b/src/Entity/Criminal.php
@@ -2,6 +2,7 @@
namespace App\Entity;
+use OutOfRangeException;
use App\Entity\Document;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\CriminalRepository;
@@ -13,6 +14,10 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
class Criminal extends Document
{
+ public const TYPE_JAIL = 'jail';
+ public const TYPE_FINE = 'fine';
+ public const TYPE_COMMUNITY_WORK = 'community_work';
+
/**
* @ORM\ManyToOne(targetEntity=Directory::class, inversedBy="criminals")
* @ORM\JoinColumn(nullable=false)
@@ -31,6 +36,12 @@ class Criminal extends Document
*/
private $amountTime;
+ /**
+ * @ORM\Column(type="integer", nullable=true)
+ * @Gedmo\Versioned
+ */
+ private $amountCommunityWork;
+
/**
* @ORM\Column(type="text", length=4294967295, nullable=true)
* @Gedmo\Versioned
@@ -41,6 +52,24 @@ class Criminal extends Document
*/
private $content;
+ /**
+ * @ORM\Column(type="float", nullable=true)
+ * @Gedmo\Versioned
+ */
+ private $amountMoneySettled;
+
+ /**
+ * @ORM\Column(type="integer", nullable=true)
+ * @Gedmo\Versioned
+ */
+ private $amountTimeSettled;
+
+ /**
+ * @ORM\Column(type="integer", nullable=true)
+ * @Gedmo\Versioned
+ */
+ private $amountCommunityWorkSettled;
+
public function __construct(User $user)
{
parent::__construct($user);
@@ -83,6 +112,18 @@ class Criminal extends Document
return $this;
}
+ public function getAmountCommunityWork(): ?int
+ {
+ return $this->amountCommunityWork;
+ }
+
+ public function setAmountCommunityWork(?int $amountCommunityWork): self
+ {
+ $this->amountCommunityWork = $amountCommunityWork;
+
+ return $this;
+ }
+
public function getContent(): ?string
{
return $this->content;
@@ -94,4 +135,64 @@ class Criminal extends Document
return $this;
}
+
+ public function getAmountMoneySettled(): ?float
+ {
+ return $this->amountMoneySettled;
+ }
+
+ public function setAmountMoneySettled(?float $amountMoneySettled): self
+ {
+ $this->amountMoneySettled = $amountMoneySettled;
+
+ return $this;
+ }
+
+ public function getAmountTimeSettled(): ?int
+ {
+ return $this->amountTimeSettled;
+ }
+
+ public function setAmountTimeSettled(?int $amountTimeSettled): self
+ {
+ $this->amountTimeSettled = $amountTimeSettled;
+
+ return $this;
+ }
+
+ public function getAmountCommunityWorkSettled(): ?int
+ {
+ return $this->amountCommunityWorkSettled;
+ }
+
+ public function setAmountCommunityWorkSettled(?int $amountCommunityWorkSettled): self
+ {
+ $this->amountCommunityWorkSettled = $amountCommunityWorkSettled;
+
+ return $this;
+ }
+
+ public function addSettlement($type, $amount)
+ {
+ if ($type == Criminal::TYPE_FINE) {
+ if ($this->getAmountMoney() - $this->getAmountMoneySettled() < $amount) {
+ throw new OutOfRangeException();
+ }
+ $this->setAmountMoneySettled($this->getAmountMoneySettled() + $amount);
+ } elseif ($type == Criminal::TYPE_JAIL) {
+ if ($this->getAmountTime() - $this->getAmountTimeSettled() < $amount) {
+ throw new OutOfRangeException();
+ }
+ $this->setAmountTimeSettled($this->getAmountTimeSettled() + $amount);
+ } elseif ($type == Criminal::TYPE_COMMUNITY_WORK) {
+ if ($this->getAmountCommunityWork() - $this->getAmountCommunityWorkSettled() < $amount) {
+ throw new OutOfRangeException();
+ }
+ $this->setAmountCommunityWorkSettled($this->getAmountCommunityWorkSettled() + $amount);
+ } else {
+ throw new OutOfRangeException();
+ }
+
+ return $this;
+ }
}
diff --git a/src/Entity/SentenceSettlement.php b/src/Entity/SentenceSettlement.php
new file mode 100644
index 0000000..5f8742a
--- /dev/null
+++ b/src/Entity/SentenceSettlement.php
@@ -0,0 +1,74 @@
+criminal = $criminal;
+ $this->type = $type;
+ }
+
+ /**
+ * @return Criminal
+ */
+ public function getCriminal(): Criminal
+ {
+ return $this->criminal;
+ }
+
+ /**
+ * @param Criminal $criminal
+ */
+ public function setCriminal(Criminal $criminal): void
+ {
+ $this->criminal = $criminal;
+ }
+
+ /**
+ * @return Criminal
+ */
+ public function getCriminalId(): int
+ {
+ return $this->criminal->getId();
+ }
+
+ /**
+ * @return string
+ */
+ public function getType(): string
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param string $type
+ */
+ public function setType(string $type): void
+ {
+ $this->type = $type;
+ }
+
+ /**
+ * @return null
+ */
+ public function getAmount()
+ {
+ return $this->amount;
+ }
+
+ /**
+ * @param null $amount
+ */
+ public function setAmount($amount): void
+ {
+ $this->amount = $amount;
+ }
+}
diff --git a/src/Form/CriminalType.php b/src/Form/CriminalType.php
index e187441..0dccf5e 100644
--- a/src/Form/CriminalType.php
+++ b/src/Form/CriminalType.php
@@ -20,6 +20,26 @@ class CriminalType extends DocumentType
->add('content', ContentType::class, ['label' => 'form_label_informations' ])
->add('amountMoney', null, ['label' => 'form_label_amount', 'help' => 'form_help_amount'])
->add('amountTime', null, ['label' => 'form_label_time', 'help' => 'form_help_time'])
+ ->add(
+ 'amountCommunityWork',
+ null,
+ ['label' => 'form_label_community_work', 'help' => 'form_help_community_work']
+ )
+ ->add(
+ 'amountMoneySettled',
+ null,
+ ['label' => 'form_label_amount_settled', 'help' => 'form_help_amount_settled']
+ )
+ ->add(
+ 'amountTimeSettled',
+ null,
+ ['label' => 'form_label_time_settled', 'help' => 'form_help_time_settled']
+ )
+ ->add(
+ 'amountCommunityWorkSettled',
+ null,
+ ['label' => 'form_label_community_work_settled', 'help' => 'form_help_community_work_settled']
+ )
;
}
diff --git a/src/Form/SentenceSettlementType.php b/src/Form/SentenceSettlementType.php
new file mode 100644
index 0000000..71a6cda
--- /dev/null
+++ b/src/Form/SentenceSettlementType.php
@@ -0,0 +1,57 @@
+TokenStorage = $TokenStorage;
+ }
+
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $sentence = $builder->getData();
+
+ if ($sentence) {
+ if ($sentence->getType() == "fine") {
+ $amountType = NumberType::class;
+ $amountLabel = 'form_label_paid';
+ } else {
+ $amountType = IntegerType::class;
+ $amountLabel = 'form_label_executed';
+ }
+ } else {
+ $amountType = null;
+ $amountLabel = null;
+ }
+
+ $builder->add('criminal_id', HiddenType::class)
+ ->add('type', HiddenType::class)
+ ->add('amount', $amountType, ['label' => $amountLabel])
+ ->add('submit', SubmitType::class, [
+ 'label' => 'form_button_submit',
+ 'priority' => -900,
+ ])
+ ;
+ }
+
+ public function getBlockPrefix()
+ {
+ return ''; // return an empty string here
+ }
+}
diff --git a/src/Repository/CriminalRepository.php b/src/Repository/CriminalRepository.php
index 4872ffd..726d178 100644
--- a/src/Repository/CriminalRepository.php
+++ b/src/Repository/CriminalRepository.php
@@ -19,4 +19,23 @@ class CriminalRepository extends DocumentRepositoriesExtension
parent::__construct($registry, Criminal::class);
$this->fields = ['amountMoney', 'amountTime', 'content']; //with title, list fields we can search in
}
+
+ public function limitUnsettled(string $type)
+ {
+ if ($type == Criminal::TYPE_FINE) {
+ $column = 'd.amountMoney';
+ } elseif ($type == Criminal::TYPE_JAIL) {
+ $column = 'd.amountTime';
+ } elseif ($type == Criminal::TYPE_COMMUNITY_WORK) {
+ $column = 'd.amountCommunityWork';
+ } else {
+ throw new \OutOfRangeException($type);
+ }
+
+ $settledColumn = $column . 'Settled';
+
+ $this->qb->andWhere("$column <> $settledColumn OR ($column IS NOT NULL AND $settledColumn IS NULL)");
+
+ return $this;
+ }
}
diff --git a/src/Repository/Tools/DocumentRepositoriesExtension.php b/src/Repository/Tools/DocumentRepositoriesExtension.php
index 0721497..1a13a81 100644
--- a/src/Repository/Tools/DocumentRepositoriesExtension.php
+++ b/src/Repository/Tools/DocumentRepositoriesExtension.php
@@ -12,7 +12,7 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
class DocumentRepositoriesExtension extends ServiceEntityRepository
{
public array $fields = [];
- private QueryBuilder $qb;
+ protected QueryBuilder $qb;
private ?QueryBuilder $qbsearch = null;
private ?Group $group = null;
private ?User $user = null;
diff --git a/templates/_cells/documentTable.html.twig b/templates/_cells/documentTable.html.twig
index 22f6ee1..119ce09 100644
--- a/templates/_cells/documentTable.html.twig
+++ b/templates/_cells/documentTable.html.twig
@@ -78,11 +78,21 @@
{% endif %}
{% if i.amountMoney is defined %}
{% trans %}title_amount{% endtrans %}:
- {{ i.amountMoney ? i.amountMoney ~ ' ' ~'currency_symbol'|trans :'value_no_value'|trans }}
+ {{ i.amountMoney ? i.amountMoney ~ ' ' ~'currency_symbol'|trans : 'value_no_value'|trans }}
+ {{ i.amountMoney == i.amountMoneySettled ? '✅' : '❌'}}
+
{% endif %}
{% if i.amountTime is defined %}
{% trans %}title_hours{% endtrans %}:
- {{ i.amountTime ? i.amountTime ~ ' h' :'value_no_value'|trans}}
+ {{ i.amountTime ? i.amountTime ~ 'h' : 'value_no_value'|trans}}
+ {{ i.amountTime == i.amountTimeSettled ? '✅' : '❌'}}
+
+ {% endif %}
+ {% if i.amountCommunityWork is defined %}
+
{% trans %}title_community_work{% endtrans %}:
+ {{ i.amountCommunityWork ? i.amountCommunityWork ~ 'h' : 'value_no_value'|trans}}
+ {{ i.amountCommunityWork == i.amountCommunityWorkSettled ? '✅' : '❌'}}
+
{% endif %}
{% if i.accessorySentence is defined and i.accessorySentence is not null %}
{% trans %}title_accessorySentence{% endtrans %} : {{ 'value_yes'|trans}}
diff --git a/templates/base.html.twig b/templates/base.html.twig
index f706353..7556998 100644
--- a/templates/base.html.twig
+++ b/templates/base.html.twig
@@ -152,7 +152,10 @@
{{ 'title_count'|trans }}: {{ count }}
+ {% if pagination[0].directory is not defined %}{% set nodirectorylink = true %}{% endif %} + {% set slicelimit = (limit is defined)? limit : null %} + {% set counter = 0 %} + + {% if pagination|length > 0 %} +| {% trans %}title_name{% endtrans %} | +{% trans %}title_missing{% endtrans %} | +{% trans %}title_date{% endtrans %} | + {% if noaction is not defined %} +{% trans %}tooltip_view{% endtrans %} | + {% endif %} +
|---|
{% trans %}no_data{% endtrans %}
+ {% endif %} +