<?php
namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\FikenApiToken;
use App\Entity\Invoice;
use App\Entity\User;
use App\Fiken\Api\ApiEndpoint;
use App\Fiken\Api\Client;
use App\Fiken\Api\Collection\CompanyCollection;
use App\Fiken\Api\Entity\InvoiceDraft;
use App\Fiken\Api\FikenEnv;
use App\Fiken\Api\Token;
use App\Repository\FikenApiTokenRepository;
use Doctrine\ORM\EntityManagerInterface;
use Ramsey\Uuid\Uuid;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
final class InvoiceSubscriber implements EventSubscriberInterface {
public function __construct(
private EntityManagerInterface $entityManagerInterface,
private Security $security,
private MailerInterface $mailerInterface
) {}
public static function getSubscribedEvents() {
return [
KernelEvents::VIEW => [
'makeInvoiceDraft', EventPriorities::POST_WRITE
],
];
}
public function makeInvoiceDraft(ViewEvent $event) {
$instance = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$instance instanceof Invoice || Request::METHOD_POST !== $method)
return;
$invoice = (fn(Invoice $i): Invoice => $i)($instance);
$repo = $this->entityManagerInterface->getRepository(FikenApiToken::class);
$user = $this->entityManagerInterface->getRepository(User::class)->findOneBy(['email' => 'post@giaever-vertskap.no']);
$sender = (fn(UserInterface $u): User => $u)($this->security->getUser());
try {
$token = (
fn(FikenApiTokenRepository $repo): FikenApiToken => $repo->getLeastFrequentlyUsed($user)
)($repo);
if ($token == null)
throw new \Exception("Missing Fiken Token for user: " . $user->getEmail());
$env = FikenEnv::PROD;
$slug = $env == FikenEnv::DEBUG ? 'fiken-demo-garn-og-glod-as3' : 'giaever-vertskap-as';
$client = new ApiEndpoint(new Client(
$token->getToken(),
function (Token $t) use ($token): void {
$this->entityManagerInterface->persist($token->setToken($t));
$this->entityManagerInterface->flush();
},
$env
));
$companies = (fn(ApiEndpoint $c): CompanyCollection =>
$c->getCompanies()->load()
)($client);
$company = $companies->getOneBy(['slug' => $slug]);
$invoices = $company->getInvoices();
$now = new \DateTimeImmutable();
$issueDate = new \DateTimeImmutable($invoice->getMonth()->format('Y-m-t'));
$issueMax = 16;
if ($issueDate > $now)
$issueDate = $now;
else if ($issueDate->add(new \DateInterval(sprintf('P%dD', $issueMax))) < $now)
$issueDate = $now;
// dd($invoice->getMappedInvoiceEntries($client->getClient()->getEnv()));
$invoices->addEntry(InvoiceDraft::createFromJson(
$invoices, [
'uuid' => $uuid = Uuid::uuid4(),
'type' => 'invoice',
'issueDate' => $issueDate->format('Y-m-d'),
'daysUntilDueDate' => ($invoice->getProperty()->getOwner()->getDaysUntilDue() ?? $issueMax) + $issueDate->diff($now)->days,
'customerId' => $invoice->getProperty()->getOwner()->getCustomerId($client->getClient()->getEnv()),
'projectId' => $invoice->getProperty()->getProjectId($client->getClient()->getEnv()),
'invoiceText' => sprintf(
"Hei, {kundenavn}, her kommer faktura for prosjektet «%s».\n\nVennligst se fakturaspesifikasjon. Skulle noe være uklart er det bare ta kontakt.",
$invoice->getProperty()->getSection()
),
'lines' => $invoice->getMappedInvoiceEntries($client->getClient()->getEnv())
]
));
$invoice->setExternalUuid($uuid);
$this->entityManagerInterface->persist($invoice);
$this->entityManagerInterface->flush();
return $this->mailerInterface->send(
(new TemplatedEmail())
->to(...array_unique([$user->getEmail(), $sender->getEmail()]))
->from('post@giaever-vertskap.no')
->subject('New invoice-draft sendt to Fiken')
->addCc($sender->getEmail())
->htmlTemplate('emails/invoice.summary.html.twig')
->context([
'sender' => $sender,
'invoice' => $invoice,
'lines' => $invoice->getMappedInvoiceEntries($client->getClient()->getEnv())
])
);
} catch (\Exception $e) {
return $this->mailerInterface->send(
(new TemplatedEmail())
->to(...array_unique([$user->getEmail(), $sender->getEmail()]))
->from('post@giaever-vertskap.no')
->subject('Failed sending in the invoice')
->htmlTemplate('emails/exception.html.twig')
->context([
'exception' => $e,
'invoice' => $invoice,
])
);
}
// $changes = json_decode($event->getRequest()->getContent(), true);
// if (isset($changes['guests'])) {
// $prev = $booking->getPreviousBooking();
// if (!$prev || $prev->getCheckout()->diff(new \DateTime())->days > 2)
// return;
// $recepients = [ !$prev->isClean() && $prev->getResponsible() ? $prev->getResponsible()->getEmail() : 'post@giaever-vertskap.no' ];
// if ($prev->getResponsible() !== null && !$prev->isClean())
// $recepients = array_merge($recepients, array_map(function (User $u): string {
// return $u->getEmail();
// }, array_filter($this->em->getRepository(User::class)->findBy(['company' => $prev->getResponsible()->getCompany()]), function (User $u): bool {
// return in_array('ROLE_MANAGER', $u->getRoles());
// })));
// $recepients = array_unique($recepients);
// return $this->mailer->send(
// (new TemplatedEmail())
// ->to(...$recepients)
// ->from('post@giaever-vertskap.no')
// ->subject(sprintf("Amount of guests updated by %s", $this->security->getUser()->getName()))
// ->htmlTemplate('emails/booking.guests.alert.html.twig')
// ->context([
// "user" => $this->security->getUser(),
// "previous" => $prev,
// "upcoming" => $booking,
// ])
// );
// } else if (isset($changes['clean'])) {
// $email = (new TemplatedEmail())
// ->to('post@giaever-vertskap.no')
// ->from('post@giaever-vertskap.no')
// ->replyTo($this->security->getUser()->getEmail())
// ->subject(sprintf("Clean alert: %s (%s)",
// $booking->getProperty()->getAddress()['address'],
// $booking->getProperty()->getSection()
// ))
// ->htmlTemplate('emails/property.clean.alert.html.twig')
// ->context([
// "booking" => $booking,
// "request" => var_export($changes, true)
// ]);
// return $this->mailer->send($email);
// } else if (isset($changes['drivingTimeUsage']) || isset($changes['timeUsage'])) {
// $email = (new TemplatedEmail())
// ->to('post@giaever-vertskap.no')
// ->from('post@giaever-vertskap.no')
// ->replyTo($this->security->getUser()->getEmail())
// ->subject(sprintf('%s time usage updated', isset($changes['drivingTimeUsage']) ? 'Driving' : 'Cleaning'))
// ->htmlTemplate('emails/property.clean.time-usage.alert.html.twig')
// ->context([
// "booking" => $booking,
// "type" => isset($changes['drivingTimeUsage']) ? 'driving' : 'cleaning'
// ]);
// }
}
}