<?php
namespace App\Security\Voters;
use App\Entity\PriceInquiry;
use App\Entity\CustomerQuotations;
use App\Entity\User;
use App\Service\Api\CountriesService;
use App\Service\Constants\Defaults;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class PriceInquiryVoter extends Voter
{
private Security $security;
private CountriesService $countriesService;
public const CAN_EDIT = 'inquiry.can_edit';
public const CAN_FILL_INQUIRY = 'inquiry.can.fill';
public const CAN_SEE_PRICES = 'inquiry.can.see_prices';
public const CAN_UPDATE = 'inquiry.can_update';
public const CAN_SEND_NOTIFICATION = 'inquiry.can.send_notification';
public const CAN_BE_SHOWN_IN_PROPOSAL = 'inquiry.can.be_shown_in_proposal';
public const CAN_BE_REJECTED = 'inquiry.can.be_rejected';
public const CAN_BE_DUPLICATED = 'inquiry.can.be_duplicated';
public const CAN_CHANGE_COMMISSION = 'inquiry.commission.can_change';
public const CAN_VERIFY_MFM = 'inquiry.can.verify';
public const CAN_VERIFY_SM = 'inquiry.can.verify.sm';
public const CAN_UPDATE_CUSTOMER_PRICES = 'inquiry.can.update.customer.prices';
public const CAN_UPDATE_MF_PRICES = 'inquiry.can.update.mf.prices';
public const CAN_OPEN_PRICES_FORM = 'inquiry.can.open.prices.form';
public const CAN_REMOVE_MFM_VERIFICATION = 'inquiry.can.remove_mfm_verification';
public const CAN_REMOVE_SM_VERIFICATION = 'inquiry.can.remove_sm_verification';
public const CAN_UPDATE_CUSTOMS_PRICES = 'inquiry.can.update.customs.prices';
private const ATTRIBUTES = [
self::CAN_EDIT,
self::CAN_FILL_INQUIRY,
self::CAN_SEE_PRICES,
self::CAN_UPDATE,
self::CAN_SEND_NOTIFICATION,
self::CAN_BE_SHOWN_IN_PROPOSAL,
self::CAN_BE_REJECTED,
self::CAN_BE_DUPLICATED,
self::CAN_CHANGE_COMMISSION,
self::CAN_VERIFY_MFM,
self::CAN_VERIFY_SM,
self::CAN_UPDATE_CUSTOMER_PRICES,
self::CAN_UPDATE_MF_PRICES,
self::CAN_OPEN_PRICES_FORM,
self::CAN_REMOVE_MFM_VERIFICATION,
self::CAN_REMOVE_SM_VERIFICATION,
self::CAN_UPDATE_CUSTOMS_PRICES,
];
public function __construct(
Security $security,
CountriesService $countriesService
)
{
$this->security = $security;
$this->countriesService = $countriesService;
}
protected function supports($attribute, $subject): bool
{
return in_array($attribute, self::ATTRIBUTES);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
switch ($attribute) {
case self::CAN_EDIT:
return $this->canEdit($subject);
case self::CAN_FILL_INQUIRY:
return $this->canBeFilled($subject);
case self::CAN_SEE_PRICES:
return $this->canSeePrices($subject, $user);
case self::CAN_UPDATE:
return $this->canUpdate($subject, $user);
case self::CAN_SEND_NOTIFICATION:
return $this->canSendNotification($subject);
case self::CAN_BE_SHOWN_IN_PROPOSAL:
return $this->canBeShownInProposal($subject);
case self::CAN_BE_REJECTED:
return $this->canBeRejected($subject);
case self::CAN_BE_DUPLICATED:
return $this->canBeDuplicated($subject);
case self::CAN_CHANGE_COMMISSION:
return $this->canChangeCommission($subject);
case self::CAN_VERIFY_MFM:
return $this->canVerifyMFM($subject);
case self::CAN_VERIFY_SM:
return $this->canVerifySM($subject);
case self::CAN_UPDATE_CUSTOMER_PRICES:
return $this->canUpdateCustomerPrices($subject);
case self::CAN_UPDATE_CUSTOMS_PRICES:
return $this->canUpdateCustomsPrices($subject);
case self::CAN_UPDATE_MF_PRICES:
return $this->canUpdateManufacturerPrices($subject);
case self::CAN_OPEN_PRICES_FORM:
return $this->canOpenPricesForm($subject);
case self::CAN_REMOVE_MFM_VERIFICATION:
return $this->canRemoveMfmVerification($subject);
case self::CAN_REMOVE_SM_VERIFICATION:
return $this->canRemoveSmVerification($subject);
}
throw new \LogicException('Invalid attribute: '.$attribute);
}
private function canEdit(PriceInquiry $inquiry): bool
{
if ( !$this->security->isGranted('ROLE_CAN_CREATE_INQUIRIES') ) {
return false;
}
// temporary disabled. 27.01.21 / Ivars
/*
if ( $inquiry->getOfferVerifiedSM() ) {
return false;
}
*/
return true;
}
private function canUpdate(PriceInquiry $inquiry): bool
{
if (in_array($inquiry->getQuotation()->getStatus(), [CustomerQuotations::STATUS_REJECTED])) {
return false;
}
if ( $this->security->isGranted('ROLE_INQUIRY_UPDATE') ) {
return true;
}
return false;
}
private function canBeFilled(PriceInquiry $inquiry): bool
{
if ( in_array($inquiry->getStatus(),[PriceInquiry::STATUS_DRAFT,PriceInquiry::STATUS_SENT,PriceInquiry::STATUS_OPEN]) ) {
return true;
}
return false;
}
private function canBeRejected(PriceInquiry $inquiry): bool
{
if ($inquiry->getStatus() == PriceInquiry::STATUS_OPEN) {
return true;
}
if ($inquiry->getStatus() == PriceInquiry::STATUS_OFFER && $this->canUpdate($inquiry)) {
return true;
}
return false;
}
private function canSeePrices(PriceInquiry $inquiry, $user): bool
{
if (!$user instanceof User) {
// the user must be logged in; if not, deny access
return false;
}
return true;
}
private function canSendNotification(PriceInquiry $inquiry): bool
{
if ( !$this->security->isGranted('ROLE_MANUFACTURING_MANAGER') ) {
return false;
}
if ( !in_array($inquiry->getStatus(), [PriceInquiry::STATUS_OFFER]) ) {
return false;
}
if ( !in_array($inquiry->getQuotation()->getStatus(), [CustomerQuotations::STATUS_INQUIRIES_SENT, CustomerQuotations::STATUS_OFFERS_RECEIVED, CustomerQuotations::STATUS_OFFERS_PARTIALLY_RECEIVED]) ) {
return false;
}
return true;
}
private function canBeShownInProposal(PriceInquiry $inquiry): bool
{
if ($inquiry->getHideInProposal()) {
return false;
}
if ($inquiry->getOfferVerified() === false) {
return false;
}
if (!$this->security->isGranted('ROLE_SALES_MANAGER') && !$inquiry->getOfferVerifiedSM()) {
return false;
}
//if delivery prices are greater then 0
if ($inquiry->getIsDeliveryPrices()) {
return true;
}
return false;
}
private function canBeDuplicated(PriceInquiry $inquiry): bool
{
if( !in_array($inquiry->getQuotation()->getStatus(), [CustomerQuotations::STATUS_INQUIRIES_SENT, CustomerQuotations::STATUS_OFFERS_RECEIVED, CustomerQuotations::STATUS_OFFERS_PARTIALLY_RECEIVED, CustomerQuotations::STATUS_PROPOSAL_SENT]) ) {
return false;
}
if ($inquiry->getStatus() === PriceInquiry::STATUS_OFFER) {
return true;
}
return false;
}
private function canChangeCommission(PriceInquiry $inquiry): bool
{
if ( !$this->security->isGranted('ROLE_CAN_CHANGE_OFFER_COMMISSION') ) {
return false;
}
$quotation = $inquiry->getQuotation();
if ( !$this->security->isGranted('quotation.commission.can_change', $quotation) ) {
return false;
}
return true;
}
private function canVerifyMFM(PriceInquiry $inquiry): bool
{
if ( !$this->security->isGranted('ROLE_MANUFACTURING_MANAGER') ) {
return false;
}
if ( $inquiry->getOfferVerified() ) {
return false;
}
if ( !in_array($inquiry->getStatus(), [PriceInquiry::STATUS_OFFER, PriceInquiry::STATUS_ACCEPTED]) ) {
return false;
}
if ( !$inquiry->getCommission() ) {
return false;
}
if ( !$inquiry->getIsDeliveryPrices() ) {
return false;
}
return true;
}
private function canVerifySM(PriceInquiry $inquiry): bool
{
if ( !$this->security->isGranted('ROLE_SALES_MANAGER') ) {
return false;
}
if ( !$inquiry->getOfferVerified() ) {
return false;
}
if ( $inquiry->getOfferVerifiedSM() ) {
return false;
}
if ( !in_array($inquiry->getStatus(), [PriceInquiry::STATUS_OFFER, PriceInquiry::STATUS_ACCEPTED]) ) {
return false;
}
return true;
}
private function canUpdateCustomerPrices(PriceInquiry $inquiry) : bool
{
if ( !$inquiry->getCustomerPriceOffer() ) {
return false;
}
if ( $inquiry->getOfferVerifiedSM() ) {
return false;
}
if ( $this->security->isGranted('ROLE_SALES_MANAGER') || $this->security->isGranted('ROLE_SUPER_PRICE_EDITOR')) {
return true;
}
return false;
}
private function canUpdateManufacturerPrices(PriceInquiry $inquiry) : bool
{
if ( !in_array($inquiry->getStatus(), [PriceInquiry::STATUS_OFFER, PriceInquiry::STATUS_ACCEPTED]) ) {
return false;
}
if ( $inquiry->getOfferVerified() ) {
return false;
}
if ( $this->security->isGranted('ROLE_MANUFACTURING_MANAGER') || $this->security->isGranted('ROLE_SUPER_PRICE_EDITOR')) {
return true;
}
return false;
}
private function canOpenPricesForm(PriceInquiry $inquiry) : bool
{
if ( in_array($inquiry->getStatus(), [PriceInquiry::STATUS_DRAFT]) ) {
return false;
}
// commenting this out allowing open price form for fully accepted offers, so managers can see comission. 29.01.22 / Ivars
/*
if ( $this->canUpdateCustomerPrices($inquiry) || $this->canUpdateManufacturerPrices($inquiry) ) {
return true;
}
*/
return true;
}
private function canRemoveMfmVerification(PriceInquiry $inquiry) : bool
{
// MFM verification cant be removed if there are active SM verification
if ( $inquiry->getOfferVerifiedSM() ) {
return false;
}
// if its already an order - cant update
if ( $inquiry->getOrderQuotation() ) {
return false;
}
if ( !$this->security->isGranted('ROLE_INQUIRY_CAN_REMOVE_MFM_VERIFY') ) {
return false;
}
return true;
}
private function canRemoveSmVerification(PriceInquiry $inquiry) : bool
{
// can be removed only if its verified before
if ( !$inquiry->getOfferVerifiedSM() ) {
return false;
}
// if its already an order - cant update
if ( $inquiry->getOrderQuotation() ) {
return false;
}
if ( !$this->security->isGranted('ROLE_INQUIRY_CAN_REMOVE_SM_VERIFY') ) {
return false;
}
return true;
}
private function canUpdateCustomsPrices(PriceInquiry $inquiry): bool
{
if ( !$inquiry->getCustomerPriceOffer() || !$inquiry->getCustomerDeliveryPrices() ) {
return false;
}
$pickupAddressDetails = $inquiry->getManufacturerAddress();
$deliveryAddress = $inquiry->getQuotation()->getDeliveryAddress();
if (
$this->countriesService->isInsideEu($pickupAddressDetails['country'] ?? Defaults::DEFAULT_COUNTRY_CODE) &&
$this->countriesService->isInsideEu($deliveryAddress['country'] ?? Defaults::DEFAULT_COUNTRY_CODE)
) {
return false;
}
return true;
}
}