src/Security/InvoiceVoter.php line 142

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/InvoiceVoter.php
  4. //------------------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  8. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  9. use Doctrine\Persistence\ManagerRegistry;
  10. use App\Entity\Access;
  11. use App\Entity\APIRest\AccessAPI;
  12. use App\Entity\Config\Config;
  13. use App\Entity\Config\Module;
  14. use App\Entity\HR\AccessFunction;
  15. use App\Entity\Platform\Devis\Devis;
  16. use App\Entity\Platform\Invoice\Invoice;
  17. use App\Entity\Mission\Mission;
  18. use App\Entity\Security\Acl;
  19. use App\Entity\Security\AclPermission;
  20. use App\Services\LogTools;
  21. use App\Services\Config\ModuleTools;
  22. use App\Services\Config\OptionConfigTools;
  23. class InvoiceVoter extends Voter
  24. {
  25.     // For now manager = author (both)
  26.     //--------------------------------------------------------------------------------
  27.     // is_granted constants
  28.     const IS_ACTIVE "invoice_is_active";
  29.     // addSimple :: $devis
  30.     // addCredit :: $invoice
  31.     // addFree :: $mission
  32.     const ADD "add_invoice";
  33.     // addPartial :: $devis
  34.     // addPartialForSociety :: $devis
  35.     const ADD_PART "add_partial_invoice";
  36.     // addFromDraft :: $draft instanceof Invoice
  37.     const CONVERT_DRAFT "add_invoice_from_draft";
  38.     const DELETE_DRAFT "delete_draft";
  39.     const LISTING "list_invoices";
  40.     const LISTING_SOCIETY "list_invoices_society";
  41.     const LISTING_MANAGER "list_invoices_manager";
  42.     const LISTING_ANY "list_invoices_any";
  43.     const VIEW "view_invoice";
  44.     const VIEW_PDF "view_pdf_invoice";
  45.     const EDIT "edit_invoice";
  46.     const EDIT_ANNULLED "edit_invoice_annulled";
  47.     const DELETE "delete_invoice";
  48.     const ANNUL "annul_invoice";
  49.     const REVIVE "revive_invoice";
  50.     const IS_ACTIVE_INVOICE_AUTO_ACCOUNT "invoice_auto_account_is_active";
  51.     // Plan.io Task #4326
  52.     const HANDLE_INSTALLMENT "handle_installment_for_invoice";
  53.     // Plan.io Task #4326
  54.     // I need some restrictions on the actions that can be done via the invoices list
  55.     // ie. convert drafts, delete drafts (for now at least ...)
  56.     // So check if the user has at least one edit permission active
  57.     const EDIT_SOME_INVOICES "edit_some_invoices";
  58.     const IS_GRANTED_CONSTANTS = array(
  59.         self::IS_ACTIVE,
  60.         self::ADD,
  61.         self::ADD_PART,                // Plan.io Task #3605
  62.         self::CONVERT_DRAFT,        // Plan.io Task #4326
  63.         self::DELETE_DRAFT,            // Plan.io Task #4326
  64.         self::LISTING,
  65.         self::LISTING_SOCIETY,
  66.         self::LISTING_MANAGER,
  67.         self::LISTING_ANY,
  68.         self::VIEW,
  69.         self::VIEW_PDF,
  70.         self::EDIT,
  71.         self::EDIT_ANNULLED,
  72.         self::DELETE,
  73.         self::ANNUL,
  74.         self::REVIVE,
  75.         self::IS_ACTIVE_INVOICE_AUTO_ACCOUNT,
  76.         self::HANDLE_INSTALLMENT,    // Plan.io Task #4326
  77.         self::EDIT_SOME_INVOICES,    // Plan.io Task #4326
  78.     );
  79.     const IS_GRANTED_CONSTANTS_SHARING_EXCEPTION = array(
  80.         self::VIEW,
  81.         self::VIEW_PDF,
  82.     );
  83.     //--------------------------------------------------------------------------------
  84.     // acl constants
  85.     const ACL_PERM_ADD "invoice_add";
  86.     const ACL_PERM_LISTING "invoice_list";
  87.     const ACL_PERM_LISTING_SOCIETY "invoice_list_society";
  88.     const ACL_PERM_LISTING_MANAGER "invoice_list_manager";
  89.     const ACL_PERM_VIEW "invoice_view";
  90.     const ACL_PERM_VIEW_SOCIETY "invoice_view_society";
  91.     const ACL_PERM_VIEW_MANAGER "invoice_view_manager";
  92.     const ACL_PERM_VIEW_CLIENT_MANAGER "invoice_view_ind_manager";
  93.     const ACL_PERM_VIEW_PDF "invoice_view_pdf";
  94.     const ACL_PERM_VIEW_PDF_SOCIETY "invoice_view_pdf_society";
  95.     const ACL_PERM_VIEW_PDF_MANAGER "invoice_view_pdf_manager";
  96.     const ACL_PERM_VIEW_PDF_CLIENT_MANAGER "invoice_view_pdf_ind_manager";
  97.     const ACL_PERM_EDIT "invoice_edit";
  98.     const ACL_PERM_EDIT_SOCIETY "invoice_edit_society";
  99.     const ACL_PERM_EDIT_MANAGER "invoice_edit_manager";
  100.     const ACL_PERM_EDIT_CLIENT_MANAGER "invoice_edit_ind_manager";
  101.     const ACL_PERM_EDIT_ANNULLED "invoice_edit_annulled";
  102.     const ACL_PERM_ANNUL "invoice_annul";
  103.     const ACL_PERM_ANNUL_SOCIETY "invoice_annul_society";
  104.     const ACL_PERM_REVIVE "invoice_revive";
  105.     const ACL_PERM_REVIVE_SOCIETY "invoice_revive_society";
  106.     //--------------------------------------------------------------------------------
  107.     public function __construct(AccessDecisionManagerInterface $accessDecisionManagerManagerRegistry $doctrineModuleTools $moduleToolsOptionConfigTools $optionConfigToolsLogTools $logTools)
  108.     {
  109.         $this->accessDecisionManager $accessDecisionManager;
  110.         $this->em $doctrine->getManager();
  111.         $this->moduleTools $moduleTools;
  112.         $this->optionConfigTools $optionConfigTools;
  113.         $this->logTools $logTools;
  114.         $this->aclRepository $this->em->getRepository(Acl::class);
  115.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  116.     }
  117.     // Plan.io Task #4453 [See AccessVoter for details]
  118.     public function supportsAttribute(string $attribute): bool
  119.     {
  120.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  121.     }
  122.     protected function supports(string $attribute$subject): bool
  123.     {
  124.         // if the attribute isn't one we support, return false
  125.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  126.         {
  127.             return false;
  128.         }
  129.         // Only vote on Invoice and Mission objects inside this voter
  130.         // ... and Devis (Plan.io #3605)
  131.         if ($subject !== null && !($subject instanceof Invoice || $subject instanceof Mission || $subject instanceof Devis))
  132.         {
  133.             return false;
  134.         }
  135.         return true;
  136.     }
  137.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  138.     {
  139.         $user $token->getUser();
  140.         // Plan.io Task #3707
  141.         if ($user instanceof AccessAPI)
  142.         {
  143.             if ($user->getAccess() === null)
  144.             {
  145.                 return false;
  146.             }
  147.             $user $user->getAccess();
  148.         }
  149.         // Plan.io Task #3707
  150.         // At this point $user is an object of Access type
  151.         // even if the $token->getUser() is AccessAPI
  152.         if (!$user instanceof Access)
  153.         {
  154.             // the user must be logged in; if not, deny access
  155.             return false;
  156.         }
  157.         // The user must have a function; if not deny access
  158.         $function $user->getFunction();
  159.         if ($function === null)        return false;
  160.         // Plan.io Task #3710 : Get current group
  161.         $currentGroup $user->getSocietyGroup();
  162.         if ($currentGroup === null)
  163.             return false;
  164.         $this->currentGroup $currentGroup;
  165.         // Module activated ?
  166.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_INVOICE))
  167.         {
  168.             return false;
  169.         }
  170.         $invoice null;
  171.         $mission null;
  172.         if ($subject instanceof Invoice)
  173.         {
  174.             /** @var Invoice $invoice */
  175.             $invoice $subject;
  176.             // Check current group affectation
  177.             // Make an exception for "view/pdf" : take sharing into account
  178.             if ($invoice !== null)
  179.             {
  180.                 $invoiceSociety $invoice->getSociety();
  181.                 if ($invoiceSociety === null)
  182.                     return false;
  183.                 $invoiceSocietyGroup $invoiceSociety->getGroup();
  184.                 if ($invoiceSocietyGroup === null)
  185.                     return false;
  186.                 if (!in_array($attributeself::IS_GRANTED_CONSTANTS_SHARING_EXCEPTION))
  187.                 {
  188.                     // Just check currentGroup
  189.                     if (!$currentGroup->equals($invoiceSocietyGroup))
  190.                         return false;
  191.                 }
  192.                 else
  193.                 {
  194.                     // Take sharing into account
  195.                     // If the invoice belongs to a mission that was created by the currentGroup
  196.                     // (invoice.mission.societyGroupAuthor == currentGroup)
  197.                     // Then it can see the invoice
  198.                     if (!$currentGroup->equals($invoiceSocietyGroup))
  199.                     {
  200.                         if ($invoice->getMission() !== null)
  201.                         {
  202.                             $missionSocietyGroupAuthor $invoice->getMission()->getSocietyGroupAuthor();
  203.                             if (!$currentGroup->equals($missionSocietyGroupAuthor))
  204.                             {
  205.                                 return false;
  206.                             }
  207.                         }
  208.                     }
  209.                 }
  210.             }
  211.         }
  212.         else
  213.         {
  214.             if ($subject instanceof Mission)
  215.             {
  216.                 /** @var Mission $mission */
  217.                 $mission $subject;
  218.                 // Plan.io Task #3517
  219.                 // Adding an invoice counts as editing a mission
  220.                 // So check if the current user has access to this mission
  221.                 // If this is too restrictive, change 'edit_mission' with 'view_mission'
  222.                 // 'view_mission' is better ;)
  223.                 if (!$this->accessDecisionManager->decide($token, ['view_mission'], $mission))
  224.                 {
  225.                     return false;
  226.                 }
  227.             }
  228.         }
  229.         switch ($attribute)
  230.         {
  231.             case self::IS_ACTIVE:
  232.                 return true;
  233.             case self::IS_ACTIVE_INVOICE_AUTO_ACCOUNT:
  234.             {
  235.                 return $this->optionConfigTools->isActive_InvoiceAutoAccount($currentGroup);
  236.             }
  237.             case self::ADD:
  238.             {
  239.                 // addSimple :: $devis
  240.                 // addCredit :: $invoice
  241.                 // addFree :: $mission
  242.                 return $this->canAdd($subject$user$function);
  243.             }
  244.             case self::EDIT_SOME_INVOICES:
  245.             {
  246.                 // Plan.io Task #4326
  247.                 return $this->canEditSomeInvoices($user$function);
  248.             }
  249.             case self::CONVERT_DRAFT:
  250.             {
  251.                 // Plan.io Task #4326
  252.                 // addFromDraft :: $draft instanceof Invoice
  253.                 return $this->canConvertDraft($subject$user$function);
  254.             }
  255.             case self::DELETE_DRAFT:
  256.             {
  257.                 // Plan.io Task #4326
  258.                 // addFromDraft :: $draft instanceof Invoice
  259.                 return $this->canDeleteDraft($subject$user$function);
  260.             }
  261.             // Plan.io Task #3605
  262.             case self::ADD_PART:
  263.             {
  264.                 // addPartial :: $devis
  265.                 // addPartialForSociety :: $devis
  266.                 return $this->canAddPart($subject$user$function);
  267.             }
  268.             case self::LISTING:
  269.                 return $this->canList($invoice$user$function);
  270.             case self::LISTING_SOCIETY:
  271.                 return $this->canListSociety($invoice$user$function);
  272.             case self::LISTING_MANAGER:
  273.                 return $this->canListManager($invoice$user$function);
  274.             case self::LISTING_ANY:
  275.                 return $this->canListAny($invoice$user$function);
  276.             case self::VIEW:
  277.                 return $this->canView($invoice$user$function);
  278.             case self::VIEW_PDF:
  279.                 return $this->canViewPdf($invoice$user$function);
  280.             case self::EDIT:
  281.                 return $this->canEdit($invoice$user$function);
  282.             case self::EDIT_ANNULLED:
  283.                 return $this->canEditAnnulled($invoice$user$function);
  284.             case self::DELETE:
  285.                 return $this->canDelete($invoice$user$function);
  286.             case self::ANNUL:
  287.                 return $this->canAnnul($invoice$user$function);
  288.             case self::REVIVE:
  289.                 return $this->canRevive($invoice$user$function);
  290.             case self::HANDLE_INSTALLMENT:
  291.                 return $this->canHandleInstallment($invoice$user$function);
  292.         }
  293.         throw new \LogicException('This code should not be reached!');
  294.     }
  295.     // $access is the user trying to load the resource
  296.     // $invoice is the resource being loaded
  297.     // Check if the Society of the resource
  298.     // belongs to the societies of the $access
  299.     private function checkSociety(Invoice $invoiceAccess $access)
  300.     {
  301.         // Get all the societies of the access
  302.         $societies $access->getSocieties();
  303.         // Get the Society of the Invoice
  304.         $invoiceSociety $invoice->getSociety();
  305.         if ($invoiceSociety === null)
  306.             return false;
  307.         $found false;
  308.         foreach ($societies as $society)
  309.         {
  310.             if ($society->getId() == $invoiceSociety->getId())
  311.             {
  312.                 $found true;
  313.                 break;
  314.             }
  315.         }
  316.         return $found;
  317.     }
  318.     // Check if the $access is the manager / author of the $invoice
  319.     private function checkManager(Invoice $invoiceAccess $access)
  320.     {
  321.         // Get manager
  322.         $manager $invoice->getManager();
  323.         $author $invoice->getManager();
  324.         if ($manager === null && $author === null)
  325.             return false;
  326.         if ($manager !== null)
  327.             if ($manager->getId() === $access->getId())
  328.                 return true;
  329.         if ($author !== null)
  330.             if ($author->getId() === $access->getId())
  331.                 return true;
  332.         return false;
  333.     }
  334.     // Check if the $access is the manager of the $invoice
  335.     private function checkClientManager(Invoice $invoiceAccess $access)
  336.     {
  337.         // Get Client
  338.         $client $invoice->getReceiver();
  339.         if ($client === null)
  340.             return false;
  341.         if ($client->getIndividual() !== null)
  342.         {
  343.             // Only Individuals have managers
  344.             // Get manager
  345.             $manager $invoice->getReceiver()->getIndividual()->getManager();
  346.             if ($manager === null)
  347.                 return false;
  348.             if ($manager->getId() === $access->getId())
  349.                 return true;
  350.         }
  351.         return false;
  352.     }
  353.     private function canAdd($subjectAccess $userAccessFunction $function)
  354.     {
  355.         if ($subject instanceof Invoice)
  356.         {
  357.             // Plan.io Task #4326
  358.             // No adding invoices for drafts
  359.             if ($subject->isDraft())
  360.             {
  361.                 return false;
  362.             }
  363.         }
  364.         return $this->commonAddConditions($subject$user$function);
  365.     }
  366.     // Plan.io Task #4326
  367.     private function canDeleteDraft(Invoice $draftAccess $userAccessFunction $function)
  368.     {
  369.         // No deleting invoices
  370.         if ($draft->isNotDraft())
  371.         {
  372.             return false;
  373.         }
  374.         return $this->commonEditConditions($draft$user$function);
  375.     }
  376.     // Plan.io Task #4326
  377.     private function canConvertDraft(Invoice $draftAccess $userAccessFunction $function)
  378.     {
  379.         // No converting invoices
  380.         if ($draft->isNotDraft())
  381.         {
  382.             return false;
  383.         }
  384.         return $this->commonAddConditions($draft$user$function);
  385.     }
  386.     private function commonAddConditions($subjectAccess $userAccessFunction $function)
  387.     {
  388.         if ($subject instanceof Invoice)
  389.         {
  390.             $mission $subject->getMission();
  391.         }
  392.         else
  393.         {
  394.             if ($subject instanceof Devis)
  395.             {
  396.                 $mission $subject->getMission();
  397.             }
  398.             else
  399.             {
  400.                 if ($subject instanceof Mission)
  401.                 {
  402.                     $mission $subject;
  403.                 }
  404.                 else
  405.                 {
  406.                     return false;
  407.                 }
  408.             }
  409.         }
  410.         if ($mission === null)
  411.         {
  412.             return false;
  413.         }
  414.         // Deny actions on archivedRefused objects
  415.         if ($mission->isArchivedRefused())
  416.         {
  417.             return false;
  418.         }
  419.         // If the mission is shared and the author is the current group, deny adding devis
  420.         // When a mission is shared, the author cannot edit it
  421.         if ($mission->isShared())
  422.         {
  423.             if ($mission->isSharedBySocietyGroup($this->currentGroup))
  424.             {
  425.                 return false;
  426.             }
  427.         }
  428.         // Get AclPermission
  429.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  430.         if ($aclPerm === null)        return false;
  431.         // Get Acl
  432.         $acl $this->aclRepository->findOneBy(array(
  433.             'function'        =>    $function,
  434.             'permission'    =>    $aclPerm
  435.         ));
  436.         if ($acl === null)        return false;
  437.         // Since only one acl type can exist
  438.         // we can return the result of the acl_permission
  439.         return $acl->getValue();
  440.     }
  441.     // Plan.io Task #3605
  442.     private function canAddPart(Devis $devisAccess $userAccessFunction $function)
  443.     {
  444.         if (!$this->canAdd($devis->getMission(), $user$function))
  445.         {
  446.             // Deny if no permission to add any kind of invoices
  447.             return false;
  448.         }
  449.         if ($devis->getGhost() !== null)
  450.         {
  451.             // Deny permission if devis has a ghost
  452.             return false;
  453.         }
  454.         // Plan.io Task #4328
  455.         if ($devis->hasEcoBonus())
  456.         {
  457.             // Deny permission if devis has ecobonus
  458.             return false;
  459.         }
  460.         // Allow
  461.         return true;
  462.     }
  463.     private function canEditAnnulled(Invoice $invoice nullAccess $userAccessFunction $function)
  464.     {
  465.         // Plan.io Task #4326 : Deny on everything that is not a Draft
  466.         if ($invoice->isNotDraft())
  467.         {
  468.             return false;
  469.         }
  470.         // Plan.io Task #3897 : Deny on Group Invoices
  471.         if ($invoice->isGroup())
  472.         {
  473.             return false;
  474.         }
  475.         // Deny edit on archivedRefused objects
  476.         if ($invoice->isArchivedRefused())
  477.         {
  478.             return false;
  479.         }
  480.         // Get AclPermission
  481.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_ANNULLED);
  482.         if ($aclPerm === null)        return false;
  483.         // Get Acl
  484.         $acl $this->aclRepository->findOneBy(array(
  485.             'function'        =>    $function,
  486.             'permission'    =>    $aclPerm
  487.         ));
  488.         if ($acl === null)        return false;
  489.         // Since only one acl type can exist
  490.         // we can return the result of the acl_permission
  491.         return $acl->getValue();
  492.     }
  493.     private function canList(Invoice $invoice nullAccess $userAccessFunction $function)
  494.     {
  495.         // Get AclPermission
  496.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  497.         if ($aclPerm === null)        return false;
  498.         // Get Acl
  499.         $acl $this->aclRepository->findOneBy(array(
  500.             'function'        =>    $function,
  501.             'permission'    =>    $aclPerm
  502.         ));
  503.         if ($acl === null)        return false;
  504.         // Since only one acl type can exist
  505.         // we can return the result of the acl_permission
  506.         return $acl->getValue();
  507.     }
  508.     private function canListSociety(Invoice $invoice nullAccess $userAccessFunction $function)
  509.     {
  510.         // Get AclPermission
  511.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  512.         if ($aclPerm === null)        return false;
  513.         // Get Acl
  514.         $acl $this->aclRepository->findOneBy(array(
  515.             'function'        =>    $function,
  516.             'permission'    =>    $aclPerm
  517.         ));
  518.         if ($acl === null)        return false;
  519.         // Since only one acl type can exist
  520.         // we can return the result of the acl_permission
  521.         // Further filtering is done in the Controller
  522.         return $acl->getValue();
  523.     }
  524.     private function canListManager(Invoice $invoice nullAccess $userAccessFunction $function)
  525.     {
  526.         // Get AclPermission
  527.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_MANAGER);
  528.         if ($aclPerm === null)        return false;
  529.         // Get Acl
  530.         $acl $this->aclRepository->findOneBy(array(
  531.             'function'        =>    $function,
  532.             'permission'    =>    $aclPerm
  533.         ));
  534.         if ($acl === null)        return false;
  535.         // Since only one acl type can exist
  536.         // we can return the result of the acl_permission
  537.         // Further filtering is done in the Controller
  538.         return $acl->getValue();
  539.     }
  540.     private function canListAny(Invoice $invoice nullAccess $userAccessFunction $function)
  541.     {
  542.         // Three AclPermission may exist
  543.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  544.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  545.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_MANAGER);
  546.         // If all are null, exit
  547.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  548.             return false;
  549.         // Get First one
  550.         if ($aclPerm !== null)
  551.         {
  552.             $acl $this->aclRepository->findOneBy(array(
  553.                 'function'        =>    $function,
  554.                 'permission'    =>    $aclPerm
  555.             ));
  556.             if ($acl !== null)
  557.             {
  558.                 if ($acl->getValue())
  559.                 {
  560.                     // A single positive answer is enough
  561.                     return true;
  562.                 }
  563.             }
  564.         }
  565.         // If we are here it means that nothing good has been found
  566.         // Load second permission
  567.         if ($aclPermSociety !== null)
  568.         {
  569.             $acl $this->aclRepository->findOneBy(array(
  570.                 'function'        =>    $function,
  571.                 'permission'    =>    $aclPermSociety
  572.             ));
  573.             if ($acl !== null)
  574.             {
  575.                 if ($acl->getValue())
  576.                 {
  577.                     // A single positive answer is enough
  578.                     return true;
  579.                 }
  580.             }
  581.         }
  582.         // If we are here it means that nothing good has been found
  583.         // Load third permission
  584.         if ($aclPermManager !== null)
  585.         {
  586.             $acl $this->aclRepository->findOneBy(array(
  587.                 'function'        =>    $function,
  588.                 'permission'    =>    $aclPermManager
  589.             ));
  590.             if ($acl !== null)
  591.             {
  592.                 if ($acl->getValue())
  593.                 {
  594.                     // A single positive answer is enough
  595.                     return true;
  596.                 }
  597.             }
  598.         }
  599.         // If we are here, all hope is lost
  600.         return false;
  601.     }
  602.     private function canView(Invoice $invoice nullAccess $userAccessFunction $function)
  603.     {
  604.         // Four AclPermission may exist
  605.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  606.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  607.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_MANAGER);
  608.         $aclPermClientManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_CLIENT_MANAGER);
  609.         // If all are null, exit
  610.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null && $aclPermClientManager)
  611.             return false;
  612.         // Get First one
  613.         if ($aclPerm !== null)
  614.         {
  615.             $acl $this->aclRepository->findOneBy(array(
  616.                 'function'        =>    $function,
  617.                 'permission'    =>    $aclPerm
  618.             ));
  619.             if ($acl !== null)
  620.             {
  621.                 if ($acl->getValue())
  622.                 {
  623.                     // A single positive answer is enough
  624.                     return true;
  625.                 }
  626.             }
  627.         }
  628.         // If we are here it means that nothing good has been found
  629.         // Load second permission
  630.         if ($aclPermSociety !== null)
  631.         {
  632.             $acl $this->aclRepository->findOneBy(array(
  633.                 'function'        =>    $function,
  634.                 'permission'    =>    $aclPermSociety
  635.             ));
  636.             if ($acl !== null)
  637.             {
  638.                 if ($acl->getValue())
  639.                 {
  640.                     // A single positive answer is enough
  641.                     // In this case the good answer will be provided by the checkSociety
  642.                     return $this->checkSociety($invoice$user);
  643.                 }
  644.             }
  645.         }
  646.         // If we are here it means that nothing good has been found
  647.         // Load third permission
  648.         if ($aclPermManager !== null)
  649.         {
  650.             $acl $this->aclRepository->findOneBy(array(
  651.                 'function'        =>    $function,
  652.                 'permission'    =>    $aclPermManager
  653.             ));
  654.             if ($acl !== null)
  655.             {
  656.                 if ($acl->getValue())
  657.                 {
  658.                     // A single positive answer is enough
  659.                     // In this case the good answer will be provided by the checkSociety
  660.                     return $this->checkManager($invoice$user);
  661.                 }
  662.             }
  663.         }
  664.         // If we are here it means that nothing good has been found
  665.         // Load fourth permission
  666.         if ($aclPermClientManager !== null)
  667.         {
  668.             $acl $this->aclRepository->findOneBy(array(
  669.                 'function'        =>    $function,
  670.                 'permission'    =>    $aclPermClientManager
  671.             ));
  672.             if ($acl !== null)
  673.             {
  674.                 if ($acl->getValue())
  675.                 {
  676.                     // A single positive answer is enough
  677.                     // In this case the good answer will be provided by the checkSociety
  678.                     return $this->checkClientManager($invoice$user);
  679.                 }
  680.             }
  681.         }
  682.         // If we are here, all hope is lost
  683.         return false;
  684.     }
  685.     private function canViewPdf(Invoice $invoice nullAccess $userAccessFunction $function)
  686.     {
  687.         // Four AclPermission may exist
  688.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF);
  689.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF_SOCIETY);
  690.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF_MANAGER);
  691.         $aclPermClientManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF_CLIENT_MANAGER);
  692.         // If all are null, exit
  693.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null && $aclPermClientManager === null)
  694.             return false;
  695.         // Get First one
  696.         if ($aclPerm !== null)
  697.         {
  698.             $acl $this->aclRepository->findOneBy(array(
  699.                 'function'        =>    $function,
  700.                 'permission'    =>    $aclPerm
  701.             ));
  702.             if ($acl !== null)
  703.             {
  704.                 if ($acl->getValue())
  705.                 {
  706.                     // A single positive answer is enough
  707.                     return true;
  708.                 }
  709.             }
  710.         }
  711.         // If we are here it means that nothing good has been found
  712.         // Load second permission
  713.         if ($aclPermSociety !== null)
  714.         {
  715.             $acl $this->aclRepository->findOneBy(array(
  716.                 'function'        =>    $function,
  717.                 'permission'    =>    $aclPermSociety
  718.             ));
  719.             if ($acl !== null)
  720.             {
  721.                 if ($acl->getValue())
  722.                 {
  723.                     // A single positive answer is enough
  724.                     // In this case the good answer will be provided by the checkSociety
  725.                     return $this->checkSociety($invoice$user);
  726.                 }
  727.             }
  728.         }
  729.         // If we are here it means that nothing good has been found
  730.         // Load third permission
  731.         if ($aclPermManager !== null)
  732.         {
  733.             $acl $this->aclRepository->findOneBy(array(
  734.                 'function'        =>    $function,
  735.                 'permission'    =>    $aclPermManager
  736.             ));
  737.             if ($acl !== null)
  738.             {
  739.                 if ($acl->getValue())
  740.                 {
  741.                     // A single positive answer is enough
  742.                     // In this case the good answer will be provided by the checkSociety
  743.                     return $this->checkManager($invoice$user);
  744.                 }
  745.             }
  746.         }
  747.         // If we are here it means that nothing good has been found
  748.         // Load fourth permission
  749.         if ($aclPermClientManager !== null)
  750.         {
  751.             $acl $this->aclRepository->findOneBy(array(
  752.                 'function'        =>    $function,
  753.                 'permission'    =>    $aclPermClientManager
  754.             ));
  755.             if ($acl !== null)
  756.             {
  757.                 if ($acl->getValue())
  758.                 {
  759.                     // A single positive answer is enough
  760.                     // In this case the good answer will be provided by the checkSociety
  761.                     return $this->checkClientManager($invoice$user);
  762.                 }
  763.             }
  764.         }
  765.         // If we are here, all hope is lost
  766.         return false;
  767.     }
  768.     private function canHandleInstallment(Invoice $invoiceAccess $userAccessFunction $function)
  769.     {
  770.         return $this->commonEditConditions($invoice$user$function);
  771.     }
  772.     private function canEdit(Invoice $invoice nullAccess $userAccessFunction $function)
  773.     {
  774.         // Plan.io Task #4326 : Deny on everything that is not a Draft
  775.         if ($invoice->isNotDraft())
  776.         {
  777.             return false;
  778.         }
  779.         // Plan.io Task #4328
  780.         if ($this->moduleTools->isInactiveByCode($this->currentGroupModule::MODULE_ECO_BONUS) && $invoice->hasEcoBonus())
  781.         {
  782.             // Deny permission if devis has ecobonus
  783.             return false;
  784.         }
  785.         return $this->commonEditConditions($invoice$user$function);
  786.     }
  787.     private function commonEditConditions(Invoice $invoice nullAccess $userAccessFunction $function)
  788.     {
  789.         // Plan.io Task #3897 : Deny on Group Invoices
  790.         if ($invoice->isGroup())
  791.         {
  792.             return false;
  793.         }
  794.         // Deny edit on archivedRefused objects
  795.         if ($invoice->isArchivedRefused())
  796.         {
  797.             return false;
  798.         }
  799.         // No edditing on annulled invoices
  800.         if ($invoice->isAnnulled())
  801.         {
  802.             return false;
  803.         }
  804.         // Plan.io Task #4208 : Invoices should never be annulled,
  805.         // so even if the Invoice has a Credit, allow editing it
  806.         // No edditing on invoices that have been "annuled" (with credit)
  807.         // $credit = $this->em->getRepository(Invoice::class)->findOneByCreditInvoice($invoice);
  808.         // if ($credit !== null)
  809.         //     return false;
  810.         // Four AclPermission may exist
  811.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  812.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  813.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_MANAGER);
  814.         $aclPermClientManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_CLIENT_MANAGER);
  815.         // If all are null, exit
  816.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null && $aclPermClientManager)
  817.             return false;
  818.         // Get First one
  819.         if ($aclPerm !== null)
  820.         {
  821.             $acl $this->aclRepository->findOneBy(array(
  822.                 'function'        =>    $function,
  823.                 'permission'    =>    $aclPerm
  824.             ));
  825.             if ($acl !== null)
  826.             {
  827.                 if ($acl->getValue())
  828.                 {
  829.                     // A single positive answer is enough
  830.                     return true;
  831.                 }
  832.             }
  833.         }
  834.         // If we are here it means that nothing good has been found
  835.         // Load second permission
  836.         if ($aclPermSociety !== null)
  837.         {
  838.             $acl $this->aclRepository->findOneBy(array(
  839.                 'function'        =>    $function,
  840.                 'permission'    =>    $aclPermSociety
  841.             ));
  842.             if ($acl !== null)
  843.             {
  844.                 if ($acl->getValue())
  845.                 {
  846.                     // A single positive answer is enough
  847.                     // In this case the good answer will be provided by the checkSociety
  848.                     return $this->checkSociety($invoice$user);
  849.                 }
  850.             }
  851.         }
  852.         // If we are here it means that nothing good has been found
  853.         // Load third permission
  854.         if ($aclPermManager !== null)
  855.         {
  856.             $acl $this->aclRepository->findOneBy(array(
  857.                 'function'        =>    $function,
  858.                 'permission'    =>    $aclPermManager
  859.             ));
  860.             if ($acl !== null)
  861.             {
  862.                 if ($acl->getValue())
  863.                 {
  864.                     // A single positive answer is enough
  865.                     // In this case the good answer will be provided by the checkSociety
  866.                     return $this->checkManager($invoice$user);
  867.                 }
  868.             }
  869.         }
  870.         // If we are here it means that nothing good has been found
  871.         // Load fourth permission
  872.         if ($aclPermClientManager !== null)
  873.         {
  874.             $acl $this->aclRepository->findOneBy(array(
  875.                 'function'        =>    $function,
  876.                 'permission'    =>    $aclPermClientManager
  877.             ));
  878.             if ($acl !== null)
  879.             {
  880.                 if ($acl->getValue())
  881.                 {
  882.                     // A single positive answer is enough
  883.                     // In this case the good answer will be provided by the checkSociety
  884.                     return $this->checkClientManager($invoice$user);
  885.                 }
  886.             }
  887.         }
  888.         // If we are here, all hope is lost
  889.         return false;
  890.     }
  891.     private function canDelete(Invoice $invoice nullAccess $userAccessFunction $function)
  892.     {
  893.         return false;
  894.     }
  895.     private function canAnnul(Invoice $invoice nullAccess $userAccessFunction $function)
  896.     {
  897.         // We no longer annul invoices
  898.         return false;
  899.     }
  900.     private function canRevive(Invoice $invoice nullAccess $userAccessFunction $function)
  901.     {
  902.         // We no longer annul & revive invoices
  903.         return false;
  904.     }
  905.     // Plan.io Task #4326
  906.     // I need some restrictions on the actions that can be done via the invoices list
  907.     // ie. convert drafts, delete drafts (for now at least ...)
  908.     // So check if the user has at least one edit permission active
  909.     private function canEditSomeInvoices(Access $userAccessFunction $function)
  910.     {
  911.         // Four AclPermission may exist
  912.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  913.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  914.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_MANAGER);
  915.         $aclPermClientManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_CLIENT_MANAGER);
  916.         // If all are null, exit
  917.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null && $aclPermClientManager)
  918.             return false;
  919.         // Get First one
  920.         if ($aclPerm !== null)
  921.         {
  922.             $acl $this->aclRepository->findOneBy(array(
  923.                 'function'        =>    $function,
  924.                 'permission'    =>    $aclPerm
  925.             ));
  926.             if ($acl !== null)
  927.             {
  928.                 if ($acl->getValue())
  929.                 {
  930.                     // A single positive answer is enough
  931.                     return true;
  932.                 }
  933.             }
  934.         }
  935.         // If we are here it means that nothing good has been found
  936.         // Load second permission
  937.         if ($aclPermSociety !== null)
  938.         {
  939.             $acl $this->aclRepository->findOneBy(array(
  940.                 'function'        =>    $function,
  941.                 'permission'    =>    $aclPermSociety
  942.             ));
  943.             if ($acl !== null)
  944.             {
  945.                 if ($acl->getValue())
  946.                 {
  947.                     // A single positive answer is enough
  948.                     return true;
  949.                 }
  950.             }
  951.         }
  952.         // If we are here it means that nothing good has been found
  953.         // Load third permission
  954.         if ($aclPermManager !== null)
  955.         {
  956.             $acl $this->aclRepository->findOneBy(array(
  957.                 'function'        =>    $function,
  958.                 'permission'    =>    $aclPermManager
  959.             ));
  960.             if ($acl !== null)
  961.             {
  962.                 if ($acl->getValue())
  963.                 {
  964.                     // A single positive answer is enough
  965.                     return true;
  966.                 }
  967.             }
  968.         }
  969.         // If we are here it means that nothing good has been found
  970.         // Load fourth permission
  971.         if ($aclPermClientManager !== null)
  972.         {
  973.             $acl $this->aclRepository->findOneBy(array(
  974.                 'function'        =>    $function,
  975.                 'permission'    =>    $aclPermClientManager
  976.             ));
  977.             if ($acl !== null)
  978.             {
  979.                 if ($acl->getValue())
  980.                 {
  981.                     // A single positive answer is enough
  982.                     return true;
  983.                 }
  984.             }
  985.         }
  986.         // If we are here, all hope is lost
  987.         return false;
  988.     }
  989. }