src/EventSubscriber/InvoiceSubscriber.php line 130

  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\CheckInformation;
  4. use App\Entity\InvoiceReview;
  5. use App\Entity\InvoiceSupportTicket;
  6. use App\Entity\LatePaymentChargeLogs;
  7. use App\Entity\Municipality;
  8. use App\Entity\MunicipalityFeePeriod;
  9. use App\Entity\MunicipalityLateFees;
  10. use App\Entity\MunicipalityLateFeesPeriod;
  11. use App\Entity\RegistrationForm;
  12. use App\Entity\RenewalForm;
  13. use App\Entity\SupportTicket;
  14. use App\Entity\User;
  15. use App\Event\AppEvents;
  16. use App\Event\FormCreatedEvent;
  17. use App\Event\FormsDeletedEvent;
  18. use App\Event\Support\InvoiceEvent as InvoiceSupportEvent;
  19. use App\Event\InvoiceEvent;
  20. use App\Helper\PropertyHelper;
  21. use App\Repository\LatePaymentChargeLogsRepository;
  22. use App\ValueObject\MunicipalityLateFeesType;
  23. use App\ValueObject\SearchCriteria\MunicipalityFeeSearchCriteria;
  24. use App\ValueObject\InvoicePaymentTypes;
  25. use App\ValueObject\InvoiceStatuses;
  26. use Doctrine\ORM\EntityManagerInterface;
  27. use App\Entity\Form;
  28. use App\Entity\Invoice;
  29. use App\Entity\MunicipalityFee;
  30. use App\ValueObject\InvoiceTypes;
  31. use App\ValueObject\SearchCriteria\RenewalFormSearchCriteria;
  32. use App\Lib\EmailSenderInterface;
  33. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  34. /**
  35. * Class InvoiceListener
  36. */
  37. class InvoiceSubscriber implements EventSubscriberInterface
  38. {
  39. /**
  40. * @var EntityManagerInterface
  41. */
  42. private $em;
  43. /**
  44. * @var EmailSenderInterface
  45. */
  46. private $emailSender;
  47. private LatePaymentChargeLogsRepository $latePaymentChargeLogsRepository;
  48. public function __construct(
  49. EntityManagerInterface $entityManager,
  50. EmailSenderInterface $emailSender,
  51. LatePaymentChargeLogsRepository $latePaymentChargeLogsRepository
  52. )
  53. {
  54. $this->em = $entityManager;
  55. $this->emailSender = $emailSender;
  56. $this->latePaymentChargeLogsRepository = $latePaymentChargeLogsRepository;
  57. }
  58. /**
  59. * {@inheritdoc}
  60. */
  61. public static function getSubscribedEvents(): array
  62. {
  63. return [
  64. AppEvents::FORMS_DELETED => 'onFormsDeleted',
  65. AppEvents::INVOICE_CREATED => 'onInvoiceCreated',
  66. AppEvents::INVOICE_DISPUTE_CREATED => 'onDisputeCreated',
  67. AppEvents::FORM_CREATED => 'onFormCreated'
  68. ];
  69. }
  70. /**
  71. * @param FormsDeletedEvent $event
  72. */
  73. public function onFormsDeleted(FormsDeletedEvent $event): void
  74. {
  75. $formIds = $event->getForms();
  76. if (count($formIds)) {
  77. //Delete Invoices for the forms.
  78. $invoiceIds = $this->em->getRepository(Invoice::class)->deleteInIds($formIds);
  79. if (count($invoiceIds)) {
  80. //Delete Invoices Reviews.
  81. $this->em->getRepository(InvoiceReview::class)->deleteInIds($invoiceIds);
  82. //Delete Invoices Dispute and Support.
  83. $invoiceTicketIds = $this->em->getRepository(InvoiceSupportTicket::class)->getTicketsInIds($invoiceIds);
  84. if (count($invoiceTicketIds)) {
  85. $this->em->getRepository(SupportTicket::class)->deleteInIds($invoiceTicketIds);
  86. }
  87. }
  88. }
  89. }
  90. /**
  91. * @param InvoiceEvent $event
  92. */
  93. public function onInvoiceCreated(InvoiceEvent $event): void
  94. {
  95. $invoice = $event->getInvoice();
  96. /** @var Form $form */
  97. $form = $invoice->getForm();
  98. $form->setFeeAmount($invoice->getInvoiceAmount());
  99. $form->setDueAmount($invoice->getInvoiceAmount());
  100. $this->em->persist($form);
  101. $this->em->flush();
  102. }
  103. /**
  104. * @param InvoiceSupportEvent $event
  105. */
  106. public function onDisputeCreated(InvoiceSupportEvent $event): void
  107. {
  108. //Set Invoice In Dispute.
  109. $invoice = $event->getTicket()->getInvoice();
  110. $invoice->inDispute();
  111. $this->em->persist($invoice);
  112. $this->em->flush();
  113. }
  114. public function onFormCreated(FormCreatedEvent $event): void
  115. {
  116. // try {
  117. // UPDATE property p JOIN ( SELECT f.property_id, COUNT(*) AS totalRenewal FROM `renewal_form` rf INNER JOIN form f ON f.id = rf.id GROUP BY f.property_id ) rc ON p.id = rc.property_id SET p.renewal_number = rc.totalRenewal + 1;
  118. $checkInformation = $event->getCheckInformation();
  119. $usedPayByCheck = $event->getUsedPayByCheck();
  120. $form = $event->getForm();
  121. $property = $form->getProperty();
  122. $municipality = $property->getMunicipality();
  123. $lateFeesTriggerType = '';
  124. if ($event->getType() == InvoiceTypes::VPR_REGISTRATION) {
  125. $zone = $form->getZonesPropertyUse()[0];
  126. } elseif ($event->getType() == InvoiceTypes::VPR_RENEWAL) {
  127. $zone = $form->getProperty()->getZonesPropertyUse()->first();
  128. }
  129. $criteria = new MunicipalityFeeSearchCriteria();
  130. $criteria->industrialType = strtolower($zone ? $zone->getName() : '');
  131. $criteria->municipalityId = $municipality->getId();
  132. $municipalityFee = null;
  133. $municipalityFees = $this->em->getRepository(MunicipalityFee::class)->search($criteria);
  134. $municipalityFee = $municipalityFees[0];
  135. $amount = 0;
  136. $invoiceDate = new \DateTime('now');
  137. $dueDate = new \DateTime('now');
  138. $description = '';
  139. $nextRenewalNumber = $property->getRenewalNumber();
  140. if ($event->getType() == InvoiceTypes::VPR_REGISTRATION) {
  141. $dueDate = new \DateTime($property->getRegistrationDate() ? $property->getRegistrationDate()->format('Y-m-d H:i:s') : 'now'); // Y-m-d
  142. $amount = $municipalityFee->getRegistrationFee();
  143. $description = 'Registration Invoice for '.$property->getAddress().' registered on '.$invoiceDate->format('Y-m-d H:i:s');
  144. } elseif ($event->getType() == InvoiceTypes::VPR_RENEWAL) {
  145. // count past renewals
  146. $criteria = new RenewalFormSearchCriteria();
  147. $criteria->property = $property;
  148. $countRenewals = $this->em->getRepository(RenewalForm::class)->countByCriteria($criteria);
  149. if (count($municipalityFee->getPeriods()) && $countRenewals > 1) {
  150. // count total periods including base charge for renewal
  151. $feesIndex = $countRenewals - 1;
  152. $nextRenewalNumber = $countRenewals + 1;
  153. /** @var MunicipalityFee $municipalityFee*/
  154. $feesArray = [$municipalityFee->getRenewalBaseFee()];
  155. if (count($municipalityFee->getPeriods())) {
  156. foreach ($municipalityFee->getPeriods() as $period) {
  157. $feesArray[] = $period->getTotalFee();
  158. }
  159. }
  160. $type = '';
  161. switch ($municipalityFee->getPeriodFixedRecurrenceType()) {
  162. case 'year':
  163. $type = 'Y';
  164. break;
  165. case 'month':
  166. $type = 'M';
  167. break;
  168. case 'day':
  169. $type = 'D';
  170. break;
  171. }
  172. $invoiceDate = new \DateTime();
  173. $dueDate = new \DateTime();
  174. if ($type == 'Y') {
  175. $dueDate->modify('+'.PropertyHelper::DUE_YEAR_RENEW.' day');
  176. }
  177. else if ($type == 'M') {
  178. $dueDate->modify('+'.PropertyHelper::DUE_MONTH_RENEW.' day');
  179. }
  180. $renewalDate = $property->getRenewalDate() ? $property->getRenewalDate()->format('Y-m-d H:i:s') : (new \DateTime())->format('Y-m-d H:i:s');
  181. $description = 'Renewal Invoice for '.$property->getAddress().' registered on '.$renewalDate;
  182. if (array_key_exists($feesIndex, $feesArray)) {
  183. $amount = $feesArray[$feesIndex];
  184. } else {
  185. $amount = end($feesArray);
  186. }
  187. } else {
  188. $dueDate = new \DateTime($property->getRegistrationDate() ? $property->getRegistrationDate()->format('Y-m-d H:i:s') : 'now'); // Y-m-d
  189. $description = 'Renewal Invoice for '.$property->getAddress().' registered on '.$invoiceDate->format('Y-m-d H:i:s');
  190. $amount = $municipalityFee->getRenewalBaseFee();
  191. $nextRenewalNumber = $property->getRenewalNumber() + 1;
  192. }
  193. $municipalityLateFees = $this->em->getRepository(MunicipalityLateFees::class)->findOneBy(
  194. ['municipality' => $municipality->getId(), 'type' => MunicipalityLateFeesType::RENEWAL_TYPE]
  195. );
  196. $currentUser = $this->em->getRepository(User::class)->findOneBy(['email' => $form->getCreatedBy()]);
  197. if ($municipalityLateFees instanceof MunicipalityLateFees) {
  198. $lateFeesTriggerType = $municipalityLateFees->getFeesTriggerType();
  199. $lateFeesTriggerAfter = $municipalityLateFees->getFeesTriggerAfter();
  200. $nextRenewalDate = $property->getNextRenewalDate();
  201. $currentDate = new \DateTime();
  202. $dateDiff = $currentDate->diff($nextRenewalDate);
  203. $charge = '';
  204. $usersLatePaymentChargeLogsCount = count($this->latePaymentChargeLogsRepository->findBy(['user' => $currentUser, 'municipality' => $municipality]));
  205. $lateFeeBaseCharge = $municipalityLateFees->getFeesAmount();
  206. $lateChargesArray = [];
  207. $periods = $municipalityLateFees->getPeriods()->getValues();
  208. if (!empty($periods)) {
  209. /**@var MunicipalityLateFeesPeriod $period */
  210. foreach ($periods as $period) {
  211. $municipalityLateFeesId = $period->getMunicipalityLateFees()->getId();
  212. $lateChargesArray[(int) $municipalityLateFeesId][] = (float) $period->getTotalFee();
  213. }
  214. if (array_key_exists($municipalityLateFees->getId(), $lateChargesArray)) {
  215. array_unshift($lateChargesArray[$municipalityLateFees->getId()], $municipalityLateFees->getFeesAmount());
  216. }
  217. if ($usersLatePaymentChargeLogsCount == 0) {
  218. $charge = (float) $municipalityLateFees->getFeesAmount();
  219. } elseif (array_key_exists($municipalityLateFees->getId(), $lateChargesArray) && array_key_exists($usersLatePaymentChargeLogsCount, $lateChargesArray[$municipalityLateFees->getId()])) {
  220. $charge = $lateChargesArray[$municipalityLateFees->getId()][$usersLatePaymentChargeLogsCount];
  221. } else {
  222. $charge = end($lateChargesArray[$municipalityLateFees->getId()]);
  223. }
  224. }
  225. }
  226. }
  227. $property->setRenewalNumber($nextRenewalNumber);
  228. $this->em->persist($property);
  229. $this->em->flush();
  230. $totalAmount = $dueAmount = $amount;
  231. $invoice = new Invoice(
  232. $form->getRegistrant(),
  233. $event->getType(),
  234. $invoiceDate,
  235. $dueDate,
  236. $amount,
  237. );
  238. $invoice->setPaymentType(InvoicePaymentTypes::CREDIT_CARD);
  239. $invoice->setDescription($description);
  240. $invoice->setForm($form);
  241. if ($checkInformation instanceof CheckInformation) {
  242. $invoice->setCheckInformation($checkInformation);
  243. $checkAmount = $checkInformation->getAmount();
  244. if ($checkAmount >= $totalAmount) {
  245. $invoiceStatus = InvoiceStatuses::PAID;
  246. $dueAmount = 0;
  247. } else {
  248. $invoiceStatus = InvoiceStatuses::UNPAID;
  249. $dueAmount = $totalAmount - $checkAmount;
  250. }
  251. $invoice->setStatus($invoiceStatus);
  252. $invoice->setPaymentDate(new \DateTime());
  253. $invoice->setPaymentType(InvoicePaymentTypes::CHECK);
  254. $form->setPaidAmount($checkAmount);
  255. }
  256. if ($usedPayByCheck) {
  257. $invoice->setPaymentType(InvoicePaymentTypes::CHECK);
  258. }
  259. $this->em->persist($invoice);
  260. $this->em->flush();
  261. if ($lateFeesTriggerType == 'day') {
  262. $daysDiff = $dateDiff->days;
  263. if ($daysDiff >= $lateFeesTriggerAfter) {
  264. $this->generateLatePaymentLog($currentUser, $municipality, $invoice, $charge);
  265. }
  266. } else if ($lateFeesTriggerType == 'month') {
  267. $monthsDiff = $dateDiff->m;
  268. if ($monthsDiff >= $lateFeesTriggerAfter) {
  269. $this->generateLatePaymentLog($currentUser, $municipality, $invoice, $charge);
  270. }
  271. }
  272. if ($form instanceof RegistrationForm || $form instanceof RenewalForm) {
  273. $form->setFeeAmount($totalAmount);
  274. $form->setDueAmount($dueAmount);
  275. $this->em->persist($form);
  276. }
  277. $this->em->flush();
  278. }
  279. public function generateLatePaymentLog(User $user,Municipality $municipality,Invoice $invoice, $charge): void
  280. {
  281. $latePaymentChargeLog = $this->latePaymentChargeLogsRepository->findOneBy(['invoice' => $invoice]);
  282. if (!$latePaymentChargeLog instanceof LatePaymentChargeLogs) {
  283. $latePaymentChargeLog = new LatePaymentChargeLogs();
  284. $latePaymentChargeLog->setUser($user);
  285. $latePaymentChargeLog->setMunicipality($municipality);
  286. $latePaymentChargeLog->setInvoice($invoice);
  287. $latePaymentChargeLog->setMunicipalityLateFeesCharge($charge);
  288. $this->em->persist($latePaymentChargeLog);
  289. $this->em->flush();
  290. }
  291. }
  292. }