src/Controller/Api/ProjectController.php line 1224

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api;
  3. use App\Controller\ModulesAccessTypes;
  4. use App\Entity\AccessRoles;
  5. use App\Entity\Administrative;
  6. use App\Entity\Branches;
  7. use App\Entity\Certificates;
  8. use App\Entity\CertificatesGroups;
  9. use App\Entity\Countries;
  10. use App\Entity\Customer;
  11. use App\Entity\CustomerCertificates;
  12. use App\Entity\InvoiceType;
  13. use App\Entity\ProjectAddendumCosts;
  14. use App\Entity\ProjectBranches;
  15. use App\Entity\ProjectExpense;
  16. use App\Entity\ProjectOrderExpensePositions;
  17. use App\Entity\ProjectOrders;
  18. use App\Entity\ProjectOrderUndertakings;
  19. use App\Entity\ProjectOwner;
  20. use App\Entity\Projects;
  21. use App\Entity\ProjectSettings;
  22. use App\Entity\ProjectStakeholders;
  23. use App\Entity\Qualification;
  24. use App\Entity\TimesheetStatus;
  25. use App\Entity\User;
  26. use App\Entity\UserScopedItem;
  27. use App\Entity\WorkerActivities;
  28. use App\Entity\WorkerTimesheet;
  29. use App\Repository\BranchesRepository;
  30. use App\Repository\CertificatesRepository;
  31. use App\Repository\QualificationRepository;
  32. use App\Service\AisDate;
  33. use App\Service\PdfOutputProjectPaymentReport;
  34. use App\Service\PdfOutputTimesheet;
  35. use App\Service\RgbToHex;
  36. use App\Service\SeverityInterface;
  37. use App\Service\StatusCodes;
  38. use App\Service\TimesheetInterface\TimesheetReaderInterface;
  39. use Container69K1BxJ\getMaker_PhpCompatUtilService;
  40. use Doctrine\Common\Collections\ArrayCollection;
  41. use Doctrine\ORM\EntityManagerInterface;
  42. use Monolog\DateTimeImmutable;
  43. use PhpOffice\PhpSpreadsheet\IOFactory;
  44. use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
  45. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  46. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  47. use Symfony\Component\HttpFoundation\JsonResponse;
  48. use Symfony\Component\HttpFoundation\Request;
  49. use Symfony\Component\HttpFoundation\Response;
  50. use Symfony\Component\Routing\Annotation\Route;
  51. use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
  52. use Symfony\Component\Serializer\SerializerInterface;
  53. use Symfony\Contracts\Translation\TranslatorInterface;
  54. use function Doctrine\StaticAnalysis\DBAL\makeMeACustomConnection;
  55. use function Psr\Log\error;
  56. use function Symfony\Bundle\MakerBundle\Util\advanceBeyondMultilineArrayLastItem;
  57. use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
  58. /**
  59.  * @Route("/api/project")
  60. */
  61. class ProjectController extends AbstractController
  62. {
  63.     // ⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
  64.     /**
  65.      * 💡💡💡info 💡💡💡
  66.      * $postedBranches is Core Branch ( not projectBranch Id!!!)
  67.      */
  68.     private function appendBranchToProject(?Projects $projectEntityManagerInterface $manager, array $posted_branch_ids ): Projects {
  69.         // Eğer $posted_branch_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
  70.         if (gettype($posted_branch_ids) === "string") {
  71.             $posted_branch_ids json_decode($posted_branch_idsfalse); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
  72.         }
  73.         // ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
  74.         $posted_branch_ids array_map('intval'$posted_branch_ids);
  75.         // Projenin mevcut branch ilişkilerini al (Doctrine Collection)
  76.         $olderBranches $project->getProjectBranches();
  77.         // Eğer projede daha önce eklenmiş branch'ler varsa
  78.         if ($olderBranches->count()) {
  79.             // Her eski ilişkiyi dön
  80.             foreach ($olderBranches as $olderBranch) {
  81.                 // İlişkili branch'in ID'sini al
  82.                 $olderBranchId $olderBranch->getBranch()->getId();
  83.                 // Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
  84.                 if (!in_array($olderBranchId$posted_branch_idstrue)) {
  85.                     $project->removeProjectBranch($olderBranch); // Doctrine üzerinden ilişkiyi kaldır
  86.                 } else {
  87.                     // Varsa, tekrar eklemeye gerek yok
  88.                     // Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
  89.                     $posted_branch_ids array_diff($posted_branch_ids, [$olderBranchId]);
  90.                 }
  91.             }
  92.         }
  93.         // Yeni eklenecek branch ID'leri kaldıysa
  94.         if ($posted_branch_ids) {
  95.             if (count($posted_branch_ids)) {
  96.                 // Bu ID'lere karşılık gelen Branch objelerini DB'den çek
  97.                 $branches $manager->getRepository(Branches::class)->findBy(["id" => $posted_branch_ids]);
  98.                 // Her yeni branch için ProjectBranches ilişkisi oluştur
  99.                 foreach ($branches as $branch) {
  100.                     $projectBranch = new ProjectBranches(); // Yeni ilişki nesnesi
  101.                     $projectBranch->setBranch($branch);     // Branch ilişkilendirilir
  102.                     // Gerekirse persist edilebilir (Doctrine cascade yoksa)
  103.                     // $manager->persist($projectBranch);
  104.                     $project->addProjectBranch($projectBranch); // İlişki projeye eklenir
  105.                 }
  106.             }
  107.         }
  108.         // Güncellenmiş Project nesnesi geri döndürülür
  109.         return $project;
  110.     }
  111.     private function manageProjectCertificatesProjects $projectEntityManagerInterface $manager, array $posted_certificate_ids = [] ): Projects {
  112.         #dd($posted_certificate_ids);
  113.         // Eğer $posted_certificate_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
  114.         if (gettype($posted_certificate_ids) === "string") {
  115.             $posted_certificate_ids json_decode($posted_certificate_idsfalse); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
  116.         }
  117.         // ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
  118.         $posted_certificate_ids array_map('intval'$posted_certificate_ids);
  119.         #dd($posted_certificate_ids);
  120.         // Projenin mevcut branch ilişkilerini al (Doctrine Collection)
  121.         $olderCertificates $project->getDependentCertificates();
  122.         #dump($posted_certificate_ids);
  123.         // Eğer projede daha önce eklenmiş branch'ler varsa
  124.         if ($olderCertificates->count()) {
  125.             // Her eski ilişkiyi dön
  126.             foreach ($olderCertificates as $olderCertificate) {
  127.                 // İlişkili branch'in ID'sini al
  128.                 $olderCertificateId $olderCertificate->getId();
  129.                 dump($olderCertificateId);
  130.                 // Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
  131.                 if (!in_array($olderCertificateId$posted_certificate_idstrue)) {
  132.                     $project->removeDependentCertificate($olderCertificate); // Doctrine üzerinden ilişkiyi kaldır
  133.                 } else {
  134.                     // Varsa, tekrar eklemeye gerek yok
  135.                     // Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
  136.                     $posted_certificate_ids array_diff($posted_certificate_ids, [$olderCertificateId]);
  137.                 }
  138.             }
  139.         }
  140.         // Yeni eklenecek branch ID'leri kaldıysa
  141.         if ($posted_certificate_ids) {
  142.             if (count($posted_certificate_ids)) {
  143.                 // Bu ID'lere karşılık gelen Branch objelerini DB'den çek
  144.                 $certificates $manager->getRepository(Certificates::class)->findBy(["id" => $posted_certificate_ids]);
  145.                 // Her yeni branch için ProjectBranches ilişkisi oluştur
  146.                 foreach ($certificates as $certificate ) {
  147.                     $project->addDependentCertificate($certificate); // Yeni ilişki nesnesi
  148.                 }
  149.             }
  150.         }
  151.         // Güncellenmiş Project nesnesi geri döndürülür
  152.         return $project;
  153.     }
  154.     private function manageProjectQualificationsProjects $projectEntityManagerInterface $manager, array $posted_qualification_ids = [] ): Projects {
  155.         #dd($posted_qualification_ids);
  156.         // Eğer $posted_qualification_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
  157.         if (gettype($posted_qualification_ids) === "string") {
  158.             $posted_qualification_ids json_decode($posted_qualification_idsfalse); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
  159.         }
  160.         // ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
  161.         $posted_qualification_ids array_map('intval'$posted_qualification_ids);
  162.         #dd($posted_qualification_ids);
  163.         // Projenin mevcut branch ilişkilerini al (Doctrine Collection)
  164.         $olderQualifications $project->getDependentQualifications();
  165.         #dump($posted_qualification_ids);
  166.         // Eğer projede daha önce eklenmiş branch'ler varsa
  167.         if ($olderQualifications->count()) {
  168.             // Her eski ilişkiyi dön
  169.             foreach ($olderQualifications as $olderQualification) {
  170.                 // İlişkili branch'in ID'sini al
  171.                 $olderQualificationId $olderQualification->getId();
  172.                 dump($olderQualificationId);
  173.                 // Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
  174.                 if (!in_array($olderQualificationId$posted_qualification_idstrue)) {
  175.                     $project->removeDependentQualification($olderQualification); // Doctrine üzerinden ilişkiyi kaldır
  176.                 } else {
  177.                     // Varsa, tekrar eklemeye gerek yok
  178.                     // Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
  179.                     $posted_qualification_ids array_diff($posted_qualification_ids, [$olderQualificationId]);
  180.                 }
  181.             }
  182.         }
  183.         // Yeni eklenecek branch ID'leri kaldıysa
  184.         if ($posted_qualification_ids) {
  185.             if (count($posted_qualification_ids)) {
  186.                 // Bu ID'lere karşılık gelen Branch objelerini DB'den çek
  187.                 $qualifications $manager->getRepository(Qualification::class)->findBy(["id" => $posted_qualification_ids]);
  188.                 // Her yeni branch için ProjectBranches ilişkisi oluştur
  189.                 foreach ($qualifications as $qualification ) {
  190.                     $project->addDependentQualification($qualification); // Yeni ilişki nesnesi
  191.                 }
  192.             }
  193.         }
  194.         // Güncellenmiş Project nesnesi geri döndürülür
  195.         return $project;
  196.     }
  197.     /**
  198.      * @param Projects|null $project
  199.      * @param Customer|null $customer
  200.      * @param AisDate $aisDate  
  201.      * @param TranslatorInterface $translator
  202.      * @return array
  203.      * @throws \Exception
  204.      */
  205.     public function coreProjectPrettyStatusData (?Projects $project, ?Customer $customerAisDate $aisDateTranslatorInterface $translator ): array
  206.     {
  207.         $alert[] = [
  208.             "header" => $translator->trans('Suitable!'),
  209.             "severity" => "success"
  210.         ];
  211.         $suitable true;
  212.         // Core Warning's
  213.         // Check Core defined Qualifications
  214.         if (!$project->getDependentQualifications()->count()) {
  215.             $alert[] = [
  216.                 "header" => $project->getName() . " " $translator->trans("is not suitable because the qualifications for this project not defined"),
  217.                 "severity" => "warning"
  218.             ];
  219.         }
  220.         // Check Core defined Certificates
  221.         if (!$project->getDependentCertificates()->count()) {
  222.             $alert[] = [
  223.                 "header" => $project->getName() . " " $translator->trans("is not suitable because the certificates for this project not defined"),
  224.                 "severity" => "warning"
  225.             ];
  226.         }
  227.         $missingCertificates $project->getDependentCertificates()->filter(function (/**@var $dependedCertificate Certificates */ $dependedCertificate) use ($customer) {
  228.             return $dependedCertificate->getCertificateEligibility()->getName() === 'company' && $customer->getCustomerCertificates()->filter(function (/**@var $customerCertificate CustomerCertificates */ $customerCertificate) use ($dependedCertificate) {
  229.                     return $customerCertificate->getCertificate()->getId() === $dependedCertificate->getId();
  230.                 })->count() === 0;
  231.         })->getValues();
  232.         if( count($missingCertificates) ){
  233.             $alert[] = [
  234.                 "header" => $project->getName() . " " $translator->trans('Project for this company is suitable with missing certificates'),
  235.                 "subheader" => (new ArrayCollection($missingCertificates))->map( function( /**@var $missingCertificate Certificates*/$missingCertificate ){
  236.                     return [
  237.                         "header" => "* " $missingCertificate->getName(),
  238.                         "severity" => "info"
  239.                     ];
  240.                 }),
  241.                 "severity" => "info"
  242.             ];
  243.         }
  244.         if ( !$project->getEndAt() ) {
  245.             $alert[] = [
  246.                 "header" => $translator->trans(
  247.                     "'End Date' of Core Project not defined,
  248.                     If any time, you try to define 'End Date' of Core with your confirmation,
  249.                     system can equalize 'End-Date' of Stakeholders with Core!,
  250.                     If you are unsure of the due date, I recommend leaving it blank."),
  251.                 "severity" => "info"
  252.             ];
  253.         }
  254.         // Worker Active in selected stakeholder project
  255.         // By join to project, not by edit!
  256.         if( $customer ){
  257.             $foundedCustomerInProject $customer->getProjectStakeholders()->filter( function(/**@var $projectStakeholder ProjectStakeholders*/ $projectStakeholder ) use ( $project ){
  258.                 return $projectStakeholder->getProject()->getId() === $project->getId() &&
  259.                     ( !$projectStakeholder->getEndAt() || ($projectStakeholder->getEndAt() > new DateTimeImmutable('now')));
  260.             })->first();
  261.             #dd($foundedCustomerInProject);
  262.             if( $foundedCustomerInProject ){
  263.                 $alert = [
  264.                     "header" => $foundedCustomerInProject->getCustomer()->getCompany() . ' ' $translator->trans('already in project!'),
  265.                     "severity" => "info"
  266.                 ];
  267.                 $suitable false;
  268.             }
  269.         }
  270.         if(!is_null($project->getStatus())){
  271.             // Overwrite if completed
  272.             if($project->getStatus()['completed'] ){
  273.                 $alert = [
  274.                     "header" => $translator->trans('Completed!'),
  275.                     "severity" => "info"
  276.                 ];
  277.                 $suitable false;
  278.             }
  279.             // Overwrite if expired
  280.             if ( !$project->getStatus()['completed'] && $project->getEndAt() && $aisDate->date($project->getEndAt())->lowerThan(new \DateTimeImmutable('now'))) {
  281.                 $alert = [
  282.                     "header" => $project->getName() . " " $translator->trans(' has expired'),
  283.                     "severity" => "success"
  284.                 ];
  285.                 $suitable false;
  286.             }
  287.         }
  288.         return [
  289.             "suitable" => $suitable,
  290.             "notifications" => $alert
  291.         ];
  292.     }
  293.     private function serializeProjects( array $projectsSerializerInterface $serializer): array {
  294.         return json_decode$serializer->serialize$projects'json', [
  295.             'groups' => [
  296.                 "project.list.with.necessary.details",
  297.                 "project.details.orders",
  298.                 "project.details"
  299.             ]
  300.         ]));
  301.     }
  302.     private function getUserAccessedProjects(User $userEntityManagerInterface $managerSerializerInterface $serializer): array {
  303.         $allProjects = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
  304.         #dd($user->getUserScopedItems()->toArray());
  305.         $userScopedForProjectList $user->getUserScopedItems()->filter(function(/**@var UserScopedItem $scopedItem */ $scopedItem){
  306.             return $scopedItem->getScopedItem()->getCategory()
  307.                 === ModulesAccessTypes::E_MODULES_SCOPED_CATEGORIES_PROJECT && $scopedItem->getScopedItem()->getType() === ModulesAccessTypes::E_MODULES_SCOPED_TYPES_LIST;
  308.         })->first();
  309.         #dd($userScopedForProjectList->isOnlyOwned());
  310.         #dd($allProjects);
  311.         #dd($userScopedForProjectList);
  312.         $isAdmin = (in_array('ROLE_ADMIN'$user->getRoles()) || in_array('ROLE_SUPER_ADMIN'$user->getRoles()));
  313.         if($userScopedForProjectList) {
  314.             $userScopedForProjectList $userScopedForProjectList->isOnlyOwned();
  315.             if ($userScopedForProjectList) {
  316.                 $filteredProjects $allProjects->filter(function (/**@var Projects $project */ $project) use ($user) {
  317.                     // NEDEN LEAD ICIN YAPIMIS ??? ⚠️ SADECE USER ONLY OWNED MI CONTROLU YETERLI
  318. //                        return $project->getProjectOrders()->exists(function($key, /**@var ProjectOrders $projectOrder*/ $projectOrder) use ($user) {
  319. //                            // Eğer sipariş lideri yoksa, sadece debug için dump
  320. //                            if ($projectOrder->getOrderLead() === null) {
  321. //                                #dump($projectOrder->getProject()->getProjectId());
  322. //                            }
  323. //                            // Sipariş lideri mevcutsa, kullanıcı eşleşmesini kontrol et
  324. //                            $orderLeadUser = null;
  325. //                            if( $projectOrder->getOrderLead() ){
  326. //                                $orderLeadUser = $projectOrder->getOrderLead()->getUser();
  327. //                                if(!is_null($orderLeadUser)){
  328. //                                    if($orderLeadUser->getId() === $user->getId()){
  329. //                                        #dump($orderLeadUser->getId(), $user->getId());
  330. //                                        return true;
  331. //                                    }
  332. //
  333. //                                }
  334. //                            }
  335. //                            return false;
  336. //                        });
  337. //                        // return $project->getProjectOrders()->filter( fn( Projects $project) => true );
  338.                     // return $project->getProjectOrders()->exists( fn(ProjectOrders $projectOrder ) => $projectOrder->getOrderLead()?->getUser()->getId() === $user->getId() );
  339.                     return $project->getProjectOrders()->contains(function (ProjectOrders $projectOrder) use ($user) {
  340.                         return $projectOrder->getOrderLead() && $projectOrder->getOrderLead()->getUser()->getId() === $user->getId() || $projectOrder->getOrderAlternateLeads()->exists(fn(WorkerActivities $workerActivity) => $workerActivity->getUser()->getId() === $user->getId());
  341.                     });
  342.                 });
  343.                 #
  344.                 $filteredProjects $allProjects->filter(function (Projects $project) use ($user$isAdmin) {
  345.                     foreach ($project->getProjectOrders() as /**@var ProjectOrders $projectOrder*/$projectOrder) {
  346.                         // Global Permissions
  347.                         $globalPermission $projectOrder->getOrderPrimaryLead() && $projectOrder->getOrderPrimaryLead()->getWorkerActivitySubstitutions()->exists(
  348.                             fn ( $keyWorkerActivities $_workerActivity) => $_workerActivity->getId() === $this->getUser()->getUserAsWorkerLatestActivity()->getId()
  349.                         );
  350.                         // Order Based Permissions
  351.                         $orderBasedPermission $projectOrder->getOrderAlternateLeads() && $projectOrder->getOrderAlternateLeads()->exists(
  352.                             fn( $keyWorkerActivities $workerActivity ) => $workerActivity->getId() === $this->getUser()->getUserAsWorkerLatestActivity()->getId()
  353.                         );
  354.                         // Scoped (Isolated) item's
  355.                         $scopeIsolated = ($projectOrder->getOrderPrimaryLead() && $projectOrder->getOrderPrimaryLead()->getUser()) && $projectOrder->getOrderPrimaryLead()->getUser()->getId() === $user->getId();
  356.                         return $isAdmin || ($globalPermission || (($orderBasedPermission || $scopeIsolated)));
  357.                     }
  358.                     return false;
  359.                 });
  360.                 $allProjects $filteredProjects;
  361.             }
  362.         }
  363.         #dd();
  364.         #dd($allProjects->count());
  365.         $archived   = [];
  366.         $trashed    = [];
  367.         $active     = [];
  368.         #dd();
  369.         $allProjects->map( function( /**@var Projects $project */$project) use(&$archived, &$trashed, &$active){
  370.             if( !$project->isRecycle()){
  371.                 if($project->isArchived()){
  372.                     $archived[] = $project;
  373.                 } else {
  374.                     $active[] = $project;
  375.                 }
  376.             } else {
  377.                 $trashed[] = $project;
  378.             }
  379.         });
  380.         return [
  381.             "archived" => $this->serializeProjects($archived$serializer),
  382.             "trashed" => $this->serializeProjects($trashed$serializer),
  383.             "active" => $this->serializeProjects($active$serializer),
  384.         ];
  385.     }
  386.     /**
  387.      * @Route("/fetch-projects-for-administrative-customer/{classify}", name="fetch_projects_for_administrative_customer")
  388.      * @param EntityManagerInterface $manager
  389.      * @param SerializerInterface $serializer
  390.      * @param string $classify
  391.      * @return Response
  392.      */
  393.     public function fetchProjectsForAdministrativeCustomerEntityManagerInterface $managerSerializerInterface $serializerstring $classify 'active' ): Response {
  394.             /**@var $user User */
  395.             $user $this->getUser();
  396.             #dd($this->getUser());
  397.             
  398.             $administrative $manager->getRepository(Administrative::class)->findAdministrative();
  399.             // dd($administrative->getPairedCustomer()->getProjectStakeholders()->toArray());
  400.             if(!$administrative){
  401.                 return $this->json([
  402.                     "message" => "No any customer as administrative found!",
  403.                     "severity" => "error"
  404.                 ], Response::HTTP_NOT_FOUND, [], []);
  405.             }
  406.             # $fetchAdministrativeProjects = $manager->getRepository(Projects::class)->fetchAdministrativeProjects($administrative->getPairedCustomer()->getId(), $classify );
  407.             #dd($fetchAdministrativeProjects);
  408.             # $projects = $this->serializeProjects($fetchAdministrativeProjects, $serializer);
  409.         #dd('fetchProjectsForAdministrativeCustomer_12');
  410.         return $this->json([
  411.             # "projects" => $projects,
  412.             #"projects" => $allProjects,
  413.             "disposed" => $this->getUserAccessedProjects$user$manager$serializer ),
  414.             "classify" => $classify
  415.         ], Response::HTTP_OK, [], []);
  416.     }
  417.     /**
  418.      * @Route("/fetch-projects-for-timesheet", name="fetch_projects_for_timesheet")
  419.      * @param EntityManagerInterface $manager
  420.      * @param SerializerInterface $serializer
  421.      * @return JsonResponse
  422.      */
  423.     public function fetchProjectsForTimesheetEntityManagerInterface $managerSerializerInterface $serializer ): Response {
  424.         $administrative $manager->getRepository(Administrative::class)->findAdministrative();
  425.         if(!$administrative){
  426.             return $this->json([
  427.                 "message" => "No any customer as administrative found!",
  428.                 "severity" => "error"
  429.             ], Response::HTTP_NOT_FOUND, [], []);
  430.         }
  431.         
  432.         $projects $manager->getRepository(Projects::class)->findAll();
  433.         $projects json_decode($serializer->serialize($projects'json', [
  434.             'groups' => [
  435.                 'project.details.for.collected.timesheet',
  436.                 'order.base',
  437.                 'project.branches'
  438.             ]
  439.         ]));
  440.         
  441.         return $this->json([
  442.             "projects" => $projects
  443.         ], Response::HTTP_OK, [], []);
  444.     }
  445.     /**
  446.      * @deprecated using from one Component Future will Remove
  447.      * @see fetch-projects-for-administrative-customer
  448.      * nullable customer_id need while check customer status in core projects
  449.      * @Route("/fetch-projects/{customer_id}", name="fetch_weak_list", defaults={"customer_id":null})
  450.      * @ParamConverter("customer", options={"mapping":{"customer_id": "id"}})
  451.      * @param EntityManagerInterface $manager
  452.      * @param SerializerInterface $serializer
  453.      * @return Response
  454.      * Customer Analyse for projects
  455.      */
  456.     public function fetchProjectsEntityManagerInterface $managerSerializerInterface $serializer ): Response
  457.     {
  458.         #dd("fetch-projects");
  459.         $projectsEntity = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
  460.         $projects json_decode$serializer->serialize$projectsEntity'json', [
  461.             'groups' => [
  462.                 "project.selectable.list"
  463.             ]
  464.         ]));
  465.         
  466.         return $this->json([
  467.             "projects" => $projects
  468.         ], Response::HTTP_OK, [], []);
  469.     }
  470.     /**
  471.      * @param Customer|null $customer
  472.      * @param Projects|null $project
  473.      * @param StatusCodes $codes
  474.      * @param SerializerInterface $serializer
  475.      * @param AisDate $aisDate
  476.      * @param TranslatorInterface $translator
  477.      * @param int|null $project_id
  478.      * @return Response
  479.      * @throws \Exception
  480.      * @Route("/core-joinable-project/{customer_slug}/{project_id}", name="core_joinable_project", methods={"POST"}, defaults={"project_id":null})
  481.      * @ParamConverter("project", options={"mapping":{"project_id":"id"}})
  482.      * @ParamConverter("customer", options={"mapping":{"customer_slug":"slug"}})
  483.      */
  484.     public function fetchCoreJoinableProject( ?Customer $customer, ?Projects $projectStatusCodes $codesSerializerInterface $serializerAisDate $aisDateTranslatorInterface $translator, ?int $project_id ): Response{
  485.         if( !$project ){
  486.             return $this->json([
  487.                 'message' => $translator->trans('Project not found!'),
  488.                 "severity" => "error",
  489.                 "variant"=>"snackbar"
  490.             ], Response::HTTP_NOT_FOUND );
  491.         }
  492.         $serializedProject json_decode$serializer->serialize$project'json', [
  493.             'groups' => [
  494.                 'stakeholder.selected.core.project.manage'
  495.             ]
  496.         ]));
  497.         return $this->json([
  498.             "customStatus" => $this->coreProjectPrettyStatusData$project$customer$aisDate$translator ),
  499.             "project" => $serializedProject,
  500.             'updatePath' => $this->generateUrl('customer_join_to_project', ['slug'=>$customer->getSlug()])
  501.         ], Response::HTTP_OK, [], [
  502.             AbstractNormalizer::IGNORED_ATTRIBUTES => [ ]
  503.         ]);
  504.     }
  505.     /**
  506.      * @Route("/save-project/{project_id}", name="save_project", defaults={"project_id": null })
  507.      * @ParamConverter("project", options={"mapping":{"project_id": "id"}})
  508.      * @param Projects|null $project
  509.      * @param EntityManagerInterface $manager
  510.      * @param AisDate $aisDate
  511.      * @param SerializerInterface $serializer
  512.      * @param TranslatorInterface $translator
  513.      * @param Request $request
  514.      * @return Response
  515.      * @throws \Exception
  516.      */
  517.     public function save( ?Projects $projectEntityManagerInterface $managerAisDate $aisDateSerializerInterface $serializerTranslatorInterface $translatorRequest $requestint $project_id null ): Response
  518.     {
  519.         $params $request->request;
  520.        #dd($params);
  521.         // @deprecated this mode use user_rights
  522. //        /**@var $userRole AccessRoles */
  523. //        $userRole =$this->getUser()->getUserAccessedRoles()->filter(function(/**@var $item AccessRoles*/$item){
  524. //            return $item->getAccessType()->getName() === 'Project';
  525. //        })->first();
  526. //
  527. //        /**@var $user User */
  528. //        $user = $this->getUser();
  529. //
  530. //        $userAccess = $user->getUserRights();
  531. //
  532. //
  533. //
  534. //
  535. //        if( !$userRole ){
  536. //            return $this->json([
  537. //                'message' => $translator->trans('Access role required for this operation.'),
  538. //                "severity" => "error",
  539. //                "variant"=>"snackbar"
  540. //            ], Response::HTTP_NOT_ACCEPTABLE );
  541. //        }
  542.         try{
  543.             if( $project_id && !$project ){
  544.                 return $this->json([
  545.                     "message" => $translator->trans('Project not found!') ,
  546.                     "severity"=>"warning"
  547.                 ], Response::HTTP_NOT_FOUND);
  548.             }
  549.             if( !$project ){
  550.                 // Check same ID already created
  551.                 $projectIdFound $manager->getRepositoryProjects::class )->findOneBy(['project_id' => $params->get('project_id')]);
  552.                 if($projectIdFound){
  553.                     return $this->json([
  554.                         "message" => $params->get('project_id') . ' ' $translator->trans(', Project-ID already added, please try another one!') ,
  555.                         "severity"=>"warning"
  556.                     ], Response::HTTP_UNAUTHORIZED);
  557.                 }
  558.                 $project = new Projects();
  559.                 $project
  560.                     ->setProjectId$params->get('project_id'))
  561.                     ->setCreatedAt( new \DateTimeImmutable('now'));
  562.             }
  563.             $project->setProjectId($params->get('project_id'));
  564.             /**@var $countryEntity Countries*/
  565.             $countryEntity null;
  566.             if( intval($params->get('country')) ){
  567.                 $countryEntity $manager->getRepository(Countries::class)->find($params->get('country'));
  568.             }
  569.             $project
  570.                 ->setName$params->get('name') )
  571.                 ->setStartAt( new \DateTimeImmutable($params->get('start_at')))
  572.                 ->setEndAt$params->get('end_at') ? new \DateTimeImmutable($params->get('end_at')) : null )
  573.                 // ->setCost(floatval($params->get('cost')) ? $params->get('cost') : null )
  574.                 //                // ->setLongitude($params->get('longitude'))
  575.                 //                // ->setLatitude($params->get('latitude'))
  576.                 //                // ->setScanDistance(intval($params->get('scan_distance')) ? $params->get('scan_distance') : null )
  577.                 //                ->setRewardTime(intval($params->get('reward_time')) ? $params->get('reward_time') : null )
  578.                                 // ->setWorkPause( intval($params->get('work_pause')) ? $params->get('work_pause') : null )
  579.                                 // ->setWorkingTimeStart($params->get('working_time_start'))
  580.                                 // ->setWorkingTimeStop($params->get('working_time_stop'))
  581.                                 // ->setAddress($params->get('address'))
  582.                                 // ->setCodePostal($params->get('code_postal'))
  583.                 ->setTown($params->get('town'))
  584.                 ->setCountry$countryEntity )
  585.             ;
  586.             if(!empty($params->get('invoice_type'))){
  587.                 $invoice_type $manager->getRepository(InvoiceType::class)->find($params->get('invoice_type'));
  588.                 $project->setInvoiceType($invoice_type);
  589.             }
  590.             $projectSettings $project->getProjectSettings();
  591.             $target_profit intval($params->get('target_profit')) ?? 0;
  592.             $material_budget intval($params->get('material_budget')) ?? 0;
  593.             if( !$projectSettings ){
  594.                 $projectSettings = new ProjectSettings();
  595.             }
  596.             $projectSettings
  597.                 ->setTargetProfit($target_profit)
  598.                 ->setMaterialBudget($material_budget)
  599.                 ->setTimesheetBudget(100 - ($target_profit $material_budget));
  600.             $project->setProjectSetting($projectSettings);
  601.             if( !empty($params->get('owner'))){
  602.                 $owner $manager->getRepository(ProjectOwner::class)->find($params->get('owner'));
  603.                 $project->setOwner($owner);
  604.             }
  605.             $collectionRequiresErrors = [];
  606.             if($params->get('project_branches') === null) {
  607.                 $collectionRequiresErrors[] = [
  608.                     'message' => $translator->trans('At least one branch is required.'),
  609.                     'severity' => SeverityInterface::WARNING
  610.                 ];
  611.             }
  612.             if($params->get('dependent_qualifications') === null) {
  613.                 $collectionRequiresErrors[] = [
  614.                     'message' => $translator->trans('At least one qualification is required.'),
  615.                     'severity' => SeverityInterface::WARNING
  616.                 ];
  617.             }
  618.             if($params->get('dependent_certificates') === null) {
  619.                 $collectionRequiresErrors[] = [
  620.                     'message' => $translator->trans('At least one certificate is required.'),
  621.                     'severity' => SeverityInterface::WARNING
  622.                 ];
  623.             }
  624.             if(count($collectionRequiresErrors)){
  625.                 return $this->json([
  626.                     'errors' => $collectionRequiresErrors
  627.                 ], Response::HTTP_NOT_ACCEPTABLE);
  628.             }
  629.             $project $this->manageProjectQualifications($project$manager$params->get('dependent_qualifications') );
  630.             $project $this->manageProjectCertificates($project$manager$params->get('dependent_certificates') );
  631.             $this->appendBranchToProject$project$manager, (array)$params->get('project_branches') );
  632.             $manager->persist$project );
  633.             $manager->flush();
  634.             $manager->refresh($project);
  635.         } catch (\Exception $exception) {
  636.             return $this->json([
  637.                 'message' => 'Error by core project save ' $exception->getMessage()
  638.             ], Response::HTTP_UNAUTHORIZED);
  639.         }
  640.         $project_ json_decode($serializer->serialize$project'json', [
  641.             'groups' => [
  642.                 'project.base',
  643.                 'project.branches',
  644.                 'project.expenses',
  645.                 'project.owner',
  646.                 'project.qualifications',
  647.                 'project.certificates',
  648.                 'project.orders',
  649.                 "project.details.orders"
  650.             ]
  651.         ]), true );
  652.         return $this->json([
  653.             "message"=>$translator->trans('Project added successfully'),
  654.             "severity" => "success",
  655.             "project" => $project_,
  656.             "classify" => $params->get('classify')
  657.         ], Response::HTTP_OK, [], [
  658.             AbstractNormalizer::IGNORED_ATTRIBUTES => []
  659.         ] );
  660.     }
  661.     /**
  662.      * @Route("/save-partial-append-branches-to-project/{project_id}", name="save_partial_append_branches_to_project", defaults={"project_id": null })
  663.      * @ParamConverter("project", options={"mapping":{"project_id": "id"}})
  664.      * @param Projects|null $project
  665.      * @param EntityManagerInterface $manager
  666.      * @param AisDate $aisDate
  667.      * @param SerializerInterface $serializer
  668.      * @param TranslatorInterface $translator
  669.      * @param Request $request
  670.      * @return Response
  671.      * @throws \Exception
  672.      */
  673.     public function savePartialAppendBranches( ?Projects $projectEntityManagerInterface $managerSerializerInterface $serializerTranslatorInterface $translatorRequest $requestint $project_id null ): Response{
  674.         $params $request->request;
  675.         #dd($params->all());
  676.         $project $this->appendBranchToProject$project$manager, (array)$params->get('project_branches') );
  677.         $manager->persist$project );
  678.         $manager->flush();
  679.         $manager->refresh($project);
  680.         $project_ json_decode($serializer->serialize$project'json', [
  681.             'groups' => [
  682.                 'project.base',
  683.                 'project.branches',
  684.                 'project.expenses',
  685.                 'project.owner',
  686.                 'project.qualifications',
  687.                 'project.certificates',
  688.                 'project.orders'
  689.             ]
  690.         ]), true );
  691.         return $this->json([
  692.             "message"=>$translator->trans('Project added successfully'),
  693.             "severity" => "success",
  694.             "project" => $project_
  695.         ], Response::HTTP_OK, [], [
  696.             AbstractNormalizer::IGNORED_ATTRIBUTES => []
  697.         ] );
  698.     }
  699.     /**
  700.      * @Route("/fetch/{project_id}", name="project_fetch", defaults={"project_id": null}, methods={"POST", "GET"})
  701.      * @ParamConverter("project", options={"mapping":{"project_id": "id"}})
  702.      * @param Projects|null $project
  703.      * @param EntityManagerInterface $manager
  704.      * @param SerializerInterface $serializer
  705.      * @return Response
  706.      */
  707.     public function fetch( ?Projects $projectEntityManagerInterface $managerSerializerInterface $serializer ): Response
  708.     {
  709.         #dd(12);
  710.         /*return $this->json([
  711.             "message"=>"Error",
  712.             "severity" => "error"
  713.         ], Response::HTTP_NOT_FOUND, [], [
  714.             AbstractNormalizer::IGNORED_ATTRIBUTES => []
  715.         ] );*/
  716.         // dd($project->getProjectBranches()->toArray());
  717.         $countries $manager->getRepository(Countries::class)->findAll();
  718.         /**@var $qualificationsRepo QualificationRepository*/
  719.         $qualificationsRepo $manager->getRepository(Qualification::class);
  720.         $qualifications $qualificationsRepo->fetchWeak(); // All
  721.         /**@var $certificatesRepo CertificatesRepository*/
  722.         $certificatesRepo $manager->getRepository(Certificates::class);
  723.         $certificates $certificatesRepo->fetchWeakByName(); // All
  724.         /**@var $certificateGroupsRepo CertificatesGroups*/
  725.         $certificateGroups $manager->getRepository(CertificatesGroups::class)->findAll();
  726.         /**@var $projectBranchesRepo BranchesRepository */
  727.         $projectBranchesRepo $manager->getRepository(Branches::class);
  728.         $branches $projectBranchesRepo->findAll(); // All
  729.         /**@var $projectOwners ProjectOwner*/
  730.         $projectOwnersRepo $manager->getRepository(ProjectOwner::class);
  731.         $projectOwners $projectOwnersRepo->findAll(); // All
  732.         /**@var $projectOwners ProjectOwner*/
  733.         $invoiceTypesRepo $manager->getRepository(InvoiceType::class);
  734.         $invoiceTypes $invoiceTypesRepo->findAll(); // All
  735.         $project_ $serializer->serialize$project'json', [
  736.             'groups' => [
  737.                 'project.base',
  738.                 'project.branches',
  739.                 'project.expenses',
  740.                 'project.owner',
  741.                 'project.qualifications',
  742.                 'project.certificates',
  743.                 'project.settings',
  744.                 'project.setting.core',
  745.                 
  746.                 
  747.                 'project.orders',
  748.                 "project.details.orders",
  749.                 // "project.details.orders.expenses",
  750.                 // "project.orders.expense.base",
  751.                 "project.orders.expense.positions",
  752.                 "project.orders.expense.position.base",
  753.                 "project_order@stock_issues",
  754.                 "stock_issue@core",
  755.             ]
  756.         ]);
  757.         $countries_ $serializer->serialize$countries'json', [ 'groups' => ['countries.base']]);
  758.         $branches_ $serializer->serialize$branches'json', ['groups' => ['branches.base''branches.location.base']]);
  759.         $project_owners $serializer->serialize$projectOwners'json', ['groups' => ['project.owner']]);
  760.         $invoice_types $serializer->serialize$invoiceTypes'json', ['groups' => ['invoice.type.base']]);
  761.         $certificate_groups $serializer->serialize$certificateGroups'json', ['groups' => ['certificate.group.base']]);
  762.         $certificate_groups json_decode($certificate_groupstrue);
  763.         $project json_decode$project_ );
  764.         $countries json_decode$countries_ );
  765.         $branches json_decode$branches_ );
  766.         $project_owners json_decode$project_owners );
  767.         $invoice_types json_decode$invoice_types );
  768.         #dd($project);
  769.         #dd($project);
  770.         return $this->json([
  771.             "certificates"=>$certificates,
  772.             "certificate_groups" => $certificate_groups,
  773.             "qualifications"=>$qualifications,
  774.             'project'=>$project,
  775.             'countries'=>$countries,
  776.             'branches_collection' => $branches,
  777.             'project_owners' => $project_owners,
  778.             'invoice_types' => $invoice_types
  779.         ], Response::HTTP_OK );
  780.     }
  781.     /**
  782.      * @deprecated
  783.      * info for Stakeholder not more Use fetch direct Project!
  784.      * @Route("/project-stakeholder-timesheet-pdf-as-project-wait-for-check/{project_stakeholder_id}", name="project_stakeholder_timesheet_pdf_as_project_wait_for_check", methods={"POST", "GET"})
  785.      * @param Request $request
  786.      * @param RgbToHex $rgbToHex
  787.      * @param EntityManagerInterface $manager
  788.      * @param TimesheetReaderInterface $timesheetReader
  789.      * @param ProjectStakeholders|null $projectStakeholder
  790.      * @param SerializerInterface $serializer
  791.      * @param PdfOutputTimesheet $pdfOutputTimesheet
  792.      * @param StatusCodes $codes
  793.      * @param TranslatorInterface $translator
  794.      * @param int $project_stakeholder_id
  795.      * @return Response
  796.      * @ParamConverter("projectStakeholder", options={"mapping":{"project_stakeholder_id":"id"}})
  797.      */
  798.     public function _wait_for_check_stakeholderTimesheet(Request $requestRgbToHex $rgbToHexEntityManagerInterface $managerTimesheetReaderInterface $timesheetReader, ?ProjectStakeholders $projectStakeholderSerializerInterface $serializerPdfOutputTimesheet $pdfOutputTimesheetStatusCodes $codesTranslatorInterface $translatorint $project_stakeholder_id ): Response
  799.     {
  800.         $timesheets null;
  801.         $years $request->request->get('years');
  802.         $is_guest $request->request->get('is_guest');
  803.         $projectJoinedEmployees $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest$projectStakeholder){
  804. //            if( $is_guest !== "true" ){
  805. //                return $stakeholder->getId() === $projectStakeholder->getId();
  806. //            }
  807.             return $stakeholder;
  808.         })->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest$projectStakeholder ){
  809.             return $stakeholder->getWorkerInProjects()->getValues();
  810.         });
  811.         $serializedWorkersInProject json_decode($serializer->serialize$projectJoinedEmployees 'json', [
  812.             'groups' => [
  813.                 'timesheet.for.stakeholder'
  814.             ],
  815.             AbstractNormalizer::IGNORED_ATTRIBUTES => [
  816.                 // 'worker_timesheets'
  817.             ]
  818.         ]) , true );
  819.         #dd($serializedWorkersInProject);
  820.         $serializedWorkersInProject call_user_func_array('array_merge'$serializedWorkersInProject);
  821.         /// Filtered For Current Project
  822.         $collection = new ArrayCollection($serializedWorkersInProject);
  823.         $accessedYears  = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
  824.         if( $years ) {
  825.             $accessedYears  json_decode($years); // <-- Should as param
  826.         }
  827.         // Overwrite for another process
  828.         $years = [];
  829.         $timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
  830.             // Manipulate color to Hex
  831.             $item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
  832.             return $item;
  833.         });
  834.         // Initial Values
  835.         $timesheetReader
  836.             ->setTimesheetStatusCollection($timesheetStatus)
  837.             // ->setProjectStakeholders( $projectStakeholder );
  838.             ->readerPathManager$projectStakeholder->getProject(), nullnull );
  839.         #dd($collection);
  840.         array_map(function( $accessedYear ) use ( &$years$is_guest$collection$timesheetReader$timesheetStatus, &$final_times, &$final_costs ){
  841.             $yearly_times = [];
  842.             $yearly_costs = [];
  843.             $final_month_times = [];
  844.             $final_costs = [];
  845.             #dd($collection);
  846.             // Done Empty Workers for current year
  847.             $workers = [];
  848.             // Project Stakeholder workers Collection Loop
  849.             $collection->filter(function($workerActivity) use ($is_guest){
  850.                 return $workerActivity// $workerActivity['worker_activity']['guest'] === "1" && $is_guest === "true";
  851.             })->map(function($workerActivity) use (
  852.                 &$yearly,
  853.                 &$workers,
  854.                 $accessedYear,
  855.                 $timesheetReader,
  856.                 $timesheetStatus,
  857.                 &$yearly_times,
  858.                 &$yearly_costs,
  859.                 &$final_month_times,
  860.                 &$final_costs
  861.             ){
  862.                 $_worker = [
  863.                     "id" => $workerActivity['worker_activity']["id"],
  864.                     "name" => $workerActivity['worker_activity']['worker']["name"],
  865.                     "surname" => $workerActivity['worker_activity']['worker']["surname"],
  866.                     "customer" => $workerActivity['worker_activity']['customer']["company"],
  867.                     "guest" => $workerActivity['worker_activity']['guest']
  868.                 ];
  869.                 // Worker Timesheet Source
  870.                 $foundedYear array_filter$workerActivity['worker_activity']['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
  871.                     return $timesheetForYear['year'] === $accessedYear;
  872.                 });
  873.                 // Update Worker Element with timesheet
  874.                 // try{
  875.                 if( $foundedYear ){
  876.                     $foundedYear array_values($foundedYear);
  877.                     $foundedYear $foundedYear[0];
  878.                     $pattern '/^m\d+_d\d+?$/';
  879.                     $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  880.                         return preg_match($pattern$item);
  881.                     });
  882.                     $activeColumns array_values($activeColumns);
  883.                     try{
  884.                         foreach ($foundedYear as $key => $item ) {
  885.                             if( !in_array($key$activeColumns) ){
  886.                                 unset($foundedYear[$key]);
  887.                             }
  888.                         }
  889.                     }catch (\Exception $exception ){
  890.                         dd($exception->getMessage());
  891.                     }
  892.                     $months $monthsFinal = [];
  893.                     // Loop Months
  894.                     foreach ( range(112) as $monthIndex ) {
  895.                         $timesheetReader->setMonth($monthIndex);
  896.                         $workerMonthTimeCollection $workerMonthCostCollection $workerMonthInactiveTimeCollection $workerMonthInactiveCostCollection = [];
  897.                         $pattern '/m' $monthIndex '_d\d/';
  898.                         // Get days of current month
  899.                         $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  900.                             return preg_match($pattern$item);
  901.                         });
  902.                         foreach ( $activeColumns as $dayKey ) {
  903.                             $timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
  904.                             // $readData = $timesheetReader->readTimeExtend();
  905.                             #dump($foundedYear[$dayKey]);
  906.                             $readData $timesheetReader->readTimeExtendRolesBasic();
  907.                             #dump($readData);
  908.                             if( array_key_exists($timesheetReader::KEY_TIME_PROP$readData )){
  909.                                 switch ($readData[$timesheetReader::KEY_COST_TYPE]){
  910.                                     case $timesheetReader::KEY_COST_TYPE_ACTIVE:
  911.                                         $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  912.                                         $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
  913.                                         break;
  914.                                     case $timesheetReader::KEY_COST_TYPE_INACTIVE:
  915.                                         $workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  916.                                         $workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
  917.                                         break;
  918.                                 }
  919.                             }
  920.                         }
  921.                         // Employee month
  922.                         $months[$monthIndex] = [
  923.                             "times" => array_sum($workerMonthTimeCollection),
  924.                             "costs" => array_sum($workerMonthCostCollection),
  925.                         ];
  926.                         // Inactive Times
  927.                         $monthsFinal[$monthIndex] = [
  928.                             "times" => array_sum(array_merge($workerMonthInactiveTimeCollection$workerMonthTimeCollection)),
  929.                             "costs" => array_sum(array_merge($workerMonthInactiveCostCollection$workerMonthInactiveCostCollection)),
  930.                         ];
  931.                         // Final month
  932.                         // $final_month_times[$monthIndex][] =
  933.                     }
  934.                     $_worker["months"] = $months;
  935.                     $_worker["months_final"] = $monthsFinal;
  936.                     $_worker["yearTimes"] = array_sum(array_map( function ( $month ){
  937.                         return floatval($month['times']);
  938.                     }, $months ));
  939.                     $_worker["yearCosts"] = array_sum(array_map( function ( $month ){
  940.                         return floatval($month['costs']);
  941.                     }, $months ));
  942.                     $yearly_times[] = $_worker["yearTimes"];
  943.                     $yearly_costs[] = $_worker["yearCosts"];
  944.                     $workers[] = $_worker;
  945.                 }
  946.             });
  947.             dump(array_sum($yearly_times));
  948.             // Append created worker to accessed year
  949.             $years[$accessedYear]['workers'] = $workers;
  950.             $years[$accessedYear]['times'] = array_sum($yearly_times);
  951.             $years[$accessedYear]['costs'] = array_sum($yearly_costs);
  952.             if($yearly_times ){
  953.                 dump($years);
  954.             }
  955.         }, $accessedYears );
  956.         #dd(array_sum(array_map(function($item){ return $item['times']; }, $years )));
  957.         #dump($final_times);
  958.         #dump($final_costs);
  959.         #dd();
  960.         #dd($is_guest);
  961.         # dd($years);
  962.         try{
  963.             $output null;
  964.             $pdfOutputTimesheet->setPrintedBy$this->getUser()->getEmail());
  965.             $output $pdfOutputTimesheet->stakeholderTimesheet(
  966.                 $translator->trans('Timesheet') . ' ' $projectStakeholder->getProject()->getName() . ' ' $projectStakeholder->getCustomer()->getCompany(),
  967.                 $projectStakeholder->getCustomer()->getCompany() . ' in ' $projectStakeholder->getProject()->getName(),
  968.                 $years,
  969.                 array_sum(array_map(function($item){ return $item['times']; }, $years )),
  970.                 array_sum(array_map(function($item){ return $item['costs']; }, $years )),
  971.                 'F'
  972.             );
  973.             if( $output->code !== Response::HTTP_OK ){
  974.                 return $this->json([
  975.                     'message' => $output->message,
  976.                     "severity" => "error"
  977.                 ], Response::HTTP_CONFLICT );
  978.             }
  979.         } catch (\Exception $exception){
  980.             return $this->json([
  981.                 'message' => $exception->getMessage(),
  982.                 "severity" => "error"
  983.             ], Response::HTTP_CONFLICT );
  984.         }
  985.         return $this->json([
  986.             'message' => $translator->trans('Timesheet created successfully!'),
  987.             "severity" => "success",
  988.             'output'=>$output
  989.         ]);
  990.     }
  991.     private function chartValueGetter$value$useOnePercent false ){
  992.         return is_numeric($value) ? ($useOnePercent $value 100 $value) : 0;
  993.     }
  994.     /**
  995.      * @Route("/evaluate-profit-margin/{project_id}", name="app_project_evaluate_profit_margin", defaults={"project_id"=null})
  996.      * @ParamConverter("project", options={"mapping":{"project_id": "id"}})
  997.     */
  998.     public function evaluateProfitMargin(?Projects $projectTranslatorInterface $translator): Response {
  999.         $netRevenues       = [];
  1000.         $netProfitMargins   = [];
  1001.         $netExpenses       = [];
  1002.         $netHoursCostSpent = [];
  1003.         $netHoursSpent     = [];
  1004.         $netProfit          = [];
  1005.         $chartGroups        = [];
  1006.         $chartGroupColors   = [];
  1007.         // Chart Groups Data
  1008.         // Worked Times Data of all Contructions Managers
  1009.         $chartGroupsData[] = ["data" => []]; // Spent Times
  1010.         $chartGroupsData[] = ["data" => []]; // Revenue
  1011.         $chartGroupsData[] = ["data" => []]; // Expenses
  1012.         $chartGroupsData[] = ["data" => []]; // Cost Spent
  1013.         $chartGroupsData[] = ["data" => []]; // Profit
  1014.         $chartGroupsDataset = []; // Spent Times
  1015.         $profitMargins = [];
  1016.         if( !$project ){
  1017.             return $this->json([
  1018.                 'message' => $translator->trans('Project not found!'),
  1019.                 "severity" => "warning"
  1020.             ], Response::HTTP_CONFLICT );
  1021.         }
  1022.         // Calculate
  1023.         try{
  1024.             $project->getProjectOrders()->map(function (/**@var ProjectOrders $projectOrder*/$projectOrder) use (
  1025.                 &$profitMargins,
  1026.                 &$netRevenues,
  1027.                 &$netExpenses,
  1028.                 &$netHoursCostSpent,
  1029.                 &$netHoursSpent,
  1030.                 &$chartGroups,
  1031.                 &$chartGroupColors,
  1032.                 &$chartGroupsData,
  1033.                 $project,
  1034.                 &$chartGroupsDataset,
  1035.                 $translator
  1036.             ){
  1037.                 $defaultAverageProfitMargin 20;
  1038.                 $profitMargin $projectOrder->getTargetProfitAsPercent() ?? $defaultAverageProfitMargin;
  1039.                 $profitMargins[] = $profitMargin;
  1040.                 if(is_null($profitMargin)){
  1041.                     dump("Profit margin is null for {$projectOrder->getId()}");
  1042.                 }
  1043.                 else if ( $profitMargin <> 20 ) {
  1044.                     dump("Profit margin of order {$projectOrder->getId()} {$profitMargin}");
  1045.                 }
  1046.                 $netRevenues[] = $projectOrder->getOrderPrise();
  1047.                 $projectOrder->getProjectOrderExpensePositions()
  1048.                     ->filter(function(/**@var ProjectOrderExpensePositions $expensePosition */$expensePosition){
  1049.                         return !is_null($expensePosition->getAmount());
  1050.                     })->map(function(/**@var ProjectOrderExpensePositions $expensePosition */$expensePosition) use (&$netExpenses){
  1051.                         // return $expensePosition->getAmount() ? floatval($expensePosition->getAmount()) : 0;
  1052.                         $netExpenses[] = $expensePosition->getAmount() ? floatval($expensePosition->getAmount()) : 0;
  1053.                     });
  1054.                 $netHoursSpent[] = $projectOrder->getHoursSpent();
  1055.                 $netHoursCostSpent[] = $projectOrder->getCostSpent();
  1056.                 // Chart Grouplarini belirle
  1057.                 $foundedOrderLead array_filter($chartGroups, function(/**@var User $user*/$user) use($projectOrder) {
  1058.                     return $projectOrder->getOrderLead() && $user
  1059.                         && $user->getId() === $projectOrder->getOrderLead()->getId();
  1060.                 });
  1061.                 if(!$foundedOrderLead){
  1062.                     $chartGroups[] = $projectOrder->getOrderLead();
  1063.                     $r rand(100255); // 100-255
  1064.                     $g rand(100255); // 100-255
  1065.                     $b rand(100255); // 100-255
  1066.                     $chartGroupColors[] = "rgb({$r}{$g}{$b})";
  1067.                     // Chart Group Data yi olustur order lead a ait
  1068.                     $_hoursSpent = [];
  1069.                     $_workedCostSpent = [];
  1070.                     $_revenues = [];
  1071.                     $_expenses = [];
  1072.                     $project->getProjectOrders()
  1073.                         ->filter(function(/**@var ProjectOrders $_projectOrder*/$_projectOrder) use ($projectOrder) {
  1074.                             return $projectOrder->getOrderLead() && (!$_projectOrder->getOrderLead() || $_projectOrder->getOrderLead()->getId()
  1075.                                 === $projectOrder->getOrderLead()->getId());
  1076.                         })
  1077.                         ->map(function(/**@var ProjectOrders $_projectOrder*/$_projectOrder) use (
  1078.                             &$_hoursSpent,
  1079.                             &$_workedCostSpent,
  1080.                             &$_revenues,
  1081.                             &$_expenses
  1082.                         )
  1083.                         {
  1084.                             $__expense_pos_amounts $_projectOrder->getProjectOrderExpensePositions()
  1085.                                 ->map(function (/**@var ProjectOrderExpensePositions $expensePosition*/ $expensePosition ){
  1086.                                     return !is_null($expensePosition->getAmount()) ? floatval($expensePosition->getAmount() ) : 0;
  1087.                                 })->toArray();
  1088.                             // Total Expenses for Lead assigned orders
  1089.                             $__expenses array_reduce$__expense_pos_amounts , function($carry$item){
  1090.                                 return $carry $item;
  1091.                             }, );
  1092.                             $_workedCostSpent[] = $_projectOrder->getCostSpent();
  1093.                             $_hoursSpent[] = $_projectOrder->getHoursSpent();
  1094.                             $_revenues[] = $_projectOrder->getOrderPrise();
  1095.                             $_expenses[] = $__expenses;
  1096.                         }) ;
  1097.                     $_chartGroupsDataHoursSpent array_reduce($_hoursSpent, function($carry$item){
  1098.                         return $carry $item;
  1099.                     }, );
  1100.                     $_chartGroupsDataRevenue array_reduce($_revenues, function($carry$item){
  1101.                         return $carry $item;
  1102.                     }, );
  1103.                     $_chartGroupsDataExpense array_reduce($_expenses, function($carry$item){
  1104.                         return $carry $item;
  1105.                     }, );
  1106.                     $_chartGroupsDataWorkedCost array_reduce($_workedCostSpent, function($carry$item){
  1107.                         return $carry $item;
  1108.                     }, );
  1109.                     $_profit $_chartGroupsDataRevenue - ( $_chartGroupsDataExpense $_chartGroupsDataWorkedCost);
  1110.                     $chartGroupsData[0]["data"][] = is_numeric($_chartGroupsDataHoursSpent) ? $_chartGroupsDataHoursSpent 0;
  1111.                     $chartGroupsData[1]["data"][] = is_numeric($_chartGroupsDataRevenue) ? $_chartGroupsDataRevenue 100 0;
  1112.                     $chartGroupsData[2]["data"][] = is_numeric($_chartGroupsDataExpense) ? $_chartGroupsDataExpense 100 0;
  1113.                     $chartGroupsData[3]["data"][] = is_numeric($_chartGroupsDataWorkedCost) ? $_chartGroupsDataWorkedCost 100 0;
  1114.                     $chartGroupsData[4]["data"][] = is_numeric($_profit) ? $_profit 100 0;
  1115.                     #dd($projectOrder->getOrderLead());
  1116. //                    $scoped = $this->getUser()->getUserScopedItems()->filter(function(/**@var $scopedItem UserScopedItem*/$scopedItem){
  1117. //                        return $scopedItem->getAccessFor() === 'project_chart';
  1118. //                    })->first();
  1119.                     /**@var $user User*/
  1120.                     $user $this->getUser();
  1121.                     $scoped $user->getUserScopedItems()->filter(function(/**@var $scopedItem UserScopedItem*/$scopedItem){
  1122.                         return $scopedItem->getScopedItem()->getCategory() === ModulesAccessTypes::E_MODULES_SCOPED_CATEGORIES_PROJECT && $scopedItem->getScopedItem()->getType() === ModulesAccessTypes::E_MODULES_SCOPED_TYPES_CHART;
  1123.                     })->first();
  1124.                     $onlyOwned $scoped && $scoped->isOnlyOwned();
  1125.                     $ownedData null;
  1126.                     try{
  1127.                         if(!is_null($projectOrder->getOrderLead())){
  1128.                             if( !is_null($projectOrder->getOrderLead()->getUser()) ){
  1129.                                 $ownedData $this->getUser()->getId() === $projectOrder->getOrderLead()->getUser()->getId();
  1130.                             }
  1131.                         }
  1132.                     } catch (\Exception $e) {
  1133.                     }
  1134.                     // $ownedData = true;
  1135. //                    $chartGroupsDataset[] = [
  1136. //                        'timesheet' => is_numeric($_chartGroupsDataHoursSpent) ? $_chartGroupsDataHoursSpent : 0,
  1137. //                        'revenue' => is_numeric($_chartGroupsDataRevenue) ? $_chartGroupsDataRevenue / 100 : 0,
  1138. //                        'expenses' => is_numeric($_chartGroupsDataExpense) ? $_chartGroupsDataExpense / 100 : 0,
  1139. //                        'employee_cost' => is_numeric($_chartGroupsDataWorkedCost) ? $_chartGroupsDataWorkedCost / 100 : 0,
  1140. //                        'profit' => is_numeric($_profit) ? $_profit / 100 : 0,
  1141. //                        // 'owner' => substr($projectOrder->getOrderLead()->getName(), 0 ,1 ) . '. ' . $projectOrder->getOrderLead()->getSurname(),
  1142. //                        'owner' => $projectOrder->getOrderLead()->getName() . ' ' . $projectOrder->getOrderLead()->getSurname(),
  1143. //                        // 'ownerId' => $projectOrder->getOrderLead()->getId()
  1144. //                        // 'isLocked' => $scoped ? ($scoped->isOnlyOwned() ? true : $this->getUser()->getId() !== $projectOrder->getOrderLead()->getUser()->getId() : false ) : false  //$this->getUser()->getId() !== $projectOrder->getOrderLead()->getUser()->getId() // $scoped && ( && !($scoped->isOnlyOwned()))// : $this->getUser()->getId() !== $projectOrder->getOrderLead()->getUser()->getId() //&& ($scoped && $scoped->isOnlyOwned())
  1145. //                        'isLocked' => $ownedData ? false : $onlyOwned,
  1146. //                        'ownedData' => $ownedData,
  1147. //                        'onlyOwned' => $onlyOwned,
  1148. //                        'userId' => $this->getUser()->getId(),
  1149. //                        'orderLeadUserId' => $projectOrder->getOrderLead()->getUser()->getId()
  1150. //                    ];
  1151.                     $chartGroupsDataset[] = [
  1152.                         'timesheet' => $this->chartValueGetter$_chartGroupsDataHoursSpentfalse),
  1153.                         'revenue' => $this->chartValueGetter($_chartGroupsDataRevenue),
  1154.                         'expenses' => $this->chartValueGetter($_chartGroupsDataExpense),
  1155.                         'employee_cost' => $this->chartValueGetter($_chartGroupsDataWorkedCost),
  1156.                         'profit' => $this->chartValueGetter($_profit),
  1157.                         // 'owner' => substr($projectOrder->getOrderLead()->getName(), 0 ,1 ) . '. ' . $projectOrder->getOrderLead()->getSurname(),
  1158.                         'owner' => $projectOrder->getOrderLead() ? ( $projectOrder->getOrderLead()->getName() . ' ' $projectOrder->getOrderLead()->getSurname() ) : "",
  1159.                         'ownerId' => $projectOrder->getOrderLead() && $projectOrder->getOrderLead()->getId(),
  1160.                         // 'locked' => $userScopped && ( $userScopped->isOnlyOwned() && $userScopped->getUser()->getId() !== $projectOrder->getOrderLead()->getUser()->getId())
  1161.                         'isLocked' => $ownedData false $onlyOwned,
  1162.                     ];
  1163.                 }
  1164.             });
  1165.             #dd();
  1166.             // Net Gelir
  1167.             $netRevenue array_reduce($netRevenues, function($carry$item){
  1168.                 return $carry $item;
  1169.             }, 0);
  1170.             // Yapilan Harcama
  1171.             $netExpense array_reduce($netExpenses, function($carry$item){
  1172.                 try{
  1173.                     return $carry $item;
  1174.                 } catch (\Exception $exception){
  1175.                     dump($carry);
  1176.                 }
  1177.             }, 0);
  1178.             // Harcanan Is Gucu Saat
  1179.             $netHourSpent array_reduce($netHoursSpent, function($carry$item){
  1180.                 // dd($carry);
  1181.                 return $carry $item;
  1182.             }, 0);
  1183.             // Harcanan Is Gucu Saat Fiyat
  1184.             $netHourCostSpent array_reduce($netHoursCostSpent, function($carry$item){
  1185.                 return $carry $item;
  1186.             }, 0);
  1187.             // Profit Ortalama
  1188.             $averageProfitMargin floatval(number_format(array_reduce($profitMargins, function($carry$item){
  1189.                     return $carry $item;
  1190.                 }, 0) / count($profitMargins), 2));
  1191.             // Net Kazanc
  1192.             $netProfit $netRevenue - ( $netExpense $netHourCostSpent);
  1193.             // Bekelnen Kar orani
  1194.             $idealerProfit $netRevenue $averageProfitMargin 100;
  1195.             // Kazanc'a gore son kar margi
  1196.             $netProfitMargin $netProfit $averageProfitMargin $idealerProfit;
  1197.             #dd($translator->trans('Timesheet'));
  1198.             return $this->json([
  1199.                 'message' => $translator->trans('The financial state of the last project has been calculated successfully'),
  1200.                 'Revenue' => $netRevenue,
  1201.                 'AverageProfitMargin' => $averageProfitMargin,
  1202.                 'Expense' => $netExpense,
  1203.                 'HourSpent' => $netHourSpent,
  1204.                 'HourCostSpent' => $netHourCostSpent,
  1205.                 'IdealerProfit' => $idealerProfit,
  1206.                 'NetProfit' => $netProfit,
  1207.                 'ProfitMargin' => $netProfitMargin,
  1208.                 // Only Name for Chart group
  1209.                 'ChartGroups' => array_map(function(/**@var User $user*/ $user ){
  1210.                     return $user substr($user->getName(), 01) . '. ' $user->getSurname() : "No name";
  1211.                 }, $chartGroups),
  1212.                 'ChartGroupsData' => $chartGroupsData,
  1213.                 'ChartGroupColors' => $chartGroupColors,
  1214.                 'ChartGroupsDataset' => $chartGroupsDataset,
  1215.                 'ChartGroupsDatasetLabels' => [
  1216.                     ["dataKey" => 'timesheet'"label" => $translator->trans('Timesheet')],
  1217.                     ["dataKey" => 'revenue'"label" => $translator->trans('Revenue')],
  1218.                     ["dataKey" => 'expenses'"label" => $translator->trans('Expenses')],
  1219.                     ["dataKey" => 'employee_cost'"label" => $translator->trans('Employee cost')],
  1220.                     ["dataKey" => 'profit'"label" => $translator->trans('Profit')],
  1221.                 ]
  1222.             ], Response::HTTP_OK );
  1223.         } catch (\Exception $exception ){
  1224.             return $this->json([
  1225.                 "message" => $exception->getMessage(),
  1226.                 "severity" => "error"
  1227.              ]);
  1228.         }
  1229.     }
  1230.     /**
  1231.      * @deprecated
  1232.      * info for Stakeholder not more Use fetch direct Project!
  1233.      * @Route("/project-stakeholder-timesheet-pdf-as-project/{project_stakeholder_id}", name="project_stakeholder_timesheet_pdf_as_project", methods={"POST", "GET"})
  1234.      * @param Request $request
  1235.      * @param RgbToHex $rgbToHex
  1236.      * @param EntityManagerInterface $manager
  1237.      * @param TimesheetReaderInterface $timesheetReader
  1238.      * @param ProjectStakeholders|null $projectStakeholder
  1239.      * @param SerializerInterface $serializer
  1240.      * @param PdfOutputTimesheet $pdfOutputTimesheet
  1241.      * @param StatusCodes $codes
  1242.      * @param TranslatorInterface $translator
  1243.      * @param int $project_stakeholder_id
  1244.      * @return Response
  1245.      * @ParamConverter("projectStakeholder", options={"mapping":{"project_stakeholder_id":"id"}})
  1246.      */
  1247.     public function stakeholderTimesheet(Request $requestRgbToHex $rgbToHexEntityManagerInterface $managerTimesheetReaderInterface $timesheetReader, ?ProjectStakeholders $projectStakeholderSerializerInterface $serializerPdfOutputTimesheet $pdfOutputTimesheetStatusCodes $codesTranslatorInterface $translatorint $project_stakeholder_id ): Response
  1248.     {
  1249.         $timesheets null;
  1250.         $years $request->request->get('years');
  1251.         $is_guest $request->request->get('is_guest');
  1252.         $projectJoinedEmployees $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest$projectStakeholder){
  1253. //            if( $is_guest !== "true" ){
  1254. //                return $stakeholder->getId() === $projectStakeholder->getId();
  1255. //            }
  1256.             #dump(count($stakeholder->getWorkerInProjects()));
  1257.             return $stakeholder;
  1258.         })->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest$projectStakeholder ){
  1259.             #dump(count($stakeholder->getWorkerInProjects()));
  1260.             return $stakeholder->getWorkerInProjects()->getValues();
  1261.         });
  1262.             #dd();
  1263.         $serializedWorkersInProject json_decode($serializer->serialize$projectJoinedEmployees 'json', [
  1264.             'groups' => [
  1265.                 'timesheet.for.stakeholder'
  1266.             ],
  1267.             AbstractNormalizer::IGNORED_ATTRIBUTES => [
  1268.                 // 'worker_timesheets'
  1269.             ]
  1270.         ]) , true );
  1271.         #dd($serializedWorkersInProject);
  1272.         $serializedWorkersInProject call_user_func_array('array_merge'$serializedWorkersInProject);
  1273.         #dd($serializedWorkersInProject);
  1274.         /// Filtered For Current Project
  1275.         $collection = new ArrayCollection($serializedWorkersInProject);
  1276.         $accessedYears  = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
  1277.         if( $years ) {
  1278.             $accessedYears  json_decode($years); // <-- Should as param
  1279.         }
  1280.         // Overwrite for another process
  1281.         $years = [];
  1282.         $timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
  1283.             // Manipulate color to Hex
  1284.             $item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
  1285.             return $item;
  1286.         });
  1287.         // Initial Values
  1288.         $timesheetReader
  1289.             ->setTimesheetStatusCollection($timesheetStatus)
  1290.             // ->setProjectStakeholders( $projectStakeholder );
  1291.             ->readerPathManager$projectStakeholder->getProject(), nullnull );
  1292.         #dd($collection);
  1293.         array_map(function( $accessedYear ) use ( &$years$is_guest$collection$timesheetReader$timesheetStatus, &$final_times, &$final_costs ){
  1294.             $yearly_times = [];
  1295.             $yearly_costs = [];
  1296.             $final_month_times = [];
  1297.             $final_costs = [];
  1298.             #dd($collection);
  1299.             // Done Empty Workers for current year
  1300.             $workers = [];
  1301.             // Project Stakeholder workers Collection Loop
  1302.             $collection->filter(function($workerActivity) use ($is_guest){
  1303.                 return $workerActivity// $workerActivity['worker_activity']['guest'] === "1" && $is_guest === "true";
  1304.             })->map(function($workerActivity) use (
  1305.                 &$yearly,
  1306.                 &$workers,
  1307.                 $accessedYear,
  1308.                 $timesheetReader,
  1309.                 $timesheetStatus,
  1310.                 &$yearly_times,
  1311.                 &$yearly_costs,
  1312.                 &$final_month_times,
  1313.                 &$final_costs
  1314.             ){
  1315.                 $_worker = [
  1316.                     "id" => $workerActivity['worker_activity']["id"],
  1317.                     "name" => $workerActivity['worker_activity']['worker']["name"],
  1318.                     "surname" => $workerActivity['worker_activity']['worker']["surname"],
  1319.                     "customer" => $workerActivity['worker_activity']['customer']["company"],
  1320.                     "guest" => $workerActivity['worker_activity']['guest']
  1321.                 ];
  1322.                 // Worker Timesheet Source
  1323.                 $foundedYear array_filter$workerActivity['worker_activity']['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
  1324.                     return $timesheetForYear['year'] === $accessedYear;
  1325.                 });
  1326.                 // Update Worker Element with timesheet
  1327.                 // try{
  1328.                 if( $foundedYear ){
  1329.                     $foundedYear array_values($foundedYear);
  1330.                     $foundedYear $foundedYear[0];
  1331.                     $pattern '/^m\d+_d\d+?$/';
  1332.                     $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  1333.                         return preg_match($pattern$item);
  1334.                     });
  1335.                     $activeColumns array_values($activeColumns);
  1336.                     try{
  1337.                         foreach ($foundedYear as $key => $item ) {
  1338.                             if( !in_array($key$activeColumns) ){
  1339.                                 unset($foundedYear[$key]);
  1340.                             }
  1341.                         }
  1342.                     }catch (\Exception $exception ){
  1343.                         dd($exception->getMessage());
  1344.                     }
  1345.                     $months $monthsFinal = [];
  1346.                     // Loop Months
  1347.                     foreach ( range(112) as $monthIndex ) {
  1348.                         #dump($monthIndex);
  1349.                         $timesheetReader->setMonth($monthIndex);
  1350.                         $workerMonthTimeCollection $workerMonthCostCollection $workerMonthInactiveTimeCollection $workerMonthInactiveCostCollection = [];
  1351.                         $pattern '/m' $monthIndex '_d\d/';
  1352.                         // Get days of current month
  1353.                         $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  1354.                             return preg_match($pattern$item);
  1355.                         });
  1356.                         #dump($activeColumns);
  1357.                         foreach ( $activeColumns as $dayKey ) {
  1358.                             $timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
  1359.                             // $readData = $timesheetReader->readTimeExtend();
  1360.                             #dump($foundedYear[$dayKey]);
  1361.                             $readData $timesheetReader->readTimeExtendRolesBasic();
  1362.                             if( array_key_exists($timesheetReader::KEY_TIME_PROP$readData )){
  1363.                                 if($readData[$timesheetReader::KEY_ABSENCE_SHORT_KEY_PROP] === "P"){
  1364.                                     #dump($readData);
  1365.                                     $workerMonthTimeCollection[] = floatval($readData[$timesheetReader::KEY_TIME_PROP]);
  1366.                                     $workerMonthCostCollection[] = floatval($readData[$timesheetReader::KEY_COST]);
  1367.                                 }
  1368. //                                switch ($readData[$timesheetReader::KEY_COST_TYPE]){
  1369. //                                    case $timesheetReader::KEY_COST_TYPE_ACTIVE:
  1370. //                                        $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  1371. //                                        $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
  1372. //                                        break;
  1373. //                                    case $timesheetReader::KEY_COST_TYPE_INACTIVE:
  1374. //                                        $workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  1375. //                                        $workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
  1376. //                                        break;
  1377. //                                }
  1378.                             }
  1379.                         }
  1380.                         // Employee month
  1381.                         $months[$monthIndex] = [
  1382.                             "times" => array_sum($workerMonthTimeCollection),
  1383.                             "costs" => array_sum($workerMonthCostCollection),
  1384.                         ];
  1385.                         // Inactive Times
  1386.                         $monthsFinal[$monthIndex] = [
  1387.                             "times" => array_sum(array_merge($workerMonthInactiveTimeCollection$workerMonthTimeCollection)),
  1388.                             "costs" => array_sum(array_merge($workerMonthInactiveCostCollection$workerMonthInactiveCostCollection)),
  1389.                         ];
  1390.                         // Final month
  1391.                         // $final_month_times[$monthIndex][] =
  1392.                     }
  1393.                     $_worker["months"] = $months;
  1394.                     $_worker["months_final"] = $monthsFinal;
  1395.                     $_worker["yearTimes"] = array_sum(array_map( function ( $month ){
  1396.                         return floatval($month['times']);
  1397.                     }, $months ));
  1398.                     $_worker["yearCosts"] = array_sum(array_map( function ( $month ){
  1399.                         return floatval($month['costs']);
  1400.                     }, $months ));
  1401.                     $yearly_times[] = $_worker["yearTimes"];
  1402.                     $yearly_costs[] = $_worker["yearCosts"];
  1403.                     $workers[] = $_worker;
  1404.                 }
  1405.             });
  1406.             #dump(array_sum($yearly_times));
  1407.             // Append created worker to accessed year
  1408.             $years[$accessedYear]['workers'] = $workers;
  1409.             $years[$accessedYear]['times'] = array_sum($yearly_times);
  1410.             $years[$accessedYear]['costs'] = array_sum($yearly_costs);
  1411.             if($yearly_times ){
  1412.                 dump($years);
  1413.             }
  1414.         }, $accessedYears );
  1415.        #dd();
  1416.         #dd(array_sum(array_map(function($item){ return $item['times']; }, $years )));
  1417.         #dump($final_times);
  1418.         #dump($final_costs);
  1419.         #dd();
  1420.         #dd($is_guest);
  1421.         # dd($years);
  1422.         try{
  1423.             $output null;
  1424.             $pdfOutputTimesheet->setPrintedBy$this->getUser()->getEmail());
  1425.             $output $pdfOutputTimesheet->stakeholderTimesheet(
  1426.                 $translator->trans('Timesheet') . ' ' $projectStakeholder->getProject()->getName() . ' ' $projectStakeholder->getCustomer()->getCompany(),
  1427.                 $projectStakeholder->getCustomer()->getCompany() . ' in ' $projectStakeholder->getProject()->getName(),
  1428.                 $years,
  1429.                 array_sum(array_map(function($item){ return $item['times']; }, $years )),
  1430.                 array_sum(array_map(function($item){ return $item['costs']; }, $years )),
  1431.                 'F'
  1432.             );
  1433.             if( $output->code !== Response::HTTP_OK ){
  1434.                 return $this->json([
  1435.                     'message' => $output->message,
  1436.                     "severity" => "error"
  1437.                 ], Response::HTTP_CONFLICT );
  1438.             }
  1439.         } catch (\Exception $exception){
  1440.             return $this->json([
  1441.                 'message' => $exception->getMessage(),
  1442.                 "severity" => "error"
  1443.             ], Response::HTTP_CONFLICT );
  1444.         }
  1445.         return $this->json([
  1446.             'message' => $translator->trans('Timesheet created successfully!'),
  1447.             "severity" => "success",
  1448.             'output'=>$output
  1449.         ]);
  1450.     }
  1451.     /**
  1452.      * @Route("/all-timesheets-pdf-as-year-for-customer/{customer_slug}/{year}", name="all_timesheets_pdf_as_year_for_customer", methods={"POST"}, defaults={"year"=null})
  1453.      * @param Request $request
  1454.      * @param TimesheetReaderInterface $timesheetReader
  1455.      * @param SerializerInterface $serializer
  1456.      * @param Customer $customer
  1457.      * @param RgbToHex $rgbToHex
  1458.      * @param PdfOutputTimesheet $pdfOutputTimesheet
  1459.      * @param StatusCodes $codes
  1460.      * @param TranslatorInterface $translator
  1461.      * @param EntityManagerInterface $manager
  1462.      * @param int|null $year
  1463.      * @return Response
  1464.      * @ParamConverter("customer", options={"mapping":{"customer_slug":"slug"}})
  1465.      */
  1466.     public function customerTimesheet(Request $requestTimesheetReaderInterface $timesheetReaderSerializerInterface $serializerCustomer $customerRgbToHex $rgbToHexPdfOutputTimesheet $pdfOutputTimesheetStatusCodes $codesTranslatorInterface $translatorEntityManagerInterface $manager, ?int $year null): Response
  1467.     {
  1468.         $timesheets null;
  1469.         $years $request->request->get('years');
  1470.         $is_guest $request->request->get('is_guest');
  1471.         $timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
  1472.             // Manipulate color to Hex
  1473.             $item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
  1474.             return $item;
  1475.         });
  1476.         $accessedYears  = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
  1477.         if( $years ) {
  1478.             $accessedYears  json_decode($years); // <-- Should as param
  1479.         }
  1480.         // Overwrite for another process
  1481.         $years = [];
  1482.         $timesheetReader
  1483.             ->setTimesheetStatusCollection($timesheetStatus);
  1484.         try{
  1485.             array_map(function( $accessedYear ) use ( &$finalCost, &$years$timesheetReader$customer$is_guest$serializer ){
  1486.                 // Done Empty Workers for current year
  1487.                 // Project Stakeholder workers Collection Loop
  1488.                 $stakeholders = [];
  1489.                 // Visit every Customer Project
  1490.                 $customer->getProjectStakeholders()->map(function(/**@var $projectStakeholder ProjectStakeholders*/$projectStakeholder) use ($is_guest, &$years, &$finalCost, &$yearly, &$workers, &$stakeholders$timesheetReader$accessedYear$serializer) {
  1491.                     // initial
  1492.                     $stakeholder["id"] = $projectStakeholder->getId();
  1493.                     $stakeholder["projectName"] = $projectStakeholder->getProject()->getName();
  1494.                     $stakeholder["year"] = $accessedYear;
  1495.                     $stakeholder['months'] = [];
  1496.                     $timesheetReader->readerPathManager$projectStakeholder->getProject(), nullnull );
  1497.                     $workers = [];
  1498.                     $projectJoinedEmployees $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest$projectStakeholder){
  1499.                         if( $is_guest !== "true" ){
  1500.                             return $stakeholder->getId() === $projectStakeholder->getId();
  1501.                         }
  1502.                         return $stakeholder;
  1503.                     })->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest$projectStakeholder ){
  1504.                         return $stakeholder->getWorkerInProjects()->getValues();
  1505.                     });
  1506.                     $serializedWorkersInProject json_decode($serializer->serialize$projectJoinedEmployees 'json', [
  1507.                         'groups' => [
  1508.                             'timesheet.for.stakeholder'
  1509.                         ],
  1510.                         AbstractNormalizer::IGNORED_ATTRIBUTES => [
  1511.                             // 'worker_timesheets'
  1512.                         ]
  1513.                     ]) , true );
  1514.                     $serializedWorkersInProject call_user_func_array('array_merge'$serializedWorkersInProject);
  1515.                     // $stakeholders[]["id"] = $projectStakeholder->getId();
  1516.                     // $stakeholders[]["projectName"] = $projectStakeholder->getProject()->getName();
  1517.                     // $stakeholders[]["year"] = $accessedYear;
  1518.                     array_map( function($workerInProject) use ( $projectStakeholder, &$finalCost, &$stakeholder$timesheetReader$accessedYear ){
  1519.                         $workerActivity $workerInProject['worker_activity'];
  1520.                         // Worker Timesheet Source
  1521.                         $foundedYear array_filter$workerActivity['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
  1522.                             return $timesheetForYear['year'] === intval($accessedYear);
  1523.                         });
  1524.                         // Update Worker Element with timesheet
  1525.                         if( $foundedYear ){
  1526.                             #dump($foundedYear);
  1527.                             $foundedYear array_values($foundedYear);
  1528.                             $foundedYear $foundedYear[0];
  1529.                             $pattern '/^m\d+_d\d+?$/';
  1530.                             $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  1531.                                 return preg_match($pattern$item);
  1532.                             });
  1533.                             $activeColumns array_values($activeColumns);
  1534.                             foreach ($foundedYear as $key => $item ) {
  1535.                                 if( !in_array($key$activeColumns) ){
  1536.                                     unset($foundedYear[$key]);
  1537.                                 }
  1538.                             }
  1539.                             // unset($foundedYear['year']);
  1540.                             foreach ( range(112) as $monthIndex ) {
  1541.                                 $timesheetReader->setMonth($monthIndex);
  1542.                                 $workerMonthTimeCollection $workerMonthCostCollection = [];
  1543.                                 $pattern '/m' $monthIndex '_d\d/';
  1544.                                 // Get days of current month
  1545.                                 $activeColumns array_filterarray_keys($foundedYear), function($item) use ($pattern) {
  1546.                                     return preg_match($pattern$item);
  1547.                                 });
  1548.                                 foreach ( $activeColumns as $dayKey ) {
  1549.                                     $timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
  1550.                                     // $readData = $timesheetReader->readTimeExtend();
  1551.                                     $readData $timesheetReader->readTimeExtendRolesBasic();
  1552.                                     if( array_key_exists($timesheetReader::KEY_TIME_PROP$readData )){
  1553.                                         switch ($readData[$timesheetReader::KEY_COST_TYPE]) {
  1554.                                             case $timesheetReader::KEY_COST_TYPE_ACTIVE:
  1555.                                                 $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  1556.                                                 $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
  1557.                                                 break;
  1558.                                             case $timesheetReader::KEY_COST_TYPE_INACTIVE:
  1559.                                                 // $workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  1560.                                                 // $workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
  1561.                                                 break;
  1562.                                         }
  1563.                                         // $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
  1564.                                         // $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
  1565.                                     }
  1566.                                 }
  1567.                                 $stakeholder['months'][$monthIndex][] = [
  1568.                                     "times" => array_sum($workerMonthTimeCollection),
  1569.                                     "costs" => array_sum($workerMonthCostCollection),
  1570.                                 ];
  1571.                             }
  1572.                         }
  1573.                     }, $serializedWorkersInProject );
  1574.                     /**
  1575.                      * $stakeholder['months'] has multiple times Worker defined
  1576.                      * For example month 11 Has 3 worker defined each of worker Has For Project and Month
  1577.                      * 2 Values times and Cost Should they values collected
  1578.                      * On Bottom Doing this operation
  1579.                      */
  1580.                     foreach ($stakeholder['months'] as $monthIndex => $monthEntries ) {
  1581.                         $monthTimesSimplify = []; // Stakeholder Months has multiple Month times (Worker Entry) do it simplify
  1582.                         $monthCostsSimplify = []; // Stakeholder Months has multiple Month Costs (Worker Entry) do it simplify
  1583.                         foreach ($monthEntries as $monthEntry) {
  1584.                             $monthTimesSimplify[] = $monthEntry['times'];
  1585.                             $monthCostsSimplify[] = $monthEntry['costs'];
  1586.                         }
  1587.                         $stakeholder['months'][$monthIndex] = [
  1588.                             'times' => array_sum($monthTimesSimplify),
  1589.                             'costs' => array_sum($monthCostsSimplify)
  1590.                         ];
  1591.                     }
  1592.                     /**
  1593.                      * For Project Months values have been simplified
  1594.                      * Now Collect All simplified Times And costs from Entry
  1595.                      */
  1596.                     $projectForYearFinalTimesCollection = [];
  1597.                     $projectForYearFinalCostsCollection = [];
  1598.                     foreach ($stakeholder['months'] as $monthIndex => $simplifiedMonth ) {
  1599.                         $projectForYearFinalTimesCollection[] = floatval$simplifiedMonth['times'] );
  1600.                         $projectForYearFinalCostsCollection[] = floatval$simplifiedMonth['costs'] );
  1601.                     }
  1602.                     $stakeholder['yearTimes'] = array_sum($projectForYearFinalTimesCollection);
  1603.                     $stakeholder["yearCosts"] = array_sum($projectForYearFinalCostsCollection);
  1604.                     $stakeholders[] = $stakeholder;
  1605.                 });
  1606.                 $years[$accessedYear] = $stakeholders;
  1607.             }, $accessedYears );
  1608.         } catch (\Exception $exception ){
  1609.             return $this->json([
  1610.                 'message' => $exception->getMessage(),
  1611.                 "severity" => "error"
  1612.             ], Response::HTTP_CONFLICT );
  1613.         }
  1614.         #dd();
  1615.         #dd($years);
  1616.         try{
  1617.             if( !is_null($finalCost)){
  1618.                 foreach ($finalCost as $_year => $yearValue ) {
  1619.                     $finalCost[$_year] = array_sum($yearValue);
  1620.                 }
  1621.             }
  1622.         } catch (\Exception $exception ){
  1623.             return $this->json([
  1624.                 'message' => $exception->getMessage(),
  1625.                 "severity" => "success"
  1626.             ], Response::HTTP_NOT_FOUND );
  1627.         }
  1628.         $output null;
  1629.         $pdfOutputTimesheet->setPrintedBy$this->getUser()->getEmail());
  1630.         $output $pdfOutputTimesheet->customerTimesheet(
  1631.             $translator->trans('Timesheet') . ' ' $customer->getCompany(),
  1632.             $translator->trans('Timesheet Plan by Years of') . ' ' $customer->getCompany(),
  1633.             $years,
  1634.             $finalCost,
  1635.             'F'
  1636.         );
  1637.         return $this->json([
  1638.             'message' => $translator->trans('Timesheet created successfully!'),
  1639.             "severity" => "success",
  1640.             'output'=>$output
  1641.         ]);
  1642.     }
  1643.     /**
  1644.      * Relocate project toArchive | toTrash
  1645.      * @Route("/re-classify/{classify}/{project_id}", name="app_api_project_toarchive", methods={"POST"}, options={"project_id": null})
  1646.      * @ParamConverter("project", options={"mapping": {"project_id": "id"}})
  1647.     */
  1648.     public function reClassify ( ?Projects $projectEntityManagerInterface $managerRequest $requestSerializerInterface  $serializerTranslatorInterface $translatorstring $classify "all"int $project_id null): Response {
  1649.         $processedProjectIds $request->request->get('projects') ?? [];
  1650.         /**@var $user User*/
  1651.         $user $this->getUser();
  1652.         #dd($project_id);
  1653.         if(!$project_id && !count($processedProjectIds)){
  1654.             return $this->json([
  1655.                 "message" => $translator->trans("Project not defined"),
  1656.                 "severity" => "warning"
  1657.             ]);
  1658.         }
  1659.         if(!$project && !count($processedProjectIds)){
  1660.             return $this->json([
  1661.                 "message" => $translator->trans("Project not found"),
  1662.                 "severity" => "error"
  1663.             ]);
  1664.         }
  1665.         $projectIds = [];
  1666.         if(count($processedProjectIds)){
  1667.             $projectIds $processedProjectIds;
  1668.         } else {
  1669.             $projectIds[] = $project->getId();
  1670.         }
  1671.         try {
  1672.             $projects = [];
  1673.             if(count($processedProjectIds)){
  1674.                 $projects $manager->getRepository(Projects::class)->findBy(["id" => $processedProjectIds]);
  1675.             } else {
  1676.                 $projects[] = $project;
  1677.             }
  1678.             // dd($projects);
  1679.             (new ArrayCollection($projects))->map(function(/**@var Projects $project*/ $project) use ($classify$manager) {
  1680.                 switch ($classify){
  1681.                     case "archive":
  1682.                         $project->setIsArchived(true);
  1683.                         break;
  1684.                     case "unarchive":
  1685.                         $project->setIsArchived(null);
  1686.                         break;
  1687.                     case "trash":
  1688.                         $project->setIsRecycle(true);
  1689.                         break;
  1690.                     case "untrash":
  1691.                         $project->setIsRecycle(null);
  1692.                         break;
  1693.                 }
  1694.                 $manager->persist($project);
  1695.                 $manager->flush();
  1696.                 dump($project->getId(), $classify$project->isRecycle(), $project->isArchived());
  1697.             });
  1698.             #dd();
  1699.         } catch (\Exception $exception) {
  1700.             return $this->json([
  1701.                 "message"=> $exception->getMessage(),
  1702.                 "severity" => "error"
  1703.             ], $exception->getCode() );
  1704.         }
  1705. //        $archived = [];
  1706. //        $trashed  = [];
  1707. //        $active = [];
  1708. //        $projects = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
  1709. //        $projects->map( function( /**@var Projects $project */$project) use(&$archived, &$trashed, &$active){
  1710. //            if( !$project->isRecycle()){
  1711. //                if($project->isArchived()){
  1712. //                    $archived[] = $project;
  1713. //                } else {
  1714. //                    $active[] = $project;
  1715. //                }
  1716. //            } else {
  1717. //                $trashed[] = $project;
  1718. //            }
  1719. //        });
  1720.         dd('reClassify_12');
  1721.         return $this->json([
  1722.             "message"=> "Successfully",
  1723.             "severity" => "success",
  1724.             "projectIds" => $projectIds,
  1725. //            "disposed" => [
  1726. //                "archived" => $this->serializeProjects($archived, $serializer),
  1727. //                "trashed" => $this->serializeProjects($trashed, $serializer),
  1728. //                "active" => $this->serializeProjects($active, $serializer)
  1729. //            ]
  1730.             "disposed" => $this->getUserAccessedProjects$user$manager$serializer )
  1731.         ], Response::HTTP_OK);
  1732.     }
  1733.     /**
  1734.      * @Route("/payment-report/{project_id}", name="app_api_project_payment_report", methods={"POST"}, options={"project_id": null})
  1735.      * @ParamConverter("project", options={"mapping": {"project_id": "id"}})
  1736.      * @throws \Exception
  1737.      */
  1738.     public function paymentReport(?Projects $projectPdfOutputProjectPaymentReport $pdfOutputProjectPaymentReportTranslatorInterface $translator ): Response {
  1739.         if(!$project){
  1740.             return $this->json([
  1741.                 "message" => "Project not found",
  1742.                 "severity" => "error"
  1743.             ], Response::HTTP_NOT_FOUND);
  1744.         }
  1745.         $collected = [];
  1746.         $totalInvoice = [];
  1747.         $totalPaidInvoice = [];
  1748.         $dataColumnNames = [
  1749.             $translator->trans('Order number'),
  1750.             $translator->trans('Position-ID'),
  1751.             $translator->trans('Price'),
  1752.             $translator->trans('Sent at'),
  1753.             $translator->trans('Completed!'),
  1754.             $translator->trans('Elapsed days'),
  1755.             $translator->trans('Voucher'),
  1756.             $project->getOwner()->getCompany() . " " $translator->trans('Order number'),
  1757.             $project->getOwner()->getCompany() . " " $translator->trans('CP'),
  1758.             $project->getOwner()->getCompany() . " " $translator->trans('Telephone'),
  1759.         ];
  1760.         $dataColumnWidths = [
  1761.             705070,70,70,70,80,100,80,122
  1762.         ];
  1763.         $project->getProjectOrders()->map( function(/**@var $projectOrder ProjectOrders*/ $projectOrder) use (&$collected, &$totalInvoice, &$totalPaidInvoice ){
  1764.             // $collected[] = $projectOrder->getInvoiceType() ? $projectOrder->getInvoiceType()->getName(): "No invouce type for " . $projectOrder->getOrderNr();
  1765.             if($projectOrder->getInvoiceType()){
  1766.                 if( $projectOrder->getInvoiceType()->getName() === "Voucher" ){
  1767.                     $projectOrder->getProjectOrderUndertakings()->map(function(/**@var $orderUndertaking ProjectOrderUndertakings*/ $orderUndertaking) use (&$collected, &$totalInvoice, &$totalPaidInvoice ){
  1768.                         // if( is_null($orderUndertaking->getCompletedAt()) ){
  1769.                         if( is_null($orderUndertaking->getVoucher()) ){
  1770.                             $completed_at null;
  1771. //                            $waiting_day = $orderUndertaking->getSentAt()->diff(new DateTimeImmutable('now'))->days;
  1772. //                            if( $orderUndertaking->getVoucher()){
  1773. //                                if( $orderUndertaking->getVoucher()->getCompletedAt() ){
  1774. //                                    $completed_at = $orderUndertaking->getVoucher()->getCompletedAt();
  1775. //                                    $waiting_day = $orderUndertaking->getSentAt()->diff($completed_at)->days;
  1776. //                                    $totalPaidInvoice[] = floatval($orderUndertaking->getPrice());
  1777. //                                }
  1778. //                            }
  1779.                             // $waiting_day = $orderUndertaking->getSentAt()->diff()->days;
  1780.                             $waiting_day = (new DateTimeImmutable('now'))->diff$orderUndertaking->getSentAt())->days;
  1781.                             // $remaining = 60 - $waiting_day;
  1782.                             $remaining $waiting_day;
  1783.                             $color "transparent";
  1784.                             $txtColor "black";
  1785.                             if ($remaining <= 10) {
  1786.                                 // 50'den büyükse
  1787.                                 $color "#5cffa1";
  1788.                             } elseif ($remaining <= 30) {
  1789.                                 $color "#ffd800";
  1790.                                 // 21-50 arası
  1791.                             } elseif ($remaining 50) {
  1792.                                 // 1-20 arası
  1793.                                 $color "#ff6a00";
  1794.                             } else {
  1795.                                 // 0 veya daha az
  1796.                                 $color "red";
  1797.                                 $txtColor "white";
  1798.                             }
  1799.                             if($completed_at){
  1800.                                 $txtColor "white";
  1801.                                 $color "green";
  1802.                             }
  1803.                             $data = [
  1804.                                 "order_nr" => $orderUndertaking->getProjectOrder()->getOrderNr(),
  1805.                                 "price" => $orderUndertaking->getPrice(),
  1806.                                 "position_nr" => $orderUndertaking->getPositionNr(),
  1807.                                 "sent_at" => $orderUndertaking->getSentAt(),
  1808.                                 "completed_at" => $completed_at,
  1809.                                 // wait for day 60
  1810.                                 // "remaining_day" => 60 - $waiting_day,
  1811.                                 "remaining_day" => $waiting_day,
  1812.                                 "color" => $color,
  1813.                                 "txtColor" => $txtColor,
  1814.                                 "voucher_nr" => $orderUndertaking->getVoucher() ? $orderUndertaking->getVoucher()->getVoucherNr() : "",
  1815.                                 // Isi verene ait siparis numarasi
  1816.                                 "order_owner_order_nr" => $orderUndertaking->getProjectOrder()->getProjectOwnerOrderNr(),
  1817.                                 "order_owner_contact" => [
  1818.                                     "name" => $orderUndertaking->getProjectOrder()->getContactPerson()->getName(),
  1819.                                     "surname" => $orderUndertaking->getProjectOrder()->getContactPerson()->getSurname(),
  1820.                                     "tel" => $orderUndertaking->getProjectOrder()->getContactPerson()->getTel(),
  1821.                                 ]
  1822.                             ];
  1823.                             $totalInvoice[] = floatval($orderUndertaking->getPrice());
  1824.                             $collected[] = $data;
  1825.                         }
  1826.                     });
  1827.                 }
  1828.             }
  1829.         });
  1830.         $missingPayment array_sum($totalInvoice) - array_sum($totalPaidInvoice);
  1831.         $output null;
  1832.         $pdfOutputProjectPaymentReport->setPrintedBy$this->getUser()->getEmail());
  1833.         $output $pdfOutputProjectPaymentReport->report(
  1834.             $project->getName(),
  1835.             $translator->trans('Payment status'),
  1836.             $project->getProjectId(),
  1837.             $collected,
  1838.             $dataColumnNames,
  1839.             $dataColumnWidths,
  1840.             [
  1841.                 "total" => array_sum($totalInvoice),
  1842.                 "paid" => array_sum($totalPaidInvoice),
  1843.                 "missing" => $missingPayment,
  1844.             ],
  1845.             'F'
  1846.         );
  1847.         return $this->json([
  1848.             "message" => "Successfully",
  1849.             "severity" => "success",
  1850.             "data" => $collected,
  1851.             "output" => $output,
  1852.             "dataColumnNames" => $dataColumnNames
  1853.         ], Response::HTTP_OK );
  1854.     }
  1855.     // ⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆
  1856.     /**
  1857.      * @Route("/all-timesheets-pdf-as-year/{year}", name="all_timesheets_pdf_as_year", methods={"POST"}, defaults={"year"=null})
  1858.      * @param PdfOutputTimesheet $pdfOutputTimesheet
  1859.      * @param StatusCodes $codes
  1860.      * @param TranslatorInterface $translator
  1861.      * @param EntityManagerInterface $manager
  1862.      * @param int|null $year
  1863.      * @return Response
  1864.      */
  1865.     public function allTimesheetPDFAsYearPdfOutputTimesheet $pdfOutputTimesheetStatusCodes $codesTranslatorInterface $translatorEntityManagerInterface $manager, ?int $year null): Response
  1866.     {
  1867.         $timesheets null;
  1868.         if (!is_null($year)) {
  1869.             $timesheets $manager->getRepository(WorkerTimesheet::class)->findBy(["year" => $year]);
  1870.         }
  1871.         $parsedData null;
  1872.         if ($timesheets) {
  1873.             $parsedData = (new ArrayCollection($timesheets))->map(function (/**@var $workerTimesheet WorkerTimesheet */ $workerTimesheet) {
  1874.                 return [
  1875.                     "name" => substr($workerTimesheet->getWorker()->getName(), 0,1) . ". " $workerTimesheet->getWorker()->getSurname() . ' by ' $workerTimesheet->getWorker()->getWorkerActuallyActivity()->getCustomer()->getCompany(),
  1876.                     "timesheetMonths" => $workerTimesheet->getWorkerTimeInPlaceMonths()
  1877.                 ];
  1878.             });
  1879.         }
  1880.         // $this->workerTimeSheetDir . DIRECTORY_SEPARATOR . $filename . '.pdf'
  1881.         # return $this->json($pdfOutputTimesheet->resultForYear('Suleyman Topaloglu', $year, $parsedData, 'D' ));
  1882.         $output null;
  1883.         try{
  1884.             $pdfOutputTimesheet->setPrintedBy$this->getUser()->getEmail());
  1885.             $output $pdfOutputTimesheet->resultForYear(
  1886.                 'Romon GmbH for ' $year,
  1887.                 $year,
  1888.                 $parsedData,
  1889.                 'F'
  1890.             );
  1891.         } catch (\Exception $exception){
  1892.             $codes->set401 );
  1893.             return $this->json([
  1894.                 'message' => $exception->getMessage(),
  1895.                 "severity" => "error"
  1896.             ]);
  1897.         }
  1898.         return $this->json([
  1899.             'message' => $translator->trans('Timesheet created successfully!'),
  1900.             "severity" => "success",
  1901.             "output" => $output
  1902.         ]);
  1903.     }
  1904.     /**
  1905.      * @Route("/add-project-addendum-cost/{project_id}", name="add_project_addendum_cost", methods={"POST"}, defaults={"project_id": null})
  1906.      * @param Projects|null $project
  1907.      * @param StatusCodes $codes
  1908.      * @param AisDate $aisDate
  1909.      * @param TranslatorInterface $translator
  1910.      * @param EntityManagerInterface $manager
  1911.      * @param Request $request
  1912.      * @param int $project_id
  1913.      * @return Response
  1914.      * @throws \Exception
  1915.      * @ParamConverter("project", options={"mapping":{"project_id":"id"}})
  1916.      */
  1917.     public function addProjectAddendumCost( ?Projects $projectStatusCodes $codesAisDate $aisDateTranslatorInterface $translatorEntityManagerInterface $managerRequest $requestint $project_id ): Response
  1918.     {
  1919.         if( !$project ){
  1920.             $codes->set(404);
  1921.             return $this->json([
  1922.                 'message' => $translator->trans('Project not found!'),
  1923.                 "severity" => "error",
  1924.                 "variant"=>"snackbar"
  1925.             ]);
  1926.         }
  1927.         $params $request->request;
  1928.         $costObj = new ProjectAddendumCosts();
  1929.         $costObj
  1930.             ->setAmount($params->get('amount'))
  1931.             ->setAddedAt(new \DateTimeImmutable($params->get('added_at')))
  1932.             ->setAddedBy($this->getUser())
  1933.             // ->setProject($project)
  1934.         ;
  1935.         $project->addProjectAddendumCost($costObj);
  1936.         try{
  1937.             // $manager->persist( $costObj );
  1938.             $manager->persist$project );
  1939.             $manager->flush();
  1940.             $manager->refresh$project );
  1941.         } catch (\Exception $exception){
  1942.             $codes->set401 );
  1943.             return $this->json([
  1944.                 'message' => $exception->getMessage(),
  1945.                 "severity" => "error"
  1946.             ]);
  1947.         }
  1948.         return $this->json([
  1949.             'message' => $translator->trans('Addendum Cost added successfully!'),
  1950.             "severity" => "success",
  1951.             "totalCost" => $project->getTotalCost(),
  1952.             'addedCost'=>[
  1953.                 'id' => $costObj->getId(),
  1954.                 'project' => $project->getId(),
  1955.                 'addedAt' => $costObj->getAddedAt(),
  1956.                 'addedBy' => [
  1957.                     "id" => $costObj->getAddedBy()->getId(),
  1958.                     "username" => $costObj->getAddedBy()->getEmail(),
  1959.                 ],
  1960.                 'amount' => $costObj->getAmount(),
  1961.             ]
  1962.         ], Response::HTTP_OK, [], [
  1963.             AbstractNormalizer::IGNORED_ATTRIBUTES => [
  1964.             ]
  1965.         ]);
  1966.     }
  1967.     // Upload excel
  1968.     /**
  1969.      * @Route("/upload-cost-list/{project_id}", name="upload_cost_list", defaults={"project_id": null })
  1970.      * @param Projects $project
  1971.      * @param $uploadedFilesDir
  1972.      * @param TranslatorInterface $translator
  1973.      * @param EntityManagerInterface $manager
  1974.      * @param StatusCodes $codes
  1975.      * @param Request $request
  1976.      * @return Response
  1977.      */
  1978.     function uploadCostListProjects $project$uploadedFilesDirTranslatorInterface $translatorEntityManagerInterface $managerStatusCodes $codesRequest $request ): Response{
  1979.         if(!$project){
  1980.             return $this->json([
  1981.                 "message" => $translator->trans('Project not found'),
  1982.                 "severity" => "warning"
  1983.             ], Response::HTTP_NOT_FOUND );
  1984.         }
  1985.         $file $request->files->get('costs_file');
  1986.         if( !$file ){
  1987.             $codes->set(Response::HTTP_NOT_FOUND);
  1988.             return $this->json([
  1989.                 'code'=>404,
  1990.                 "message"=>$translator->trans('File not loaded'),
  1991.             ]);
  1992.         }
  1993.         #dd($file);
  1994.         $filePathName md5(uniqid()) . $file->getClientOriginalName();
  1995.         // apply md5 function to generate an unique identifier for the file and concat it with the file extension
  1996.         try {
  1997.             $file->move$uploadedFilesDir$filePathName );
  1998.             $spreadsheet IOFactory::load$uploadedFilesDir DIRECTORY_SEPARATOR $filePathName );
  1999.             $sheetData $spreadsheet->getActiveSheet()->toArray(nulltruetruefalse );
  2000.             // Delete file again!
  2001.             // unlink($uploadedFilesDir . DIRECTORY_SEPARATOR . $filePathName );
  2002.             // Check through is Correct file
  2003.             $header array_shift($sheetData); // $sheetData[0];
  2004.             $source = [
  2005.                 "Status""Int. Beleg-Nr." ,"Rechnungs-Nr." ,"Eingangsdatum" ,"Zahlungsstatus" ,
  2006.                 "Firmenname" ,"Zahlart" ,"Projekt" ,"Fällig am" ,"Bruttobetrag" ,"Offener Betrag" ,
  2007.                 "Projekt-Nr." ,"Kategorie" ,"Offene Überweisungen" ,"Zahlungsausgang"
  2008.             ];
  2009.             if( count(array_diff($source$header))){
  2010.                 return $this->json([
  2011.                     "message" => $translator->trans('Invalid file, file columns title does\'t compare with nested column title, please check your file, '),
  2012.                     "severity" => "info"
  2013.                 ], Response::HTTP_UNAUTHORIZED );
  2014.             }
  2015.             $index_of_invoice_nr array_search("Int. Beleg-Nr."$source);
  2016.             $index_of_project_id array_search("Projekt-Nr."$source);
  2017.             $transfer_for $request->request->get('transfer_for');
  2018.             // Filter already in found
  2019. //            $alreadyAdded = $project->getProjectExpenses()->map(function(/**@var $projectExpense ProjectExpense */ $projectExpense ) {
  2020. //                return $projectExpense->getReceiptNr();
  2021. //            })->toArray();
  2022.             $alreadyAdded = (new ArrayCollection($manager->getRepository(ProjectExpense::class)->findAll()))->map(function(/**@var $projectExpense ProjectExpense */ $projectExpense ) {
  2023.                 return $projectExpense->getReceiptNr();
  2024.             })->toArray();
  2025.             #dd($alreadyAdded);
  2026.             $addables array_values(array_filter$sheetData, function($item) use ( $index_of_invoice_nr$index_of_project_id$alreadyAdded$transfer_for  ){
  2027.                 #dd($item[$index_of_invoice_nr]);
  2028.                 return $transfer_for === "all" ?
  2029.                     !in_array($item[$index_of_invoice_nr], $alreadyAdded ) :
  2030.                     !in_array($item[$index_of_invoice_nr], $alreadyAdded ) && $item[$index_of_project_id] === $transfer_for ;
  2031.             },ARRAY_FILTER_USE_BOTH ));
  2032.             #dd($addables);
  2033.             // Default chosen_ones all
  2034.             $chosen_ones array_map(function($item) use ( $index_of_invoice_nr ) {
  2035.                 return $item[$index_of_invoice_nr];
  2036.             }, $addables);
  2037.             #dd($chosen_ones);
  2038. //            $addables = array_values(array_filter( $sheetData, function($item) use ( $index_of_invoice_nr, $alreadyAdded  ){
  2039. //                return !in_array($item[$index_of_invoice_nr], $alreadyAdded );
  2040. //            },ARRAY_FILTER_USE_BOTH ));
  2041.             #dd(array_values($addables));
  2042.         } catch (FileException $e) {
  2043.             return $this->json([
  2044.                 'code'=>$e->getCode(),
  2045.                 "message"=>$e->getMessage(),
  2046.             ]);
  2047.         }
  2048.         return $this->json([
  2049.             "code" => Response::HTTP_OK,
  2050.             "header" => $header,
  2051.             "collection" => $addables,
  2052.             "chosenOnes" => $chosen_ones,
  2053.             "message"=>$translator->trans('Uploaded successfully'),
  2054.             "fileName" => $filePathName
  2055.             ], Response::HTTP_OK, [], [
  2056.                 AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2057.                 ]
  2058.             ]
  2059.         );
  2060.     }
  2061.     /**
  2062.      * @Route("/upload-cost-list-transfer/{project_id}", name="upload_cost_list_transfer", defaults={"project_id": null })
  2063.      * @param Projects $project
  2064.      * @param $uploadedFilesDir
  2065.      * @param EntityManagerInterface $manager
  2066.      * @param TranslatorInterface $translator
  2067.      * @param Request $request
  2068.      * @return Response
  2069.      * @throws \Exception
  2070.      */
  2071.     function uploadCostListTransferProjects $project$uploadedFilesDirEntityManagerInterface $manager,  TranslatorInterface $translatorRequest $request ): Response
  2072.     {
  2073.         if (!$project) {
  2074.             return $this->json([
  2075.                 "message" => $translator->trans('Project not found'),
  2076.                 "severity" => "warning"
  2077.             ], Response::HTTP_NOT_FOUND);
  2078.         }
  2079.         $chosen_ones = !empty($request->request->get('chosen_ones')) ? preg_split("/\,/",  $request->request->get('chosen_ones') ) : [];
  2080.         $file_name $request->request->get('file_name');
  2081.         $spreadsheet IOFactory::load$uploadedFilesDir DIRECTORY_SEPARATOR $file_name );
  2082.         $sheetData $spreadsheet->getActiveSheet()->toArray(nulltruetruefalse );
  2083.         // Delete file again!
  2084.         // unlink($uploadedFilesDir . DIRECTORY_SEPARATOR . $filePathName );
  2085.         $prepared array_map( function( $selected ) use( $sheetData ){
  2086.             $d array_filter($sheetData, function($data) use ($selected){
  2087.                 return array_search($selected$data);
  2088.             });
  2089.             return array_shift($d);
  2090.         }, $chosen_ones );
  2091.         if( !count($prepared) ){
  2092.             return $this->json([
  2093.                 "message" => $translator->trans('Please select at last one transfer item'),
  2094.                 "severity" => "warning"
  2095.             ], Response::HTTP_UNAUTHORIZED);
  2096.         }
  2097.         #dd($request->request->all());
  2098.         foreach ( $prepared as $item ) {
  2099.             if( !empty($item[11] ) && $request->request->get('transfer_for') === "all" ){
  2100.                 $project $manager->getRepository(Projects::class)->findOneBy(["project_id"=>$item[11]]);
  2101.                 #dd($project);
  2102.             }
  2103.             if( $project ){
  2104.                 $project_expense = new ProjectExpense();
  2105.                 $project_expense
  2106.                     ->setStatus($item[0])
  2107.                     ->setReceiptNr($item[1])
  2108.                     ->setInvoiceNr($item[2])
  2109.                     ->setReceiptAt(new \DateTimeImmutable($item[3]))
  2110.                     ->setPaymentStatus($item[4])
  2111.                     ->setCompanyName($item[5])
  2112.                     ->setPaymentMethod($item[6])
  2113.                     ->setProject($project)
  2114.                     ->setDueAt(new \DateTimeImmutable($item[8]))
  2115.                     // ->setTotalAmount( money_format('%i', preg_replace("/\,/", "", $item[9] )))
  2116.                     ->setTotalAmountfloatval(preg_replace("/,/"null$item[9] ) ) )
  2117.                     // ->setOutstandingBalance( money_format('%i', preg_replace("/\,/", "", $item[10] )) )
  2118.                     ->setOutstandingBalancefloatval(preg_replace("/,/"null$item[10] ) ) )
  2119.                     ->setCategory($item[12])
  2120.                     ->setOpenTransfer($item[13])
  2121.                     ->setPaidAt(new \DateTimeImmutable($item[14]));
  2122.                 $manager->persist($project_expense);
  2123.                 $project null;
  2124.             }
  2125.         }
  2126.         try{
  2127.             $manager->flush();
  2128.         } catch (\Exception $exception){
  2129.             return $this->json([
  2130.                 "message" => $exception->getMessage(),
  2131.                 "severity" => "warning"
  2132.             ], Response::HTTP_NOT_FOUND);
  2133.         }
  2134.         return $this->json([
  2135.             "message" => $translator->trans('Transfer successfully'),
  2136.             "severity" => "warning"
  2137.         ], Response::HTTP_OK);
  2138.     }
  2139.     // Read excel
  2140.     /**
  2141.      * @Route("/read-uploaded-cost-list", name="read_uploaded_cost_list")
  2142.      * @param $uploadedFilesDir
  2143.      * @param Request $request
  2144.      * @return Response
  2145.      */
  2146.     function readUploadedCostList$uploadedFilesDirRequest $request ): Response{
  2147.         #dd($uploadedFilesDir);
  2148.         $spreadsheet IOFactory::load$uploadedFilesDir DIRECTORY_SEPARATOR "Export_Eingangsrechnung.xls");
  2149.         $sheetData $spreadsheet->getActiveSheet()->toArray(nulltruetruefalse );
  2150.         dd($sheetData);
  2151.         return $this->json(
  2152.             [
  2153.                 "message" => "Successfully",
  2154.                 "severity" => "success"
  2155.             ], Response::HTTP_OK, [], [
  2156.                 AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2157.                 ]
  2158.             ]
  2159.         );
  2160.     }
  2161.     // Transform
  2162.     /**
  2163.      * @Route("/transfer-uploaded-cost-list", name="transfer_uploaded_cost_list")
  2164.      * @param Request $request
  2165.      * @return Response
  2166.      */
  2167.     function transferUploadedCostListRequest $request ): Response{
  2168.         return $this->json(
  2169.             [
  2170.             ], Response::HTTP_OK, [], [
  2171.                 AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2172.                 ]
  2173.             ]
  2174.         );
  2175.     }
  2176.     /**
  2177.      * @Route("/print-project-foreword/{project_id}", name="print_project_foreword", methods={"POST", "GET"})
  2178.      * @ParamConverter("project", options={"mapping":{"project_id":"id"}})
  2179.      * @param Projects $project
  2180.      * @param Request $request
  2181.      * @return Response
  2182.      */
  2183.     function printProjectForewordProjects $projectRequest $requestPdfOutputTimesheet $pdfOutputTimesheet ): Response{
  2184.         if( !$project ){
  2185.             // Project not found!
  2186.             return $this->json(
  2187.                 [
  2188.                     "message" => "Project not found",
  2189.                     "severity" => "error"
  2190.                 ], Response::HTTP_NOT_FOUND, [], [
  2191.                     AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2192.                     ]
  2193.                 ]
  2194.             );
  2195.         }
  2196.         if( !$project->getQrCode() ){
  2197.             return $this->json(
  2198.                 [
  2199.                     "message" => "Project QR-Core not ready please save project and try again",
  2200.                     "severity" => "warning",
  2201.                 ], Response::HTTP_METHOD_NOT_ALLOWED, [], [
  2202.                     AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2203.                     ]
  2204.                 ]
  2205.             );
  2206.         }
  2207.         #dd($uploadedFilesDir);
  2208.         $pdfOutputTimesheet->setPrintedBy('Suleyman Topaloglu');
  2209.         $output $pdfOutputTimesheet->printProjectForeword$project'F' );
  2210.         return $this->json(
  2211.             [
  2212.                 "message" => "Successfully",
  2213.                 "severity" => "success",
  2214.                 'output'=>$output
  2215.             ], Response::HTTP_OK, [], [
  2216.                 AbstractNormalizer::IGNORED_ATTRIBUTES => [
  2217.                 ]
  2218.             ]
  2219.         );
  2220.     }
  2221. }