<?php
namespace App\Security\Voters;
use App\Entity\CustomerQuotations;
use App\Entity\Invoice;
use App\Service\Constants\InvoiceStatus;
use App\Service\Constants\InvoiceType;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class InvoiceVoter extends Voter
{
private Security $security;
public const CAN_ADD_PAYMENT = 'invoice.can_add_payment';
public const CAN_CREATE_SALES = 'invoice.can_create_sales';
public const CAN_UPDATE_INVOICE_JSON_DATA = 'invoice.can_update_json_data';
public const CAN_BE_DELETED = 'invoice.can_be_deleted';
public const CAN_BE_EDITED = 'invoice.can_be_edited';
public const CAN_BE_CANCELED = 'invoice.can_be_canceled';
public const CAN_BE_COPIED = 'invoice.can_be_copied';
public const CAN_SEND_TO_CUSTOMER = 'invoice.can_be_sent_to_customer';
public const VISIBLE_IN_CUSTOMER_PROF = 'invoice.visible_in_customer_prof';
public const CAN_BE_UPDATED = 'invoice.can_be_updated';
public const CAN_ROWS_BE_DELETED = 'invoice.rows_can_be_deleted';
public const HAS_PDF = 'invoice.has_pdf';
private const ATTRIBUTES = [
self::CAN_ADD_PAYMENT,
self::CAN_UPDATE_INVOICE_JSON_DATA,
self::CAN_BE_DELETED,
self::CAN_BE_EDITED,
self::CAN_BE_CANCELED,
self::CAN_BE_COPIED,
self::VISIBLE_IN_CUSTOMER_PROF,
self::CAN_SEND_TO_CUSTOMER,
self::CAN_BE_UPDATED,
self::CAN_ROWS_BE_DELETED,
self::HAS_PDF,
self::CAN_CREATE_SALES,
];
public function __construct(Security $security)
{
$this->security = $security;
}
protected function supports($attribute, $subject): bool
{
return in_array($attribute, self::ATTRIBUTES);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
switch ($attribute) {
case self::CAN_ADD_PAYMENT:
return $this->canAddPayment($subject);
case self::CAN_CREATE_SALES:
return $this->canCreateSales($subject);
case self::CAN_UPDATE_INVOICE_JSON_DATA:
case self::CAN_BE_DELETED:
case self::CAN_BE_EDITED:
return $this->canBeEdited($subject);
case self::CAN_BE_CANCELED:
return $this->canBeCanceled($subject);
case self::CAN_BE_COPIED:
return $this->canBeCopied($subject);
case self::VISIBLE_IN_CUSTOMER_PROF:
return $this->visibleInCustomerProfile($subject);
case self::CAN_SEND_TO_CUSTOMER:
return $this->canSendToCustomer($subject);
case self::CAN_BE_UPDATED:
return $this->canBeUpdated($subject);
case self::CAN_ROWS_BE_DELETED:
return $this->canRowsBeDeleted($subject);
case self::HAS_PDF:
return $this->hasPdf($subject);
}
throw new \LogicException('Invalid attribute: ' . $attribute);
}
private function canAddPayment(Invoice $invoice): bool
{
if (!$this->security->isGranted('ROLE_SALES_MANAGER')) {
return false;
}
if ($invoice->getType() == InvoiceType::INVOICE_TYPE_SALES && (!$invoice->getSenderAddress() || !$invoice->getDeliveryAddress())) {
return false;
}
if (!$this->canBeUpdated($invoice)) {
return false;
}
return true;
}
private function canBeEdited(Invoice $invoice): bool
{
if (!$this->security->isGranted('ROLE_SALES_MANAGER')) {
return false;
}
if (!$this->canBeUpdated($invoice)) {
return false;
}
return !$invoice->getIsSent();
}
private function canBeCanceled(Invoice $invoice): bool
{
if (!$this->security->isGranted('ROLE_SALES_MANAGER')) {
return false;
}
if ($invoice->getInvoiceDirection() == Invoice::INVOICE_DIRECTION_INCOMING && !$invoice->getQuotation()) {
return false;
}
if (!$this->canBeUpdated($invoice)) {
return false;
}
return true;
}
private function visibleInCustomerProfile(Invoice $invoice): bool
{
if (!$invoice->getIsSent()) {
return false;
}
if (in_array($invoice->getStatus(), [
InvoiceStatus::INVOICE_STATUS_CANCELED
])) {
return false;
}
return true;
}
private function canSendToCustomer(Invoice $invoice): bool
{
if ($invoice->getInvoiceDirection() === Invoice::INVOICE_DIRECTION_INCOMING) {
return false;
}
if (!$this->canBeUpdated($invoice)) {
return false;
}
return !$invoice->getIsSent();
}
private function canBeCopied(Invoice $invoice): bool
{
return !$invoice->getIsWebShopRelated();
}
private function canBeUpdated(Invoice $invoice): bool
{
if (count($invoice->getBatchInvoices())) {
return false;
}
if (in_array($invoice->getStatus(), [
InvoiceStatus::INVOICE_STATUS_CANCELED,
InvoiceStatus::INVOICE_STATUS_ARCHIVED,
])) {
return false;
}
return true;
}
private function canRowsBeDeleted(Invoice $invoice): bool
{
if ($invoice->getType() === InvoiceType::INVOICE_TYPE_ADVANCE) {
return false;
}
return true;
}
private function hasPdf(Invoice $invoice): bool
{
if ($invoice->getInvoiceDirection() !== Invoice::INVOICE_DIRECTION_OUTGOING) {
return false;
}
if (!$invoice->getCustomer()) {
return false;
}
if (!$invoice->getCustomerData()) {
return false;
}
return true;
}
private function createdFromAdvance(Invoice $invoice): bool
{
foreach ($invoice->getPrepaymentInvoices() as $prepaymentInvoice) {
if ($prepaymentInvoice->getStatus() === InvoiceStatus::INVOICE_STATUS_ARCHIVED) {
return true;
}
}
return false;
}
private function canCreateSales(Invoice $invoice): bool
{
if (
$invoice->getIsBatchAdvance()
&& !in_array($invoice->getStatus(), [
InvoiceStatus::INVOICE_STATUS_ARCHIVED,
InvoiceStatus::INVOICE_STATUS_CANCELED
])
) {
return true;
}
return false;
}
}