src/Controller/Paie/HonoraireController.php line 301

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Paie;
  3. use Mpdf\Mpdf;
  4. use App\Entity\Lrib;
  5. use App\Entity\PPiece;
  6. use App\Entity\PDevise;
  7. use App\Entity\PStatut;
  8. use App\Entity\PDossier;
  9. use App\Entity\Pemploye;
  10. use App\Entity\Probleme;
  11. use App\Entity\LContract;
  12. use App\Entity\PPaiement;
  13. use App\Entity\Prubrique;
  14. use App\Entity\Tbulletin;
  15. use App\Entity\PBordereau;
  16. use App\Entity\TbulletinLg;
  17. use App\Entity\PnatureContract;
  18. use App\Entity\TypRemuneration;
  19. use App\Controller\ApiController;
  20. use App\Entity\InjectRemuneration;
  21. use App\Service\CalculPaieService;
  22. use Doctrine\Persistence\ManagerRegistry;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. use Symfony\Component\HttpFoundation\JsonResponse;
  27. use PhpOffice\PhpSpreadsheet\Reader\Xlsx as Reader;
  28. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  29. use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
  30. #[Route('/paie/honoraire')]
  31. class HonoraireController extends AbstractController
  32. {
  33.     private $em;
  34.     private $calculPaieService;
  35.     private $api;
  36.     public function __construct(ManagerRegistry $doctrineCalculPaieService $calculPaieServiceApiController $api)
  37.     {
  38.         $this->em $doctrine->getManager();
  39.         $this->calculPaieService $calculPaieService;
  40.         $this->api $api;
  41.         
  42.     }
  43.     #[Route('/'name'app_paie_honoraire')]
  44.     public function index(Request $request): Response
  45.     {
  46.         $operations $this->api->check($this->getUser(), 'app_paie_honoraire'$this->em$request);
  47.         if(!is_array($operations)) {
  48.             return $this->redirectToRoute('app_site');  
  49.         }elseif(count($operations) == 0) {
  50.             return $this->render('includes/404.html.twig');
  51.         }
  52.         if(!is_array($operations)) {
  53.             return $this->redirectToRoute('app_site');  
  54.         }elseif(count($operations) == 0) {
  55.             return $this->render('includes/404.html.twig');
  56.         }
  57.         $dossiers $this->em->getRepository(PDossier::class)->findBy(['active' => true]);
  58.         $paiements $this->em->getRepository(PPaiement::class)->findBy(['active' => true]);
  59.         $devises $this->em->getRepository(PDevise::class)->findBy(['active' => true]);
  60.         $elementHonoraires $this->em->getRepository(Prubrique::class)->findBy(['honoraire' => true'active' => true]);
  61.         $natures $this->em->getRepository(PnatureContract::class)->findBy(['type' => $this->em->getRepository(TypRemuneration::class)->findBy(['id' => [35]])]);
  62.         return $this->render('paie/honoraire/index.html.twig', [
  63.            'operations' => $operations,
  64.            'natures' => $natures,
  65.            'paiements' => $paiements,
  66.            'dossiers' => $dossiers,
  67.            'devises' => $devises,
  68.            'elementHonoraires' => $elementHonoraires,
  69.         ]);
  70.     }
  71.     #[Route('/app_paie_honoraire_import/{paiement}/{devise}'name'app_paie_honoraire_import'options: ['expose' => true])]
  72.     public function app_paie_honoraire_import(Request $requestPPaiement $paiement,PDevise $devise): Response
  73.     {
  74.         // $dossier = $this->em->getRepository(PDossier::class)->find($request->get('dossier'));
  75.         $reader = new Reader();
  76.         $spreadsheet $reader->load($request->files->get('file'));
  77.         $worksheet $spreadsheet->getActiveSheet();
  78.         $spreadSheetArys $worksheet->toArray();
  79.         unset($spreadSheetArys[0]);
  80.         $array = [];
  81.         $data = [];
  82.         // dd($spreadSheetArys);
  83.         $count 0;
  84.         foreach ($spreadSheetArys as $key => $sheet) {
  85.             $element $this->em->getRepository(Prubrique::class)->findOneBy(['id' => $sheet[11], 'honoraire' => true'active' => true]);
  86.             if(!$element) {
  87.                 return new JsonResponse('Element introuvable à la ligne '.($key 1).' !'500);                
  88.             } 
  89.             $data [$key]['element']=$element->getId();
  90.             $contract $this->em->getRepository(LContract::class)->findOneBy(['id' => $sheet[0],'active' => true]);
  91.             if(!$contract) {
  92.                 return new JsonResponse('Contrat introuvable à la ligne '.($key 1).' !'500);                
  93.             } 
  94.             $data [$key]['dossier']=$contract->getDossier()->getId();
  95.             if(strtolower($contract->getEmploye()->getCin()) != strtolower($sheet[3])) {
  96.                 return new JsonResponse('le contrat n\'appartient pas à ce cin '.($key 1).' !'500);
  97.             }
  98.             $rib $this->em->getRepository(Lrib::class)->findOneBy(['contact_id' => $contract'active' => true]);
  99.             // dd($rib->getCode(), $sheet[4]);
  100.             // if($paiement->getId() == 1 && !preg_match('/^[0-9]{24}$/', $sheet[4])) {
  101.             if($paiement->getId() == && strlen($sheet[4]) < 24 && preg_match('/^[0-9\s]+$/'$sheet[4])) {
  102.                 return new JsonResponse('RIB incorrect à la ligne '.($key 1).' !'500);
  103.             } elseif ($paiement->getId() == && !$rib) {
  104.                 return new JsonResponse('vous n\'avez aucun RIB lié a cette contrat à la ligne '.($key 1).' !'500);
  105.             }
  106.             elseif($paiement->getId() == && $rib->getCode() != $sheet[4]) {
  107.                 return new JsonResponse('Veuillez insérer un RIB lié au même contrat à la ligne '.($key 1).' !'500);
  108.             }
  109.            
  110.             $count++;
  111.             for ($i=5$i 11 $i++) { 
  112.                 if($this->hasMoreThanTwoDecimals($sheet[$i])) {
  113.                     return new JsonResponse('Vous disposez d\'un montant contenant plus de 2 décimales à la ligne '.($key 1).' !'500);
  114.                 }
  115.             }
  116.             $montant preg_replace('/[\p{Z}\s]+/u'''$sheet[5]);
  117.             $montant_mad preg_replace('/[\p{Z}\s]+/u'''$sheet[6]);
  118.             $brute preg_replace('/[\p{Z}\s]+/u'''$sheet[7]);
  119.             $brute_mad preg_replace('/[\p{Z}\s]+/u'''$sheet[8]);
  120.             $ir preg_replace('/[\p{Z}\s]+/u'''$sheet[9]);
  121.             $ir_mad preg_replace('/[\p{Z}\s]+/u'''$sheet[10]);
  122.             $montant str_replace(',''.'$montant);
  123.             $montant_mad str_replace(',''.'$montant_mad);
  124.             $brute str_replace(',''.'$brute);
  125.             $brute_mad str_replace(',''.'$brute_mad);
  126.             $ir str_replace(',''.'$ir);
  127.             $ir_mad str_replace(',''.'$ir_mad);
  128.             
  129.             if($ir or $brute or $montant 0) {
  130.                 return new JsonResponse('Vous un montant négatif à la ligne '.($key 1).' !'500);
  131.             }
  132.             
  133.             
  134.             if(number_format(($brute $ir) - $montant2) != or number_format(($brute_mad $ir_mad) - $montant_mad2) != 0) {
  135.                 return new JsonResponse('Vous un écart à la ligne '.($key 1).' !'500);
  136.             }
  137.             $searchedKey $this->searchKeyByKeys($array'contract_id'$contract->getId(), 'element_id'$element->getId());
  138.             // dump($searchedKey);
  139.             if(!is_null($searchedKey)) {
  140.                 $array[$searchedKey]['montant'] += $montant;
  141.                 $array[$searchedKey]['montant_mad'] += $montant_mad;
  142.                 $array[$searchedKey]['brute'] += $brute;
  143.                 $array[$searchedKey]['brute_mad'] += $brute_mad;
  144.                 $array[$searchedKey]['ir'] += $ir;
  145.                 $array[$searchedKey]['ir_mad'] += $ir_mad;
  146.             } else {
  147.                 array_push($array, [
  148.                     'id' => $count,
  149.                     'nom' => $contract->getEmploye()->getNom(),
  150.                     'nature_contract' => $contract->getPnatureContract()->getId(),
  151.                     'prenom' => $contract->getEmploye()->getPrenom(),
  152.                     'contract_id' => $contract->getId(),
  153.                     'dossier_id' => $contract->getDossier()->getId(),
  154.                     'dossier' => $contract->getDossier()->getAbreviation(),
  155.                     'montant' => $montant,
  156.                     'montant_mad' => $montant_mad,
  157.                     'brute' => $brute,
  158.                     'brute_mad' => $brute_mad,
  159.                     'ir' => $ir,
  160.                     'ir_mad' => $ir_mad,
  161.                     'element_id' => $element->getId(),
  162.                     'element' => $element->getDesignation(),
  163.                     'rib' => $rib $rib->getCode() : '',
  164.                 ]);
  165.             }
  166.         }
  167.         // dd($data);
  168.         $data array_unique(array_map('serialize'$data));
  169.         $data array_map('unserialize'$data);
  170.         $data array_values($data);
  171.         $periode $this->calculPaieService->getPeriode();
  172.         
  173.         foreach($data as $d){
  174.             $existingHonoraires $this->em->getRepository(InjectRemuneration::class)
  175.             ->createQueryBuilder('i')
  176.             ->where('i.active = 1 ')
  177.             ->andWhere('i.type = :type ')
  178.             ->andWhere('i.periode = :periode')
  179.             ->andWhere('i.devise = :devise')
  180.             ->andWhere('i.dossier = :dossier')
  181.             ->andWhere('i.rubrique = :rubrique')
  182.             ->setParameter('type''honoraire')
  183.             ->setParameter('periode'$periode)
  184.             ->setParameter('devise'$devise)
  185.             ->setParameter('dossier'$this->em->getRepository(PDossier::class)->find($d["dossier"]))
  186.             ->setParameter('rubrique'$this->em->getRepository(Prubrique::class)->find($d["element"]))
  187.             ->getQuery()
  188.             ->getResult();
  189.             if($existingHonoraires){
  190.                 return new JsonResponse(['message' => 'Les honoraires pour la rubrique '.$d["element"].' existe déjà pour le dossier '.$d["dossier"].' dans la periode '.$periode->getCode()]);
  191.             }
  192.         }
  193.         return new JsonResponse($array);
  194.     }
  195.     #[Route('/app_paie_honoraire_insert'name'app_paie_honoraire_insert'options: ['expose' => true])]
  196.     public function app_paie_honoraire_insert(Request $request): Response
  197.     {
  198.         $devise $this->em->getRepository(PDevise::class)->find($request->get('devise'));
  199.         $paiement $this->em->getRepository(PPaiement::class)->find($request->get('paiement'));
  200.         $observation $request->get('observation');
  201.         $periode $this->calculPaieService->getPeriode();
  202.         if($periode->IsValider()) {
  203.             return new JsonResponse('Periode est valider !'500, [], JSON_UNESCAPED_UNICODE);
  204.         }
  205.         
  206.         $honoraires json_decode($request->get('honoraires'));
  207.         $returnueIR $this->em->getRepository(Prubrique::class)->find(43);
  208.         $divers $this->em->getRepository(Prubrique::class)->find(68);
  209.         $bordoreauIds = [];
  210.         $data=[];
  211.         $count=0;
  212.         // dd($honoraires);
  213.         foreach($honoraires as $key => $dossierKey) {
  214.             $dossier $this->em->getRepository(PDossier::class)->find($key);
  215.             
  216.             // dd($dossier);
  217.             foreach ($dossierKey as $key => $natureKey) {
  218.                 $bordoreau = new PBordereau;
  219.                 $bordoreau->setPiece($this->em->getRepository(PPiece::class)->find(5));
  220.                 $bordoreau->setDevise($devise);
  221.                 $bordoreau->setStatut(
  222.                     $this->em->getRepository(PStatut::class)->find(1)
  223.                 );
  224.                 $bordoreau->setPeriode($periode);
  225.                 $bordoreau->setType('honoraire');
  226.                 $bordoreau->setPaiement($paiement);
  227.                 $bordoreau->setNatureContract($this->em->getRepository(PnatureContract::class)->find($key));
  228.                 $bordoreau->setUserCreated($this->getUser());
  229.                 $bordoreau->setObservation($observation);
  230.                 $bordoreau->setDossier($dossier);
  231.         
  232.                 $this->em->persist($bordoreau);
  233.                 foreach ($natureKey as $key => $honoraire) {
  234.                     // dd($honoraire);
  235.                     $contract=$this->em->getRepository(LContract::class)->find($honoraire->contract_id);
  236.                     $mtChargeInstitutionelle=0;
  237.                     $mtChargeInstitutionelleMad=0;
  238.                     $salaireBrute2 $honoraire->brute;
  239.                     $salaireBrute2Mad $honoraire->brute_mad;
  240.                     $primeComposationIR0;
  241.                     $primeComposationIRMad0;
  242.                     $ir =0;
  243.                     $irMad=0;
  244.                     $pourcentage=($contract->getPnatureContract()->getTauxIr()/ 100);
  245.                     $bulletin = new Tbulletin();
  246.                     $bulletin->setDossier($dossier);
  247.                     $bulletin->setDevise($devise);
  248.                     $bulletin->setPPiece(
  249.                         $this->em->getRepository(PPiece::class)->find(2)
  250.                     );
  251.                     $bulletin->setPaiement($paiement);
  252.                     $bulletin->setObservation($observation);
  253.                     $bulletin->setBordereau($bordoreau);
  254.                     $bulletin->setContract(
  255.                         $this->em->getRepository(LContract::class)->find($honoraire->contract_id)
  256.                     );
  257.                     $bulletin->setPeriode($periode);
  258.                     $activeRib =  $this->em->getRepository(LContract::class)->find($honoraire->contract_id)->getLribs()->filter(function ($rib) {
  259.                            return $rib->isActive();
  260.                        })->first();
  261.                     $bulletin->setRIB($activeRib $activeRib->getCode() : null);
  262.         
  263.                     $this->em->persist($bulletin);
  264.         
  265.                     if($pourcentage != null ) {
  266.                         $chargeInstitutionelle $contract->getPnatureContract()->getAbattement() / 100;
  267.                         
  268.                         $mtChargeInstitutionelleMad=round($honoraire->brute_mad $chargeInstitutionelle2);
  269.                         $mtChargeInstitutionelle=round($honoraire->brute $chargeInstitutionelle2);
  270.                         $salaireBrute2Mad round($honoraire->brute_mad $mtChargeInstitutionelleMad2);
  271.                         $salaireBrute2 =round($honoraire->brute $mtChargeInstitutionelle2);
  272.                         $irMad round$salaireBrute2Mad $pourcentage2);
  273.                         $ir round$salaireBrute2 $pourcentage2);
  274.                         
  275.                         $primeComposationIRMad=round($honoraire->montant_mad-($salaireBrute2Mad $irMad),2);
  276.                         $primeComposationIR=round($honoraire->montant-($salaireBrute2 $ir),2);
  277.                         
  278.                         $bulletinDetChargeInstitutionelle = new TbulletinLg();
  279.                         $bulletinDetChargeInstitutionelle->setBulletin($bulletin);
  280.                         $bulletinDetChargeInstitutionelle->setRubrique($this->em->getRepository(Prubrique::class)->find(97));
  281.                         $bulletinDetChargeInstitutionelle->setSens(-1);
  282.                         $bulletinDetChargeInstitutionelle->setMontant($mtChargeInstitutionelleMad);
  283.                         $bulletinDetChargeInstitutionelle->setMontantDevise($mtChargeInstitutionelle);
  284.             
  285.                         $this->em->persist($bulletinDetChargeInstitutionelle);
  286.                         $bulletinDetPrimeComposationIR = new TbulletinLg();
  287.                         $bulletinDetPrimeComposationIR->setBulletin($bulletin);
  288.                         $bulletinDetPrimeComposationIR->setRubrique($this->em->getRepository(Prubrique::class)->find(98));
  289.                         $bulletinDetPrimeComposationIR->setSens(1);
  290.                         $bulletinDetPrimeComposationIR->setMontant($primeComposationIRMad);
  291.                         $bulletinDetPrimeComposationIR->setMontantDevise($primeComposationIR);
  292.             
  293.                         $this->em->persist($bulletinDetPrimeComposationIR);
  294.                         $bulletinDetRetunueIr = new TbulletinLg();
  295.                         $bulletinDetRetunueIr->setBulletin($bulletin);
  296.                         $bulletinDetRetunueIr->setRubrique($returnueIR);
  297.                         $bulletinDetRetunueIr->setSens(-1);
  298.                         $bulletinDetRetunueIr->setMontant($irMad);
  299.                         $bulletinDetRetunueIr->setMontantDevise($ir);
  300.             
  301.                         $this->em->persist($bulletinDetRetunueIr);
  302.                     }
  303.                     // $netMad=round(($salaireBrute2Mad+$primeComposationIRMad)-$irMad ,2);
  304.                     // $net=round(($salaireBrute2+$primeComposationIR)-$ir ,2);
  305.                     
  306.                     $bulletinDetDivers = new TbulletinLg();
  307.                     $bulletinDetDivers->setBulletin($bulletin);
  308.                     $bulletinDetDivers->setRubrique($divers);
  309.                     $bulletinDetDivers->setSens(1);
  310.                     $bulletinDetDivers->setMontant($honoraire->montant_mad);
  311.                     $bulletinDetDivers->setMontantDevise($honoraire->montant);
  312.                     
  313.                     $this->em->persist($bulletinDetDivers);
  314.                     
  315.                     $bulletinDet = new TbulletinLg();
  316.                     $bulletinDet->setBulletin($bulletin);
  317.                     $bulletinDet->setRubrique($this->em->getRepository(Prubrique::class)->find($honoraire->element_id));
  318.                     $bulletinDet->setSens(1);
  319.                     $bulletinDet->setMontant($honoraire->brute_mad);
  320.                     $bulletinDet->setMontantDevise($honoraire->brute);
  321.                     
  322.                     $this->em->persist($bulletinDet);
  323.                     $bulletinDetBruteImposable = new TbulletinLg();
  324.                     $bulletinDetBruteImposable->setBulletin($bulletin);
  325.                     $bulletinDetBruteImposable->setRubrique($this->em->getRepository(Prubrique::class)->find(95));
  326.                     $bulletinDetBruteImposable->setSens(1);
  327.                     $bulletinDetBruteImposable->setMontant($salaireBrute2Mad);
  328.                     $bulletinDetBruteImposable->setMontantDevise($salaireBrute2);
  329.                     
  330.                     $this->em->persist($bulletinDetBruteImposable);
  331.                     $count++;
  332.                     $data [$count]['dossier']=$dossier->getId();
  333.                     $data [$count]['element']=$honoraire->element_id;
  334.                 }
  335.                 $this->em->flush();
  336.                 array_push($bordoreauIds$bordoreau->getId());
  337.                 
  338.             }          
  339.         }
  340.         
  341.         $data array_unique(array_map('serialize'$data));
  342.         $data array_map('unserialize'$data);
  343.         $data array_values($data);
  344.         // dd($data);
  345.         
  346.         foreach($data as $d){
  347.             $InjectRemuneration = new InjectRemuneration();
  348.             $InjectRemuneration->setDossier$this->em->getRepository(PDossier::class)->find($d["dossier"]));
  349.             $InjectRemuneration->setDevise($devise);
  350.             $InjectRemuneration->setRubrique($this->em->getRepository(Prubrique::class)->find($d["element"]));
  351.             $InjectRemuneration->setPeriode($periode);
  352.             $InjectRemuneration->setActive(1);
  353.             $InjectRemuneration->setType('honoraire');
  354.             $InjectRemuneration->setDesignation($request->get('fileHonoraires'));
  355.     
  356.             $this->em->persist($InjectRemuneration);
  357.         }
  358.       
  359.         $this->em->flush();
  360.         $bordoreauIds array_unique($bordoreauIds);
  361.         if(count($bordoreauIds) > 0) {
  362.             $request->request->add(['bordoreauIds' => json_encode($bordoreauIds)]);
  363.         }
  364.         return new JsonResponse('Bien Enregistrer!');
  365.     }
  366.     #[Route('/app_paie_honoraire_list/{periode}'name'app_paie_honoraire_list'options: ['expose' => true])]
  367.     public function app_paie_honoraire_list(Request $request$periode): Response
  368.     {
  369.        
  370.         $date = new \DateTime($periode);
  371.         $periode $this->calculPaieService->getPeriode($date->format('mY'));
  372.         
  373.         $draw $request->query->get('draw');
  374.         $start $request->query->get('start') ?? 0;
  375.         $length $request->query->get('length') ?? 10;
  376.         $search $request->query->all('search')["value"];
  377.         $orderColumnIndex $request->query->all('order')[0]['column'];
  378.         $orderColumn $request->query->all("columns")[$orderColumnIndex]['name'];
  379.         $orderDir $request->query->all('order')[0]['dir'] ?? 'asc';
  380.         $dossier $request->getSession()->get('dossier');
  381.         $queryBuilder $this->em->createQueryBuilder()
  382.         ->select('b.code as bulletin, b.id as bulletin_id, contract.id as id, contract.code as contract_code, p.nom as nom, p.matricule as matricule , p.prenom')
  383.         ->from(LContract::class, 'contract')
  384.         ->innerJoin('contract.employe''p')
  385.         ->innerJoin('contract.bulletins''b')
  386.         ->innerJoin('b.piece''piece')
  387.         ->Where('contract.dossier = :dossier')
  388.         ->andWhere('b.dossier = :dossier')
  389.         ->andWhere('b.periode = :periode')
  390.         ->andWhere('piece.id = 2')
  391.         ->andWhere('b.active = 1')
  392.         ->setParameter('dossier'$dossier)
  393.         ->setParameter('periode'$periode);
  394.         if (!empty($search)) {
  395.             $queryBuilder->andWhere('(contract.code LIKE :search OR b.code LIKE :search OR p.matricule LIKE :search OR  p.nom LIKE :search OR p.prenom LIKE :search)')
  396.                 ->setParameter('search'"%$search%");
  397.         }
  398.         if (!empty($orderColumn)) {
  399.             $queryBuilder->orderBy("$orderColumn"$orderDir);
  400.         }
  401.         $filteredRecords count($queryBuilder->getQuery()->getResult());
  402.         
  403.         // Paginate results
  404.         $queryBuilder->setFirstResult($start)
  405.             ->setMaxResults($length)
  406.             ->orderBy('b.id''DESC');
  407.         $results $queryBuilder->getQuery()->getResult();
  408.         // dd($results);
  409.         foreach ($results as $key => $contract) {
  410.             // dd('amine');
  411.             // if($contract['id'] == 1301) {
  412.             //     dd($this->em->getRepository(PArretTravailLg::class)->getNombreJoursArret($contract['id'], $periode));
  413.             // }
  414.             $results[$key]['DT_RowId'] = $contract['id'];
  415.             $results[$key]['nombreJourTravails'] = "-";
  416.             $results[$key]['salaire'] = '<p style="text-align: right !important; margin:0 !important">'.number_format($this->em->getRepository(Tbulletin::class)->getNetAPayeByDevise($contract['bulletin_id']), 2',' ' ').'</p>';
  417.             $results[$key]['problemes'] = $this->em->getRepository(Probleme::class)->checkIfTheresProblemes($periode$contract['id']);
  418.         }
  419.         
  420.         // dd($results);
  421.         $totalRecords $this->em->createQueryBuilder()
  422.         ->select('COUNT(d.id)')
  423.         ->from(LContract::class, 'd')
  424.         ->innerJoin('d.bulletins''bulletins')
  425.         ->innerJoin('bulletins.piece''piece')
  426.         ->Where('d.active = 1')
  427.         ->andWhere('bulletins.dossier = :dossier')
  428.         ->andWhere('piece.id = 2')
  429.         ->andWhere('bulletins.periode = :periode')
  430.         ->setParameter('dossier'$dossier)
  431.         ->setParameter('periode'$periode)
  432.         ->getQuery()
  433.         ->getSingleScalarResult();
  434.         return new JsonResponse([
  435.             'draw' => $draw,
  436.             'recordsTotal' => $totalRecords,
  437.             'recordsFiltered' => $filteredRecords,
  438.             'data' => $results,
  439.         ]);
  440.     }
  441.     function hasMoreThanTwoDecimals($number) {
  442.         // Convert the number to a string to handle both integers and floats
  443.         $numberStr strval($number);
  444.     
  445.         // Use a regular expression to check if the number has more than two decimals
  446.         // The pattern matches a dot (decimal point), followed by at most two digits
  447.         return preg_match('/\.\d{3,}/'$numberStr) === 1;
  448.     }
  449.     function searchKeyByKeys($array$key1$value1$key2$value2) {
  450.         foreach ($array as $key => $item) {
  451.             if ($item[$key1] == $value1 && $item[$key2] == $value2) {
  452.                 return $key;
  453.             }
  454.         }
  455.         return null// Return null if not found
  456.     }
  457. }