<?php
// src/App/EventSubscriber/BlogPostReviewSubscriber.php
namespace App\EventSubscriber;
use App\Entity\CustomerQuotations;
use App\Entity\PriceInquiry;
use App\Service\Constants\LogEvents;
use App\Service\Log\QuotationLogService;
use Doctrine\Common\Util\ClassUtils;
use App\Repository\SubscriptionRepository;
use App\Service\RabbitMQ\RabbitMQDispatcher;
use App\Service\Subscription\SubscriptionService;
use App\Service\UserLog;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\Event;
use App\Service\PriceInquiry\PriceInquiryService;
use Symfony\Component\Workflow\Registry;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
class PriceInquiryWorkflowSubscriber implements EventSubscriberInterface
{
private $security;
private $inquiryService;
private $em;
private $workflows;
private $rabbitMQDispatcher;
private $userLog;
private $subscriptionRepo;
private $subscriptionService;
private $logService;
public function __construct(
Security $security,
PriceInquiryService $inquiryService,
EntityManagerInterface $em,
Registry $workflows,
RabbitMQDispatcher $rabbitMQDispatcher,
UserLog $userLog,
QuotationLogService $logService,
SubscriptionRepository $subscriptionRepo,
SubscriptionService $subscriptionService
)
{
$this->security = $security;
$this->inquiryService = $inquiryService;
$this->userLog = $userLog;
$this->em = $em;
$this->workflows = $workflows;
$this->rabbitMQDispatcher = $rabbitMQDispatcher;
$this->subscriptionService = $subscriptionService;
$this->subscriptionRepo = $subscriptionRepo;
$this->logService = $logService;
}
public static function getSubscribedEvents()
{
return [
'workflow.price_inquiry_status.guard.to_accepted' => ['canBeAccepted'],
'workflow.price_inquiry_status.completed.to_open' => [
['createSubscriptions']
],
// 'workflow.price_inquiry_status.completed.to_rejected' => [
// ['removeSubscriptions']
// ],
'workflow.price_inquiry_status.completed.to_offer' => [
['setDeliveryPrices', 50],
['setCustomsPricesAmounts', 40],
['setDeliveryTime', 30],
['setIsTransit', 20],
['updateQuotationStatus', 10],
],
'workflow.price_inquiry_status.completed.to_accepted' => [
['setOrderPrice'],
['setOrderDeliveryPrice'],
['setQuotationAccepted'],
],
'workflow.price_inquiry_status.announce' => [
['addQuotationLastUpdateTime'],
['logTransition'],
['sendNotification']
],
];
}
public function setOrderPrice(Event $event) {
$inquiry = $event->getSubject();
$inquiry->setOrderPrice($inquiry->getCustomerPriceOffer()[$inquiry->getOrderQuantity()]??null);
}
public function setOrderDeliveryPrice(Event $event) {
$inquiry = $event->getSubject();
$inquiry->setCustomerDeliveryPrice($inquiry->getCustomerDeliveryPrices()[$inquiry->getOrderQuantity()]??0);
}
public function setQuotationAccepted(Event $event) {
$inquiry = $event->getSubject();
$quotation = $inquiry->getQuotation();
if ( !$quotation->getIsOrder() ) {
$workflowQuotation = $this->workflows->get($quotation);
$workflowQuotation->apply($quotation, 'to_ordered');
}
$quotation->setIsOrder(true);
$quotation->setOrderInquiry($inquiry);
// decline all other inquiries
// check if there are more than one - so there is something to decline
if ( count($quotation->getPriceInquiries()) > 1 ) {
foreach ( $quotation->getPriceInquiries() as $priceInquiry ) {
// ignore the one which was chosen now
if ( $priceInquiry === $inquiry ) {
continue;
}
$workflowPriceInqyiry = $this->workflows->get($priceInquiry);
if ( $workflowPriceInqyiry->can($priceInquiry, 'to_declined') ) {
$workflowPriceInqyiry->apply($priceInquiry, 'to_declined');
}
}
}
}
public function createSubscriptions(Event $event)
{
$this->subscriptionService->generateSubscriptions($event->getSubject(), $event->getSubject()->getUserCreated());
}
public function canBeAccepted(Event $event)
{
$inquiry = $event->getSubject();
if ( $inquiry->getStatus() != PriceInquiry::STATUS_OFFER ) {
$event->setBlocked(true);
}
if ( $this->security->isGranted('user.is_manufacturer') ) {
$event->setBlocked(true);
}
$statuses = [
CustomerQuotations::STATUS_PROPOSAL_SENT,
CustomerQuotations::STATUS_HOLD,
];
if ( !in_array($inquiry->getQuotation()->getStatus(),$statuses) ) {
$event->setBlocked(true);
}
if ( $this->security->getUser() && $this->security->isGranted('user.is_app_customer', $this->security->getUser()) ) {
return true;
}
if ( !$this->security->isGranted('ROLE_SALES_MANAGER') ) {
$event->setBlocked(true);
}
if ( $inquiry->getQuotation()->getManager() != $this->security->getUser() ) {
$event->setBlocked(true);
}
return true;
}
public function addQuotationLastUpdateTime(Event $event)
{
$quotation = $event->getSubject()->getQuotation();
$quotation->setLastUpdate(new \DateTime());
$this->em->persist($quotation);
$this->em->flush();
}
public function setDeliveryPrices(Event $event)
{
$this->rabbitMQDispatcher->dispatch([
'data' => [
'inquiry_id' => $event->getSubject()->getId(),
'inquiry_uuid' => $event->getSubject()->getUuid()
],
'action_name' => 'cargoSonPriceUpdate',
'consumer_name' => 'price_inquiry_consumer'
]);
}
public function setIsTransit(Event $event)
{
$this->inquiryService->setDefaultTransit($event->getSubject());
if ($event->getSubject()->getIsTransit()) {
$this->logService->logAction(
$event->getSubject()->getQuotation(),
'log.'.LogEvents::INQUIRY_UPDATED_IS_TRANSIT,
$event->getSubject()->getInquiryNumber()
);
}
}
public function setCustomsPricesAmounts(Event $event)
{
$this->inquiryService->updateCustomsPricesAmounts($event->getSubject());
}
public function setDeliveryTime(Event $event)
{
$this->inquiryService->updateDeliveryTime($event->getSubject());
}
public function sendNotification(Event $event)
{
if ( in_array($event->getSubject()->getQuotation()->getStatus(),
[CustomerQuotations::STATUS_REJECTED, CustomerQuotations::STATUS_DELETED]) ) {
return;
}
$response = $this->subscriptionService->proceedEvent(
'inquiry.transition.' . $event->getTransition()->getName(),
$event->getSubject(),
[
'data' => [
'uuid' => $event->getSubject()->getUuid(),
'user_id' => $this->security->getUser()? $this->security->getUser()->getId():null,
'transition' => $event->getTransition()->getName()
],
'action_name' => 'inquiryStatusChangeNotify',
]
);
if ($response['notifies_count']) {
$this->userLog->log(
'notification',
'inquiry.to_offer.notifications.created',
$event->getSubject()->getId(),
'New notifications created. Notifications count: '.$response['notifies_count']. ', inquiry uuid: ' . $event->getSubject()->getUuid() . ', users: ' . $response['users']
);
}
$this->inquiryService->updateQuotationStatus($event->getSubject()->getQuotation());
}
public function updateQuotationStatus(Event $event)
{
if ( $event->getTransition()->getName() == 'to_offer' ) {
$quotation = $event->getSubject()->getQuotation();
$workflowQuotation = $this->workflows->get($quotation);
if ( $workflowQuotation->can($quotation,'to_offers_partially_received') ) {
$workflowQuotation->apply($quotation, 'to_offers_partially_received');
$this->em->persist($quotation);
$this->em->flush();
}
}
else if ( $event->getTransition()->getName() == 'to_accepted' ) {
//TODO
}
}
public function logTransition(Event $event)
{
$this->userLog->log(
'inquiry',
'status.update.'.$event->getTransition()->getName(),
$event->getSubject()->getId(),
'Inquiry status update: '.$event->getTransition()->getName(). ' ' . $event->getSubject()->getUuid()
);
}
public function removeSubscriptions(Event $event)
{
if ($subscriptions = $this->subscriptionRepo->getAll([
ClassUtils::getClass($event->getSubject()) => $event->getSubject()
])) {
$this->subscriptionService->removeSubs($subscriptions);
}
}
}