<?php
namespace App\Controller\Api;
use App\Controller\ModulesAccessTypes;
use App\Entity\AccessRoles;
use App\Entity\Administrative;
use App\Entity\Branches;
use App\Entity\Certificates;
use App\Entity\CertificatesGroups;
use App\Entity\Countries;
use App\Entity\Customer;
use App\Entity\CustomerCertificates;
use App\Entity\InvoiceType;
use App\Entity\ProjectAddendumCosts;
use App\Entity\ProjectBranches;
use App\Entity\ProjectExpense;
use App\Entity\ProjectOrderExpensePositions;
use App\Entity\ProjectOrders;
use App\Entity\ProjectOrderUndertakings;
use App\Entity\ProjectOwner;
use App\Entity\Projects;
use App\Entity\ProjectSettings;
use App\Entity\ProjectStakeholders;
use App\Entity\Qualification;
use App\Entity\TimesheetStatus;
use App\Entity\User;
use App\Entity\UserScopedItem;
use App\Entity\WorkerActivities;
use App\Entity\WorkerTimesheet;
use App\Repository\BranchesRepository;
use App\Repository\CertificatesRepository;
use App\Repository\QualificationRepository;
use App\Service\AisDate;
use App\Service\PdfOutputProjectPaymentReport;
use App\Service\PdfOutputTimesheet;
use App\Service\RgbToHex;
use App\Service\SeverityInterface;
use App\Service\StatusCodes;
use App\Service\TimesheetInterface\TimesheetReaderInterface;
use Container69K1BxJ\getMaker_PhpCompatUtilService;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use Monolog\DateTimeImmutable;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function Doctrine\StaticAnalysis\DBAL\makeMeACustomConnection;
use function Psr\Log\error;
use function Symfony\Bundle\MakerBundle\Util\advanceBeyondMultilineArrayLastItem;
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
/**
* @Route("/api/project")
*/
class ProjectController extends AbstractController
{
// ⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
/**
* 💡💡💡info 💡💡💡
* $postedBranches is Core Branch ( not projectBranch Id!!!)
*/
private function appendBranchToProject(?Projects $project, EntityManagerInterface $manager, array $posted_branch_ids ): Projects {
// Eğer $posted_branch_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
if (gettype($posted_branch_ids) === "string") {
$posted_branch_ids = json_decode($posted_branch_ids, false); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
}
// ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
$posted_branch_ids = array_map('intval', $posted_branch_ids);
// Projenin mevcut branch ilişkilerini al (Doctrine Collection)
$olderBranches = $project->getProjectBranches();
// Eğer projede daha önce eklenmiş branch'ler varsa
if ($olderBranches->count()) {
// Her eski ilişkiyi dön
foreach ($olderBranches as $olderBranch) {
// İlişkili branch'in ID'sini al
$olderBranchId = $olderBranch->getBranch()->getId();
// Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
if (!in_array($olderBranchId, $posted_branch_ids, true)) {
$project->removeProjectBranch($olderBranch); // Doctrine üzerinden ilişkiyi kaldır
} else {
// Varsa, tekrar eklemeye gerek yok
// Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
$posted_branch_ids = array_diff($posted_branch_ids, [$olderBranchId]);
}
}
}
// Yeni eklenecek branch ID'leri kaldıysa
if ($posted_branch_ids) {
if (count($posted_branch_ids)) {
// Bu ID'lere karşılık gelen Branch objelerini DB'den çek
$branches = $manager->getRepository(Branches::class)->findBy(["id" => $posted_branch_ids]);
// Her yeni branch için ProjectBranches ilişkisi oluştur
foreach ($branches as $branch) {
$projectBranch = new ProjectBranches(); // Yeni ilişki nesnesi
$projectBranch->setBranch($branch); // Branch ilişkilendirilir
// Gerekirse persist edilebilir (Doctrine cascade yoksa)
// $manager->persist($projectBranch);
$project->addProjectBranch($projectBranch); // İlişki projeye eklenir
}
}
}
// Güncellenmiş Project nesnesi geri döndürülür
return $project;
}
private function manageProjectCertificates( Projects $project, EntityManagerInterface $manager, array $posted_certificate_ids = [] ): Projects {
#dd($posted_certificate_ids);
// Eğer $posted_certificate_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
if (gettype($posted_certificate_ids) === "string") {
$posted_certificate_ids = json_decode($posted_certificate_ids, false); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
}
// ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
$posted_certificate_ids = array_map('intval', $posted_certificate_ids);
#dd($posted_certificate_ids);
// Projenin mevcut branch ilişkilerini al (Doctrine Collection)
$olderCertificates = $project->getDependentCertificates();
#dump($posted_certificate_ids);
// Eğer projede daha önce eklenmiş branch'ler varsa
if ($olderCertificates->count()) {
// Her eski ilişkiyi dön
foreach ($olderCertificates as $olderCertificate) {
// İlişkili branch'in ID'sini al
$olderCertificateId = $olderCertificate->getId();
dump($olderCertificateId);
// Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
if (!in_array($olderCertificateId, $posted_certificate_ids, true)) {
$project->removeDependentCertificate($olderCertificate); // Doctrine üzerinden ilişkiyi kaldır
} else {
// Varsa, tekrar eklemeye gerek yok
// Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
$posted_certificate_ids = array_diff($posted_certificate_ids, [$olderCertificateId]);
}
}
}
// Yeni eklenecek branch ID'leri kaldıysa
if ($posted_certificate_ids) {
if (count($posted_certificate_ids)) {
// Bu ID'lere karşılık gelen Branch objelerini DB'den çek
$certificates = $manager->getRepository(Certificates::class)->findBy(["id" => $posted_certificate_ids]);
// Her yeni branch için ProjectBranches ilişkisi oluştur
foreach ($certificates as $certificate ) {
$project->addDependentCertificate($certificate); // Yeni ilişki nesnesi
}
}
}
// Güncellenmiş Project nesnesi geri döndürülür
return $project;
}
private function manageProjectQualifications( Projects $project, EntityManagerInterface $manager, array $posted_qualification_ids = [] ): Projects {
#dd($posted_qualification_ids);
// Eğer $posted_qualification_ids bir string (JSON) olarak geldiyse, decode ederek diziye çevir
if (gettype($posted_qualification_ids) === "string") {
$posted_qualification_ids = json_decode($posted_qualification_ids, false); // burada true da kullanılabilir, ama aşağıda map ile işleniyor
}
// ID'lerin hepsini integer'a çevir (in_array'nin strict karşılaştırması için)
$posted_qualification_ids = array_map('intval', $posted_qualification_ids);
#dd($posted_qualification_ids);
// Projenin mevcut branch ilişkilerini al (Doctrine Collection)
$olderQualifications = $project->getDependentQualifications();
#dump($posted_qualification_ids);
// Eğer projede daha önce eklenmiş branch'ler varsa
if ($olderQualifications->count()) {
// Her eski ilişkiyi dön
foreach ($olderQualifications as $olderQualification) {
// İlişkili branch'in ID'sini al
$olderQualificationId = $olderQualification->getId();
dump($olderQualificationId);
// Eğer bu eski ID, gelen yeni listede yoksa → bu ilişki silinmeli
if (!in_array($olderQualificationId, $posted_qualification_ids, true)) {
$project->removeDependentQualification($olderQualification); // Doctrine üzerinden ilişkiyi kaldır
} else {
// Varsa, tekrar eklemeye gerek yok
// Aynı zamanda array'den çıkar ki, kalan ID'ler sadece yeni eklenecekler olsun
$posted_qualification_ids = array_diff($posted_qualification_ids, [$olderQualificationId]);
}
}
}
// Yeni eklenecek branch ID'leri kaldıysa
if ($posted_qualification_ids) {
if (count($posted_qualification_ids)) {
// Bu ID'lere karşılık gelen Branch objelerini DB'den çek
$qualifications = $manager->getRepository(Qualification::class)->findBy(["id" => $posted_qualification_ids]);
// Her yeni branch için ProjectBranches ilişkisi oluştur
foreach ($qualifications as $qualification ) {
$project->addDependentQualification($qualification); // Yeni ilişki nesnesi
}
}
}
// Güncellenmiş Project nesnesi geri döndürülür
return $project;
}
/**
* @param Projects|null $project
* @param Customer|null $customer
* @param AisDate $aisDate
* @param TranslatorInterface $translator
* @return array
* @throws \Exception
*/
public function coreProjectPrettyStatusData (?Projects $project, ?Customer $customer, AisDate $aisDate, TranslatorInterface $translator ): array
{
$alert[] = [
"header" => $translator->trans('Suitable!'),
"severity" => "success"
];
$suitable = true;
// Core Warning's
// Check Core defined Qualifications
if (!$project->getDependentQualifications()->count()) {
$alert[] = [
"header" => $project->getName() . " " . $translator->trans("is not suitable because the qualifications for this project not defined"),
"severity" => "warning"
];
}
// Check Core defined Certificates
if (!$project->getDependentCertificates()->count()) {
$alert[] = [
"header" => $project->getName() . " " . $translator->trans("is not suitable because the certificates for this project not defined"),
"severity" => "warning"
];
}
$missingCertificates = $project->getDependentCertificates()->filter(function (/**@var $dependedCertificate Certificates */ $dependedCertificate) use ($customer) {
return $dependedCertificate->getCertificateEligibility()->getName() === 'company' && $customer->getCustomerCertificates()->filter(function (/**@var $customerCertificate CustomerCertificates */ $customerCertificate) use ($dependedCertificate) {
return $customerCertificate->getCertificate()->getId() === $dependedCertificate->getId();
})->count() === 0;
})->getValues();
if( count($missingCertificates) ){
$alert[] = [
"header" => $project->getName() . " " . $translator->trans('Project for this company is suitable with missing certificates'),
"subheader" => (new ArrayCollection($missingCertificates))->map( function( /**@var $missingCertificate Certificates*/$missingCertificate ){
return [
"header" => "* " . $missingCertificate->getName(),
"severity" => "info"
];
}),
"severity" => "info"
];
}
if ( !$project->getEndAt() ) {
$alert[] = [
"header" => $translator->trans(
"'End Date' of Core Project not defined,
If any time, you try to define 'End Date' of Core with your confirmation,
system can equalize 'End-Date' of Stakeholders with Core!,
If you are unsure of the due date, I recommend leaving it blank."),
"severity" => "info"
];
}
// Worker Active in selected stakeholder project
// By join to project, not by edit!
if( $customer ){
$foundedCustomerInProject = $customer->getProjectStakeholders()->filter( function(/**@var $projectStakeholder ProjectStakeholders*/ $projectStakeholder ) use ( $project ){
return $projectStakeholder->getProject()->getId() === $project->getId() &&
( !$projectStakeholder->getEndAt() || ($projectStakeholder->getEndAt() > new DateTimeImmutable('now')));
})->first();
#dd($foundedCustomerInProject);
if( $foundedCustomerInProject ){
$alert = [
"header" => $foundedCustomerInProject->getCustomer()->getCompany() . ' ' . $translator->trans('already in project!'),
"severity" => "info"
];
$suitable = false;
}
}
if(!is_null($project->getStatus())){
// Overwrite if completed
if($project->getStatus()['completed'] ){
$alert = [
"header" => $translator->trans('Completed!'),
"severity" => "info"
];
$suitable = false;
}
// Overwrite if expired
if ( !$project->getStatus()['completed'] && $project->getEndAt() && $aisDate->date($project->getEndAt())->lowerThan(new \DateTimeImmutable('now'))) {
$alert = [
"header" => $project->getName() . " " . $translator->trans(' has expired'),
"severity" => "success"
];
$suitable = false;
}
}
return [
"suitable" => $suitable,
"notifications" => $alert
];
}
private function serializeProjects( array $projects, SerializerInterface $serializer): array {
return json_decode( $serializer->serialize( $projects, 'json', [
'groups' => [
"project.list.with.necessary.details",
"project.details.orders",
"project.details"
]
]));
}
private function getUserAccessedProjects(User $user, EntityManagerInterface $manager, SerializerInterface $serializer): array {
$allProjects = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
#dd($user->getUserScopedItems()->toArray());
$userScopedForProjectList = $user->getUserScopedItems()->filter(function(/**@var UserScopedItem $scopedItem */ $scopedItem){
return $scopedItem->getScopedItem()->getCategory()
=== ModulesAccessTypes::E_MODULES_SCOPED_CATEGORIES_PROJECT && $scopedItem->getScopedItem()->getType() === ModulesAccessTypes::E_MODULES_SCOPED_TYPES_LIST;
})->first();
#dd($userScopedForProjectList->isOnlyOwned());
#dd($allProjects);
#dd($userScopedForProjectList);
$isAdmin = (in_array('ROLE_ADMIN', $user->getRoles()) || in_array('ROLE_SUPER_ADMIN', $user->getRoles()));
if($userScopedForProjectList) {
$userScopedForProjectList = $userScopedForProjectList->isOnlyOwned();
if ($userScopedForProjectList) {
$filteredProjects = $allProjects->filter(function (/**@var Projects $project */ $project) use ($user) {
// NEDEN LEAD ICIN YAPIMIS ??? ⚠️ SADECE USER ONLY OWNED MI CONTROLU YETERLI
// return $project->getProjectOrders()->exists(function($key, /**@var ProjectOrders $projectOrder*/ $projectOrder) use ($user) {
// // Eğer sipariş lideri yoksa, sadece debug için dump
// if ($projectOrder->getOrderLead() === null) {
// #dump($projectOrder->getProject()->getProjectId());
// }
// // Sipariş lideri mevcutsa, kullanıcı eşleşmesini kontrol et
// $orderLeadUser = null;
// if( $projectOrder->getOrderLead() ){
// $orderLeadUser = $projectOrder->getOrderLead()->getUser();
// if(!is_null($orderLeadUser)){
// if($orderLeadUser->getId() === $user->getId()){
// #dump($orderLeadUser->getId(), $user->getId());
// return true;
// }
//
// }
// }
// return false;
// });
// // return $project->getProjectOrders()->filter( fn( Projects $project) => true );
// return $project->getProjectOrders()->exists( fn(ProjectOrders $projectOrder ) => $projectOrder->getOrderLead()?->getUser()->getId() === $user->getId() );
return $project->getProjectOrders()->contains(function (ProjectOrders $projectOrder) use ($user) {
return $projectOrder->getOrderLead() && $projectOrder->getOrderLead()->getUser()->getId() === $user->getId() || $projectOrder->getOrderAlternateLeads()->exists(fn(WorkerActivities $workerActivity) => $workerActivity->getUser()->getId() === $user->getId());
});
});
#
$filteredProjects = $allProjects->filter(function (Projects $project) use ($user, $isAdmin) {
foreach ($project->getProjectOrders() as /**@var ProjectOrders $projectOrder*/$projectOrder) {
// Global Permissions
$globalPermission = $projectOrder->getOrderPrimaryLead() && $projectOrder->getOrderPrimaryLead()->getWorkerActivitySubstitutions()->exists(
fn ( $key, WorkerActivities $_workerActivity) => $_workerActivity->getId() === $this->getUser()->getUserAsWorkerLatestActivity()->getId()
);
// Order Based Permissions
$orderBasedPermission = $projectOrder->getOrderAlternateLeads() && $projectOrder->getOrderAlternateLeads()->exists(
fn( $key, WorkerActivities $workerActivity ) => $workerActivity->getId() === $this->getUser()->getUserAsWorkerLatestActivity()->getId()
);
// Scoped (Isolated) item's
$scopeIsolated = ($projectOrder->getOrderPrimaryLead() && $projectOrder->getOrderPrimaryLead()->getUser()) && $projectOrder->getOrderPrimaryLead()->getUser()->getId() === $user->getId();
return $isAdmin || ($globalPermission || (($orderBasedPermission || $scopeIsolated)));
}
return false;
});
$allProjects = $filteredProjects;
}
}
#dd();
#dd($allProjects->count());
$archived = [];
$trashed = [];
$active = [];
#dd();
$allProjects->map( function( /**@var Projects $project */$project) use(&$archived, &$trashed, &$active){
if( !$project->isRecycle()){
if($project->isArchived()){
$archived[] = $project;
} else {
$active[] = $project;
}
} else {
$trashed[] = $project;
}
});
return [
"archived" => $this->serializeProjects($archived, $serializer),
"trashed" => $this->serializeProjects($trashed, $serializer),
"active" => $this->serializeProjects($active, $serializer),
];
}
/**
* @Route("/fetch-projects-for-administrative-customer/{classify}", name="fetch_projects_for_administrative_customer")
* @param EntityManagerInterface $manager
* @param SerializerInterface $serializer
* @param string $classify
* @return Response
*/
public function fetchProjectsForAdministrativeCustomer( EntityManagerInterface $manager, SerializerInterface $serializer, string $classify = 'active' ): Response {
/**@var $user User */
$user = $this->getUser();
#dd($this->getUser());
$administrative = $manager->getRepository(Administrative::class)->findAdministrative();
// dd($administrative->getPairedCustomer()->getProjectStakeholders()->toArray());
if(!$administrative){
return $this->json([
"message" => "No any customer as administrative found!",
"severity" => "error"
], Response::HTTP_NOT_FOUND, [], []);
}
# $fetchAdministrativeProjects = $manager->getRepository(Projects::class)->fetchAdministrativeProjects($administrative->getPairedCustomer()->getId(), $classify );
#dd($fetchAdministrativeProjects);
# $projects = $this->serializeProjects($fetchAdministrativeProjects, $serializer);
#dd('fetchProjectsForAdministrativeCustomer_12');
return $this->json([
# "projects" => $projects,
#"projects" => $allProjects,
"disposed" => $this->getUserAccessedProjects( $user, $manager, $serializer ),
"classify" => $classify
], Response::HTTP_OK, [], []);
}
/**
* @Route("/fetch-projects-for-timesheet", name="fetch_projects_for_timesheet")
* @param EntityManagerInterface $manager
* @param SerializerInterface $serializer
* @return JsonResponse
*/
public function fetchProjectsForTimesheet( EntityManagerInterface $manager, SerializerInterface $serializer ): Response {
$administrative = $manager->getRepository(Administrative::class)->findAdministrative();
if(!$administrative){
return $this->json([
"message" => "No any customer as administrative found!",
"severity" => "error"
], Response::HTTP_NOT_FOUND, [], []);
}
$projects = $manager->getRepository(Projects::class)->findAll();
$projects = json_decode($serializer->serialize($projects, 'json', [
'groups' => [
'project.details.for.collected.timesheet',
'order.base',
'project.branches'
]
]));
return $this->json([
"projects" => $projects
], Response::HTTP_OK, [], []);
}
/**
* @deprecated using from one Component Future will Remove
* @see fetch-projects-for-administrative-customer
* nullable customer_id need while check customer status in core projects
* @Route("/fetch-projects/{customer_id}", name="fetch_weak_list", defaults={"customer_id":null})
* @ParamConverter("customer", options={"mapping":{"customer_id": "id"}})
* @param EntityManagerInterface $manager
* @param SerializerInterface $serializer
* @return Response
* Customer Analyse for projects
*/
public function fetchProjects( EntityManagerInterface $manager, SerializerInterface $serializer ): Response
{
#dd("fetch-projects");
$projectsEntity = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
$projects = json_decode( $serializer->serialize( $projectsEntity, 'json', [
'groups' => [
"project.selectable.list"
]
]));
return $this->json([
"projects" => $projects
], Response::HTTP_OK, [], []);
}
/**
* @param Customer|null $customer
* @param Projects|null $project
* @param StatusCodes $codes
* @param SerializerInterface $serializer
* @param AisDate $aisDate
* @param TranslatorInterface $translator
* @param int|null $project_id
* @return Response
* @throws \Exception
* @Route("/core-joinable-project/{customer_slug}/{project_id}", name="core_joinable_project", methods={"POST"}, defaults={"project_id":null})
* @ParamConverter("project", options={"mapping":{"project_id":"id"}})
* @ParamConverter("customer", options={"mapping":{"customer_slug":"slug"}})
*/
public function fetchCoreJoinableProject( ?Customer $customer, ?Projects $project, StatusCodes $codes, SerializerInterface $serializer, AisDate $aisDate, TranslatorInterface $translator, ?int $project_id ): Response{
if( !$project ){
return $this->json([
'message' => $translator->trans('Project not found!'),
"severity" => "error",
"variant"=>"snackbar"
], Response::HTTP_NOT_FOUND );
}
$serializedProject = json_decode( $serializer->serialize( $project, 'json', [
'groups' => [
'stakeholder.selected.core.project.manage'
]
]));
return $this->json([
"customStatus" => $this->coreProjectPrettyStatusData( $project, $customer, $aisDate, $translator ),
"project" => $serializedProject,
'updatePath' => $this->generateUrl('customer_join_to_project', ['slug'=>$customer->getSlug()])
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [ ]
]);
}
/**
* @Route("/save-project/{project_id}", name="save_project", defaults={"project_id": null })
* @ParamConverter("project", options={"mapping":{"project_id": "id"}})
* @param Projects|null $project
* @param EntityManagerInterface $manager
* @param AisDate $aisDate
* @param SerializerInterface $serializer
* @param TranslatorInterface $translator
* @param Request $request
* @return Response
* @throws \Exception
*/
public function save( ?Projects $project, EntityManagerInterface $manager, AisDate $aisDate, SerializerInterface $serializer, TranslatorInterface $translator, Request $request, int $project_id = null ): Response
{
$params = $request->request;
#dd($params);
// @deprecated this mode use user_rights
// /**@var $userRole AccessRoles */
// $userRole =$this->getUser()->getUserAccessedRoles()->filter(function(/**@var $item AccessRoles*/$item){
// return $item->getAccessType()->getName() === 'Project';
// })->first();
//
// /**@var $user User */
// $user = $this->getUser();
//
// $userAccess = $user->getUserRights();
//
//
//
//
// if( !$userRole ){
// return $this->json([
// 'message' => $translator->trans('Access role required for this operation.'),
// "severity" => "error",
// "variant"=>"snackbar"
// ], Response::HTTP_NOT_ACCEPTABLE );
// }
try{
if( $project_id && !$project ){
return $this->json([
"message" => $translator->trans('Project not found!') ,
"severity"=>"warning"
], Response::HTTP_NOT_FOUND);
}
if( !$project ){
// Check same ID already created
$projectIdFound = $manager->getRepository( Projects::class )->findOneBy(['project_id' => $params->get('project_id')]);
if($projectIdFound){
return $this->json([
"message" => $params->get('project_id') . ' ' . $translator->trans(', Project-ID already added, please try another one!') ,
"severity"=>"warning"
], Response::HTTP_UNAUTHORIZED);
}
$project = new Projects();
$project
->setProjectId( $params->get('project_id'))
->setCreatedAt( new \DateTimeImmutable('now'));
}
$project->setProjectId($params->get('project_id'));
/**@var $countryEntity Countries*/
$countryEntity = null;
if( intval($params->get('country')) ){
$countryEntity = $manager->getRepository(Countries::class)->find($params->get('country'));
}
$project
->setName( $params->get('name') )
->setStartAt( new \DateTimeImmutable($params->get('start_at')))
->setEndAt( $params->get('end_at') ? new \DateTimeImmutable($params->get('end_at')) : null )
// ->setCost(floatval($params->get('cost')) ? $params->get('cost') : null )
// // ->setLongitude($params->get('longitude'))
// // ->setLatitude($params->get('latitude'))
// // ->setScanDistance(intval($params->get('scan_distance')) ? $params->get('scan_distance') : null )
// ->setRewardTime(intval($params->get('reward_time')) ? $params->get('reward_time') : null )
// ->setWorkPause( intval($params->get('work_pause')) ? $params->get('work_pause') : null )
// ->setWorkingTimeStart($params->get('working_time_start'))
// ->setWorkingTimeStop($params->get('working_time_stop'))
// ->setAddress($params->get('address'))
// ->setCodePostal($params->get('code_postal'))
->setTown($params->get('town'))
->setCountry( $countryEntity )
;
if(!empty($params->get('invoice_type'))){
$invoice_type = $manager->getRepository(InvoiceType::class)->find($params->get('invoice_type'));
$project->setInvoiceType($invoice_type);
}
$projectSettings = $project->getProjectSettings();
$target_profit = intval($params->get('target_profit')) ?? 0;
$material_budget = intval($params->get('material_budget')) ?? 0;
if( !$projectSettings ){
$projectSettings = new ProjectSettings();
}
$projectSettings
->setTargetProfit($target_profit)
->setMaterialBudget($material_budget)
->setTimesheetBudget(100 - ($target_profit + $material_budget));
$project->setProjectSetting($projectSettings);
if( !empty($params->get('owner'))){
$owner = $manager->getRepository(ProjectOwner::class)->find($params->get('owner'));
$project->setOwner($owner);
}
$collectionRequiresErrors = [];
if($params->get('project_branches') === null) {
$collectionRequiresErrors[] = [
'message' => $translator->trans('At least one branch is required.'),
'severity' => SeverityInterface::WARNING
];
}
if($params->get('dependent_qualifications') === null) {
$collectionRequiresErrors[] = [
'message' => $translator->trans('At least one qualification is required.'),
'severity' => SeverityInterface::WARNING
];
}
if($params->get('dependent_certificates') === null) {
$collectionRequiresErrors[] = [
'message' => $translator->trans('At least one certificate is required.'),
'severity' => SeverityInterface::WARNING
];
}
if(count($collectionRequiresErrors)){
return $this->json([
'errors' => $collectionRequiresErrors
], Response::HTTP_NOT_ACCEPTABLE);
}
$project = $this->manageProjectQualifications($project, $manager, $params->get('dependent_qualifications') );
$project = $this->manageProjectCertificates($project, $manager, $params->get('dependent_certificates') );
$this->appendBranchToProject( $project, $manager, (array)$params->get('project_branches') );
$manager->persist( $project );
$manager->flush();
$manager->refresh($project);
} catch (\Exception $exception) {
return $this->json([
'message' => 'Error by core project save ' . $exception->getMessage()
], Response::HTTP_UNAUTHORIZED);
}
$project_ = json_decode($serializer->serialize( $project, 'json', [
'groups' => [
'project.base',
'project.branches',
'project.expenses',
'project.owner',
'project.qualifications',
'project.certificates',
'project.orders',
"project.details.orders"
]
]), true );
return $this->json([
"message"=>$translator->trans('Project added successfully'),
"severity" => "success",
"project" => $project_,
"classify" => $params->get('classify')
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => []
] );
}
/**
* @Route("/save-partial-append-branches-to-project/{project_id}", name="save_partial_append_branches_to_project", defaults={"project_id": null })
* @ParamConverter("project", options={"mapping":{"project_id": "id"}})
* @param Projects|null $project
* @param EntityManagerInterface $manager
* @param AisDate $aisDate
* @param SerializerInterface $serializer
* @param TranslatorInterface $translator
* @param Request $request
* @return Response
* @throws \Exception
*/
public function savePartialAppendBranches( ?Projects $project, EntityManagerInterface $manager, SerializerInterface $serializer, TranslatorInterface $translator, Request $request, int $project_id = null ): Response{
$params = $request->request;
#dd($params->all());
$project = $this->appendBranchToProject( $project, $manager, (array)$params->get('project_branches') );
$manager->persist( $project );
$manager->flush();
$manager->refresh($project);
$project_ = json_decode($serializer->serialize( $project, 'json', [
'groups' => [
'project.base',
'project.branches',
'project.expenses',
'project.owner',
'project.qualifications',
'project.certificates',
'project.orders'
]
]), true );
return $this->json([
"message"=>$translator->trans('Project added successfully'),
"severity" => "success",
"project" => $project_
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => []
] );
}
/**
* @Route("/fetch/{project_id}", name="project_fetch", defaults={"project_id": null}, methods={"POST", "GET"})
* @ParamConverter("project", options={"mapping":{"project_id": "id"}})
* @param Projects|null $project
* @param EntityManagerInterface $manager
* @param SerializerInterface $serializer
* @return Response
*/
public function fetch( ?Projects $project, EntityManagerInterface $manager, SerializerInterface $serializer ): Response
{
#dd(12);
/*return $this->json([
"message"=>"Error",
"severity" => "error"
], Response::HTTP_NOT_FOUND, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => []
] );*/
// dd($project->getProjectBranches()->toArray());
$countries = $manager->getRepository(Countries::class)->findAll();
/**@var $qualificationsRepo QualificationRepository*/
$qualificationsRepo = $manager->getRepository(Qualification::class);
$qualifications = $qualificationsRepo->fetchWeak(); // All
/**@var $certificatesRepo CertificatesRepository*/
$certificatesRepo = $manager->getRepository(Certificates::class);
$certificates = $certificatesRepo->fetchWeakByName(); // All
/**@var $certificateGroupsRepo CertificatesGroups*/
$certificateGroups = $manager->getRepository(CertificatesGroups::class)->findAll();
/**@var $projectBranchesRepo BranchesRepository */
$projectBranchesRepo = $manager->getRepository(Branches::class);
$branches = $projectBranchesRepo->findAll(); // All
/**@var $projectOwners ProjectOwner*/
$projectOwnersRepo = $manager->getRepository(ProjectOwner::class);
$projectOwners = $projectOwnersRepo->findAll(); // All
/**@var $projectOwners ProjectOwner*/
$invoiceTypesRepo = $manager->getRepository(InvoiceType::class);
$invoiceTypes = $invoiceTypesRepo->findAll(); // All
$project_ = $serializer->serialize( $project, 'json', [
'groups' => [
'project.base',
'project.branches',
'project.expenses',
'project.owner',
'project.qualifications',
'project.certificates',
'project.settings',
'project.setting.core',
'project.orders',
"project.details.orders",
// "project.details.orders.expenses",
// "project.orders.expense.base",
"project.orders.expense.positions",
"project.orders.expense.position.base",
"project_order@stock_issues",
"stock_issue@core",
]
]);
$countries_ = $serializer->serialize( $countries, 'json', [ 'groups' => ['countries.base']]);
$branches_ = $serializer->serialize( $branches, 'json', ['groups' => ['branches.base', 'branches.location.base']]);
$project_owners = $serializer->serialize( $projectOwners, 'json', ['groups' => ['project.owner']]);
$invoice_types = $serializer->serialize( $invoiceTypes, 'json', ['groups' => ['invoice.type.base']]);
$certificate_groups = $serializer->serialize( $certificateGroups, 'json', ['groups' => ['certificate.group.base']]);
$certificate_groups = json_decode($certificate_groups, true);
$project = json_decode( $project_ );
$countries = json_decode( $countries_ );
$branches = json_decode( $branches_ );
$project_owners = json_decode( $project_owners );
$invoice_types = json_decode( $invoice_types );
#dd($project);
#dd($project);
return $this->json([
"certificates"=>$certificates,
"certificate_groups" => $certificate_groups,
"qualifications"=>$qualifications,
'project'=>$project,
'countries'=>$countries,
'branches_collection' => $branches,
'project_owners' => $project_owners,
'invoice_types' => $invoice_types
], Response::HTTP_OK );
}
/**
* @deprecated
* info for Stakeholder not more Use fetch direct Project!
* @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"})
* @param Request $request
* @param RgbToHex $rgbToHex
* @param EntityManagerInterface $manager
* @param TimesheetReaderInterface $timesheetReader
* @param ProjectStakeholders|null $projectStakeholder
* @param SerializerInterface $serializer
* @param PdfOutputTimesheet $pdfOutputTimesheet
* @param StatusCodes $codes
* @param TranslatorInterface $translator
* @param int $project_stakeholder_id
* @return Response
* @ParamConverter("projectStakeholder", options={"mapping":{"project_stakeholder_id":"id"}})
*/
public function _wait_for_check_stakeholderTimesheet(Request $request, RgbToHex $rgbToHex, EntityManagerInterface $manager, TimesheetReaderInterface $timesheetReader, ?ProjectStakeholders $projectStakeholder, SerializerInterface $serializer, PdfOutputTimesheet $pdfOutputTimesheet, StatusCodes $codes, TranslatorInterface $translator, int $project_stakeholder_id ): Response
{
$timesheets = null;
$years = $request->request->get('years');
$is_guest = $request->request->get('is_guest');
$projectJoinedEmployees = $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest, $projectStakeholder){
// if( $is_guest !== "true" ){
// return $stakeholder->getId() === $projectStakeholder->getId();
// }
return $stakeholder;
})->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest, $projectStakeholder ){
return $stakeholder->getWorkerInProjects()->getValues();
});
$serializedWorkersInProject = json_decode($serializer->serialize( $projectJoinedEmployees , 'json', [
'groups' => [
'timesheet.for.stakeholder'
],
AbstractNormalizer::IGNORED_ATTRIBUTES => [
// 'worker_timesheets'
]
]) , true );
#dd($serializedWorkersInProject);
$serializedWorkersInProject = call_user_func_array('array_merge', $serializedWorkersInProject);
/// Filtered For Current Project
$collection = new ArrayCollection($serializedWorkersInProject);
$accessedYears = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
if( $years ) {
$accessedYears = json_decode($years); // <-- Should as param
}
// Overwrite for another process
$years = [];
$timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
// Manipulate color to Hex
$item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
return $item;
});
// Initial Values
$timesheetReader
->setTimesheetStatusCollection($timesheetStatus)
// ->setProjectStakeholders( $projectStakeholder );
->readerPathManager( $projectStakeholder->getProject(), null, null );
#dd($collection);
array_map(function( $accessedYear ) use ( &$years, $is_guest, $collection, $timesheetReader, $timesheetStatus, &$final_times, &$final_costs ){
$yearly_times = [];
$yearly_costs = [];
$final_month_times = [];
$final_costs = [];
#dd($collection);
// Done Empty Workers for current year
$workers = [];
// Project Stakeholder workers Collection Loop
$collection->filter(function($workerActivity) use ($is_guest){
return $workerActivity; // $workerActivity['worker_activity']['guest'] === "1" && $is_guest === "true";
})->map(function($workerActivity) use (
&$yearly,
&$workers,
$accessedYear,
$timesheetReader,
$timesheetStatus,
&$yearly_times,
&$yearly_costs,
&$final_month_times,
&$final_costs
){
$_worker = [
"id" => $workerActivity['worker_activity']["id"],
"name" => $workerActivity['worker_activity']['worker']["name"],
"surname" => $workerActivity['worker_activity']['worker']["surname"],
"customer" => $workerActivity['worker_activity']['customer']["company"],
"guest" => $workerActivity['worker_activity']['guest']
];
// Worker Timesheet Source
$foundedYear = array_filter( $workerActivity['worker_activity']['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
return $timesheetForYear['year'] === $accessedYear;
});
// Update Worker Element with timesheet
// try{
if( $foundedYear ){
$foundedYear = array_values($foundedYear);
$foundedYear = $foundedYear[0];
$pattern = '/^m\d+_d\d+?$/';
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
$activeColumns = array_values($activeColumns);
try{
foreach ($foundedYear as $key => $item ) {
if( !in_array($key, $activeColumns) ){
unset($foundedYear[$key]);
}
}
}catch (\Exception $exception ){
dd($exception->getMessage());
}
$months = $monthsFinal = [];
// Loop Months
foreach ( range(1, 12) as $monthIndex ) {
$timesheetReader->setMonth($monthIndex);
$workerMonthTimeCollection = $workerMonthCostCollection = $workerMonthInactiveTimeCollection = $workerMonthInactiveCostCollection = [];
$pattern = '/m' . $monthIndex . '_d\d/';
// Get days of current month
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
foreach ( $activeColumns as $dayKey ) {
$timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
// $readData = $timesheetReader->readTimeExtend();
#dump($foundedYear[$dayKey]);
$readData = $timesheetReader->readTimeExtendRolesBasic();
#dump($readData);
if( array_key_exists($timesheetReader::KEY_TIME_PROP, $readData )){
switch ($readData[$timesheetReader::KEY_COST_TYPE]){
case $timesheetReader::KEY_COST_TYPE_ACTIVE:
$workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
$workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
break;
case $timesheetReader::KEY_COST_TYPE_INACTIVE:
$workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
$workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
break;
}
}
}
// Employee month
$months[$monthIndex] = [
"times" => array_sum($workerMonthTimeCollection),
"costs" => array_sum($workerMonthCostCollection),
];
// Inactive Times
$monthsFinal[$monthIndex] = [
"times" => array_sum(array_merge($workerMonthInactiveTimeCollection, $workerMonthTimeCollection)),
"costs" => array_sum(array_merge($workerMonthInactiveCostCollection, $workerMonthInactiveCostCollection)),
];
// Final month
// $final_month_times[$monthIndex][] =
}
$_worker["months"] = $months;
$_worker["months_final"] = $monthsFinal;
$_worker["yearTimes"] = array_sum(array_map( function ( $month ){
return floatval($month['times']);
}, $months ));
$_worker["yearCosts"] = array_sum(array_map( function ( $month ){
return floatval($month['costs']);
}, $months ));
$yearly_times[] = $_worker["yearTimes"];
$yearly_costs[] = $_worker["yearCosts"];
$workers[] = $_worker;
}
});
dump(array_sum($yearly_times));
// Append created worker to accessed year
$years[$accessedYear]['workers'] = $workers;
$years[$accessedYear]['times'] = array_sum($yearly_times);
$years[$accessedYear]['costs'] = array_sum($yearly_costs);
if($yearly_times > 0 ){
dump($years);
}
}, $accessedYears );
#dd(array_sum(array_map(function($item){ return $item['times']; }, $years )));
#dump($final_times);
#dump($final_costs);
#dd();
#dd($is_guest);
# dd($years);
try{
$output = null;
$pdfOutputTimesheet->setPrintedBy( $this->getUser()->getEmail());
$output = $pdfOutputTimesheet->stakeholderTimesheet(
$translator->trans('Timesheet') . ' ' . $projectStakeholder->getProject()->getName() . ' ' . $projectStakeholder->getCustomer()->getCompany(),
$projectStakeholder->getCustomer()->getCompany() . ' in ' . $projectStakeholder->getProject()->getName(),
$years,
array_sum(array_map(function($item){ return $item['times']; }, $years )),
array_sum(array_map(function($item){ return $item['costs']; }, $years )),
'F'
);
if( $output->code !== Response::HTTP_OK ){
return $this->json([
'message' => $output->message,
"severity" => "error"
], Response::HTTP_CONFLICT );
}
} catch (\Exception $exception){
return $this->json([
'message' => $exception->getMessage(),
"severity" => "error"
], Response::HTTP_CONFLICT );
}
return $this->json([
'message' => $translator->trans('Timesheet created successfully!'),
"severity" => "success",
'output'=>$output
]);
}
private function chartValueGetter( $value, $useOnePercent = false ){
return is_numeric($value) ? ($useOnePercent ? $value / 100 : $value) : 0;
}
/**
* @Route("/evaluate-profit-margin/{project_id}", name="app_project_evaluate_profit_margin", defaults={"project_id"=null})
* @ParamConverter("project", options={"mapping":{"project_id": "id"}})
*/
public function evaluateProfitMargin(?Projects $project, TranslatorInterface $translator): Response {
$netRevenues = [];
$netProfitMargins = [];
$netExpenses = [];
$netHoursCostSpent = [];
$netHoursSpent = [];
$netProfit = [];
$chartGroups = [];
$chartGroupColors = [];
// Chart Groups Data
// Worked Times Data of all Contructions Managers
$chartGroupsData[] = ["data" => []]; // Spent Times
$chartGroupsData[] = ["data" => []]; // Revenue
$chartGroupsData[] = ["data" => []]; // Expenses
$chartGroupsData[] = ["data" => []]; // Cost Spent
$chartGroupsData[] = ["data" => []]; // Profit
$chartGroupsDataset = []; // Spent Times
$profitMargins = [];
if( !$project ){
return $this->json([
'message' => $translator->trans('Project not found!'),
"severity" => "warning"
], Response::HTTP_CONFLICT );
}
// Calculate
try{
$project->getProjectOrders()->map(function (/**@var ProjectOrders $projectOrder*/$projectOrder) use (
&$profitMargins,
&$netRevenues,
&$netExpenses,
&$netHoursCostSpent,
&$netHoursSpent,
&$chartGroups,
&$chartGroupColors,
&$chartGroupsData,
$project,
&$chartGroupsDataset,
$translator
){
$defaultAverageProfitMargin = 20;
$profitMargin = $projectOrder->getTargetProfitAsPercent() ?? $defaultAverageProfitMargin;
$profitMargins[] = $profitMargin;
if(is_null($profitMargin)){
dump("Profit margin is null for {$projectOrder->getId()}");
}
else if ( $profitMargin <> 20 ) {
dump("Profit margin of order {$projectOrder->getId()} {$profitMargin}");
}
$netRevenues[] = $projectOrder->getOrderPrise();
$projectOrder->getProjectOrderExpensePositions()
->filter(function(/**@var ProjectOrderExpensePositions $expensePosition */$expensePosition){
return !is_null($expensePosition->getAmount());
})->map(function(/**@var ProjectOrderExpensePositions $expensePosition */$expensePosition) use (&$netExpenses){
// return $expensePosition->getAmount() ? floatval($expensePosition->getAmount()) : 0;
$netExpenses[] = $expensePosition->getAmount() ? floatval($expensePosition->getAmount()) : 0;
});
$netHoursSpent[] = $projectOrder->getHoursSpent();
$netHoursCostSpent[] = $projectOrder->getCostSpent();
// Chart Grouplarini belirle
$foundedOrderLead = array_filter($chartGroups, function(/**@var User $user*/$user) use($projectOrder) {
return $projectOrder->getOrderLead() && $user
&& $user->getId() === $projectOrder->getOrderLead()->getId();
});
if(!$foundedOrderLead){
$chartGroups[] = $projectOrder->getOrderLead();
$r = rand(100, 255); // 100-255
$g = rand(100, 255); // 100-255
$b = rand(100, 255); // 100-255
$chartGroupColors[] = "rgb({$r}, {$g}, {$b})";
// Chart Group Data yi olustur order lead a ait
$_hoursSpent = [];
$_workedCostSpent = [];
$_revenues = [];
$_expenses = [];
$project->getProjectOrders()
->filter(function(/**@var ProjectOrders $_projectOrder*/$_projectOrder) use ($projectOrder) {
return $projectOrder->getOrderLead() && (!$_projectOrder->getOrderLead() || $_projectOrder->getOrderLead()->getId()
=== $projectOrder->getOrderLead()->getId());
})
->map(function(/**@var ProjectOrders $_projectOrder*/$_projectOrder) use (
&$_hoursSpent,
&$_workedCostSpent,
&$_revenues,
&$_expenses
)
{
$__expense_pos_amounts = $_projectOrder->getProjectOrderExpensePositions()
->map(function (/**@var ProjectOrderExpensePositions $expensePosition*/ $expensePosition ){
return !is_null($expensePosition->getAmount()) ? floatval($expensePosition->getAmount() ) : 0;
})->toArray();
// Total Expenses for Lead assigned orders
$__expenses = array_reduce( $__expense_pos_amounts , function($carry, $item){
return $carry + $item;
}, 0 );
$_workedCostSpent[] = $_projectOrder->getCostSpent();
$_hoursSpent[] = $_projectOrder->getHoursSpent();
$_revenues[] = $_projectOrder->getOrderPrise();
$_expenses[] = $__expenses;
}) ;
$_chartGroupsDataHoursSpent = array_reduce($_hoursSpent, function($carry, $item){
return $carry + $item;
}, 0 );
$_chartGroupsDataRevenue = array_reduce($_revenues, function($carry, $item){
return $carry + $item;
}, 0 );
$_chartGroupsDataExpense = array_reduce($_expenses, function($carry, $item){
return $carry + $item;
}, 0 );
$_chartGroupsDataWorkedCost = array_reduce($_workedCostSpent, function($carry, $item){
return $carry + $item;
}, 0 );
$_profit = $_chartGroupsDataRevenue - ( $_chartGroupsDataExpense + $_chartGroupsDataWorkedCost);
$chartGroupsData[0]["data"][] = is_numeric($_chartGroupsDataHoursSpent) ? $_chartGroupsDataHoursSpent : 0;
$chartGroupsData[1]["data"][] = is_numeric($_chartGroupsDataRevenue) ? $_chartGroupsDataRevenue / 100 : 0;
$chartGroupsData[2]["data"][] = is_numeric($_chartGroupsDataExpense) ? $_chartGroupsDataExpense / 100 : 0;
$chartGroupsData[3]["data"][] = is_numeric($_chartGroupsDataWorkedCost) ? $_chartGroupsDataWorkedCost / 100 : 0;
$chartGroupsData[4]["data"][] = is_numeric($_profit) ? $_profit / 100 : 0;
#dd($projectOrder->getOrderLead());
// $scoped = $this->getUser()->getUserScopedItems()->filter(function(/**@var $scopedItem UserScopedItem*/$scopedItem){
// return $scopedItem->getAccessFor() === 'project_chart';
// })->first();
/**@var $user User*/
$user = $this->getUser();
$scoped = $user->getUserScopedItems()->filter(function(/**@var $scopedItem UserScopedItem*/$scopedItem){
return $scopedItem->getScopedItem()->getCategory() === ModulesAccessTypes::E_MODULES_SCOPED_CATEGORIES_PROJECT && $scopedItem->getScopedItem()->getType() === ModulesAccessTypes::E_MODULES_SCOPED_TYPES_CHART;
})->first();
$onlyOwned = $scoped && $scoped->isOnlyOwned();
$ownedData = null;
try{
if(!is_null($projectOrder->getOrderLead())){
if( !is_null($projectOrder->getOrderLead()->getUser()) ){
$ownedData = $this->getUser()->getId() === $projectOrder->getOrderLead()->getUser()->getId();
}
}
} catch (\Exception $e) {
}
// $ownedData = true;
// $chartGroupsDataset[] = [
// 'timesheet' => is_numeric($_chartGroupsDataHoursSpent) ? $_chartGroupsDataHoursSpent : 0,
// 'revenue' => is_numeric($_chartGroupsDataRevenue) ? $_chartGroupsDataRevenue / 100 : 0,
// 'expenses' => is_numeric($_chartGroupsDataExpense) ? $_chartGroupsDataExpense / 100 : 0,
// 'employee_cost' => is_numeric($_chartGroupsDataWorkedCost) ? $_chartGroupsDataWorkedCost / 100 : 0,
// 'profit' => is_numeric($_profit) ? $_profit / 100 : 0,
// // 'owner' => substr($projectOrder->getOrderLead()->getName(), 0 ,1 ) . '. ' . $projectOrder->getOrderLead()->getSurname(),
// 'owner' => $projectOrder->getOrderLead()->getName() . ' ' . $projectOrder->getOrderLead()->getSurname(),
// // 'ownerId' => $projectOrder->getOrderLead()->getId()
// // '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())
// 'isLocked' => $ownedData ? false : $onlyOwned,
// 'ownedData' => $ownedData,
// 'onlyOwned' => $onlyOwned,
// 'userId' => $this->getUser()->getId(),
// 'orderLeadUserId' => $projectOrder->getOrderLead()->getUser()->getId()
// ];
$chartGroupsDataset[] = [
'timesheet' => $this->chartValueGetter( $_chartGroupsDataHoursSpent, false),
'revenue' => $this->chartValueGetter($_chartGroupsDataRevenue),
'expenses' => $this->chartValueGetter($_chartGroupsDataExpense),
'employee_cost' => $this->chartValueGetter($_chartGroupsDataWorkedCost),
'profit' => $this->chartValueGetter($_profit),
// 'owner' => substr($projectOrder->getOrderLead()->getName(), 0 ,1 ) . '. ' . $projectOrder->getOrderLead()->getSurname(),
'owner' => $projectOrder->getOrderLead() ? ( $projectOrder->getOrderLead()->getName() . ' ' . $projectOrder->getOrderLead()->getSurname() ) : "",
'ownerId' => $projectOrder->getOrderLead() && $projectOrder->getOrderLead()->getId(),
// 'locked' => $userScopped && ( $userScopped->isOnlyOwned() && $userScopped->getUser()->getId() !== $projectOrder->getOrderLead()->getUser()->getId())
'isLocked' => $ownedData ? false : $onlyOwned,
];
}
});
#dd();
// Net Gelir
$netRevenue = array_reduce($netRevenues, function($carry, $item){
return $carry + $item;
}, 0);
// Yapilan Harcama
$netExpense = array_reduce($netExpenses, function($carry, $item){
try{
return $carry + $item;
} catch (\Exception $exception){
dump($carry);
}
}, 0);
// Harcanan Is Gucu Saat
$netHourSpent = array_reduce($netHoursSpent, function($carry, $item){
// dd($carry);
return $carry + $item;
}, 0);
// Harcanan Is Gucu Saat Fiyat
$netHourCostSpent = array_reduce($netHoursCostSpent, function($carry, $item){
return $carry + $item;
}, 0);
// Profit Ortalama
$averageProfitMargin = floatval(number_format(array_reduce($profitMargins, function($carry, $item){
return $carry + $item;
}, 0) / count($profitMargins), 2));
// Net Kazanc
$netProfit = $netRevenue - ( $netExpense + $netHourCostSpent);
// Bekelnen Kar orani
$idealerProfit = $netRevenue * $averageProfitMargin / 100;
// Kazanc'a gore son kar margi
$netProfitMargin = $netProfit * $averageProfitMargin / $idealerProfit;
#dd($translator->trans('Timesheet'));
return $this->json([
'message' => $translator->trans('The financial state of the last project has been calculated successfully'),
'Revenue' => $netRevenue,
'AverageProfitMargin' => $averageProfitMargin,
'Expense' => $netExpense,
'HourSpent' => $netHourSpent,
'HourCostSpent' => $netHourCostSpent,
'IdealerProfit' => $idealerProfit,
'NetProfit' => $netProfit,
'ProfitMargin' => $netProfitMargin,
// Only Name for Chart group
'ChartGroups' => array_map(function(/**@var User $user*/ $user ){
return $user ? substr($user->getName(), 0, 1) . '. ' . $user->getSurname() : "No name";
}, $chartGroups),
'ChartGroupsData' => $chartGroupsData,
'ChartGroupColors' => $chartGroupColors,
'ChartGroupsDataset' => $chartGroupsDataset,
'ChartGroupsDatasetLabels' => [
["dataKey" => 'timesheet', "label" => $translator->trans('Timesheet')],
["dataKey" => 'revenue', "label" => $translator->trans('Revenue')],
["dataKey" => 'expenses', "label" => $translator->trans('Expenses')],
["dataKey" => 'employee_cost', "label" => $translator->trans('Employee cost')],
["dataKey" => 'profit', "label" => $translator->trans('Profit')],
]
], Response::HTTP_OK );
} catch (\Exception $exception ){
return $this->json([
"message" => $exception->getMessage(),
"severity" => "error"
]);
}
}
/**
* @deprecated
* info for Stakeholder not more Use fetch direct Project!
* @Route("/project-stakeholder-timesheet-pdf-as-project/{project_stakeholder_id}", name="project_stakeholder_timesheet_pdf_as_project", methods={"POST", "GET"})
* @param Request $request
* @param RgbToHex $rgbToHex
* @param EntityManagerInterface $manager
* @param TimesheetReaderInterface $timesheetReader
* @param ProjectStakeholders|null $projectStakeholder
* @param SerializerInterface $serializer
* @param PdfOutputTimesheet $pdfOutputTimesheet
* @param StatusCodes $codes
* @param TranslatorInterface $translator
* @param int $project_stakeholder_id
* @return Response
* @ParamConverter("projectStakeholder", options={"mapping":{"project_stakeholder_id":"id"}})
*/
public function stakeholderTimesheet(Request $request, RgbToHex $rgbToHex, EntityManagerInterface $manager, TimesheetReaderInterface $timesheetReader, ?ProjectStakeholders $projectStakeholder, SerializerInterface $serializer, PdfOutputTimesheet $pdfOutputTimesheet, StatusCodes $codes, TranslatorInterface $translator, int $project_stakeholder_id ): Response
{
$timesheets = null;
$years = $request->request->get('years');
$is_guest = $request->request->get('is_guest');
$projectJoinedEmployees = $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest, $projectStakeholder){
// if( $is_guest !== "true" ){
// return $stakeholder->getId() === $projectStakeholder->getId();
// }
#dump(count($stakeholder->getWorkerInProjects()));
return $stakeholder;
})->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest, $projectStakeholder ){
#dump(count($stakeholder->getWorkerInProjects()));
return $stakeholder->getWorkerInProjects()->getValues();
});
#dd();
$serializedWorkersInProject = json_decode($serializer->serialize( $projectJoinedEmployees , 'json', [
'groups' => [
'timesheet.for.stakeholder'
],
AbstractNormalizer::IGNORED_ATTRIBUTES => [
// 'worker_timesheets'
]
]) , true );
#dd($serializedWorkersInProject);
$serializedWorkersInProject = call_user_func_array('array_merge', $serializedWorkersInProject);
#dd($serializedWorkersInProject);
/// Filtered For Current Project
$collection = new ArrayCollection($serializedWorkersInProject);
$accessedYears = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
if( $years ) {
$accessedYears = json_decode($years); // <-- Should as param
}
// Overwrite for another process
$years = [];
$timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
// Manipulate color to Hex
$item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
return $item;
});
// Initial Values
$timesheetReader
->setTimesheetStatusCollection($timesheetStatus)
// ->setProjectStakeholders( $projectStakeholder );
->readerPathManager( $projectStakeholder->getProject(), null, null );
#dd($collection);
array_map(function( $accessedYear ) use ( &$years, $is_guest, $collection, $timesheetReader, $timesheetStatus, &$final_times, &$final_costs ){
$yearly_times = [];
$yearly_costs = [];
$final_month_times = [];
$final_costs = [];
#dd($collection);
// Done Empty Workers for current year
$workers = [];
// Project Stakeholder workers Collection Loop
$collection->filter(function($workerActivity) use ($is_guest){
return $workerActivity; // $workerActivity['worker_activity']['guest'] === "1" && $is_guest === "true";
})->map(function($workerActivity) use (
&$yearly,
&$workers,
$accessedYear,
$timesheetReader,
$timesheetStatus,
&$yearly_times,
&$yearly_costs,
&$final_month_times,
&$final_costs
){
$_worker = [
"id" => $workerActivity['worker_activity']["id"],
"name" => $workerActivity['worker_activity']['worker']["name"],
"surname" => $workerActivity['worker_activity']['worker']["surname"],
"customer" => $workerActivity['worker_activity']['customer']["company"],
"guest" => $workerActivity['worker_activity']['guest']
];
// Worker Timesheet Source
$foundedYear = array_filter( $workerActivity['worker_activity']['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
return $timesheetForYear['year'] === $accessedYear;
});
// Update Worker Element with timesheet
// try{
if( $foundedYear ){
$foundedYear = array_values($foundedYear);
$foundedYear = $foundedYear[0];
$pattern = '/^m\d+_d\d+?$/';
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
$activeColumns = array_values($activeColumns);
try{
foreach ($foundedYear as $key => $item ) {
if( !in_array($key, $activeColumns) ){
unset($foundedYear[$key]);
}
}
}catch (\Exception $exception ){
dd($exception->getMessage());
}
$months = $monthsFinal = [];
// Loop Months
foreach ( range(1, 12) as $monthIndex ) {
#dump($monthIndex);
$timesheetReader->setMonth($monthIndex);
$workerMonthTimeCollection = $workerMonthCostCollection = $workerMonthInactiveTimeCollection = $workerMonthInactiveCostCollection = [];
$pattern = '/m' . $monthIndex . '_d\d/';
// Get days of current month
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
#dump($activeColumns);
foreach ( $activeColumns as $dayKey ) {
$timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
// $readData = $timesheetReader->readTimeExtend();
#dump($foundedYear[$dayKey]);
$readData = $timesheetReader->readTimeExtendRolesBasic();
if( array_key_exists($timesheetReader::KEY_TIME_PROP, $readData )){
if($readData[$timesheetReader::KEY_ABSENCE_SHORT_KEY_PROP] === "P"){
#dump($readData);
$workerMonthTimeCollection[] = floatval($readData[$timesheetReader::KEY_TIME_PROP]);
$workerMonthCostCollection[] = floatval($readData[$timesheetReader::KEY_COST]);
}
// switch ($readData[$timesheetReader::KEY_COST_TYPE]){
// case $timesheetReader::KEY_COST_TYPE_ACTIVE:
// $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
// $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
// break;
// case $timesheetReader::KEY_COST_TYPE_INACTIVE:
// $workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
// $workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
// break;
// }
}
}
// Employee month
$months[$monthIndex] = [
"times" => array_sum($workerMonthTimeCollection),
"costs" => array_sum($workerMonthCostCollection),
];
// Inactive Times
$monthsFinal[$monthIndex] = [
"times" => array_sum(array_merge($workerMonthInactiveTimeCollection, $workerMonthTimeCollection)),
"costs" => array_sum(array_merge($workerMonthInactiveCostCollection, $workerMonthInactiveCostCollection)),
];
// Final month
// $final_month_times[$monthIndex][] =
}
$_worker["months"] = $months;
$_worker["months_final"] = $monthsFinal;
$_worker["yearTimes"] = array_sum(array_map( function ( $month ){
return floatval($month['times']);
}, $months ));
$_worker["yearCosts"] = array_sum(array_map( function ( $month ){
return floatval($month['costs']);
}, $months ));
$yearly_times[] = $_worker["yearTimes"];
$yearly_costs[] = $_worker["yearCosts"];
$workers[] = $_worker;
}
});
#dump(array_sum($yearly_times));
// Append created worker to accessed year
$years[$accessedYear]['workers'] = $workers;
$years[$accessedYear]['times'] = array_sum($yearly_times);
$years[$accessedYear]['costs'] = array_sum($yearly_costs);
if($yearly_times > 0 ){
dump($years);
}
}, $accessedYears );
#dd();
#dd(array_sum(array_map(function($item){ return $item['times']; }, $years )));
#dump($final_times);
#dump($final_costs);
#dd();
#dd($is_guest);
# dd($years);
try{
$output = null;
$pdfOutputTimesheet->setPrintedBy( $this->getUser()->getEmail());
$output = $pdfOutputTimesheet->stakeholderTimesheet(
$translator->trans('Timesheet') . ' ' . $projectStakeholder->getProject()->getName() . ' ' . $projectStakeholder->getCustomer()->getCompany(),
$projectStakeholder->getCustomer()->getCompany() . ' in ' . $projectStakeholder->getProject()->getName(),
$years,
array_sum(array_map(function($item){ return $item['times']; }, $years )),
array_sum(array_map(function($item){ return $item['costs']; }, $years )),
'F'
);
if( $output->code !== Response::HTTP_OK ){
return $this->json([
'message' => $output->message,
"severity" => "error"
], Response::HTTP_CONFLICT );
}
} catch (\Exception $exception){
return $this->json([
'message' => $exception->getMessage(),
"severity" => "error"
], Response::HTTP_CONFLICT );
}
return $this->json([
'message' => $translator->trans('Timesheet created successfully!'),
"severity" => "success",
'output'=>$output
]);
}
/**
* @Route("/all-timesheets-pdf-as-year-for-customer/{customer_slug}/{year}", name="all_timesheets_pdf_as_year_for_customer", methods={"POST"}, defaults={"year"=null})
* @param Request $request
* @param TimesheetReaderInterface $timesheetReader
* @param SerializerInterface $serializer
* @param Customer $customer
* @param RgbToHex $rgbToHex
* @param PdfOutputTimesheet $pdfOutputTimesheet
* @param StatusCodes $codes
* @param TranslatorInterface $translator
* @param EntityManagerInterface $manager
* @param int|null $year
* @return Response
* @ParamConverter("customer", options={"mapping":{"customer_slug":"slug"}})
*/
public function customerTimesheet(Request $request, TimesheetReaderInterface $timesheetReader, SerializerInterface $serializer, Customer $customer, RgbToHex $rgbToHex, PdfOutputTimesheet $pdfOutputTimesheet, StatusCodes $codes, TranslatorInterface $translator, EntityManagerInterface $manager, ?int $year = null): Response
{
$timesheets = null;
$years = $request->request->get('years');
$is_guest = $request->request->get('is_guest');
$timesheetStatus = (new ArrayCollection($manager->getRepository(TimesheetStatus::class)->findAll() ?? []))->map( function(/**@var $item TimesheetStatus*/ $item ) use ($rgbToHex){
// Manipulate color to Hex
$item->setAbsenceColorHex($rgbToHex->convertWithArray($item->getAbsenceBrColor()));
return $item;
});
$accessedYears = [(new DateTimeImmutable('now'))->format('Y')]; // Initial
if( $years ) {
$accessedYears = json_decode($years); // <-- Should as param
}
// Overwrite for another process
$years = [];
$timesheetReader
->setTimesheetStatusCollection($timesheetStatus);
try{
array_map(function( $accessedYear ) use ( &$finalCost, &$years, $timesheetReader, $customer, $is_guest, $serializer ){
// Done Empty Workers for current year
// Project Stakeholder workers Collection Loop
$stakeholders = [];
// Visit every Customer Project
$customer->getProjectStakeholders()->map(function(/**@var $projectStakeholder ProjectStakeholders*/$projectStakeholder) use ($is_guest, &$years, &$finalCost, &$yearly, &$workers, &$stakeholders, $timesheetReader, $accessedYear, $serializer) {
// initial
$stakeholder["id"] = $projectStakeholder->getId();
$stakeholder["projectName"] = $projectStakeholder->getProject()->getName();
$stakeholder["year"] = $accessedYear;
$stakeholder['months'] = [];
$timesheetReader->readerPathManager( $projectStakeholder->getProject(), null, null );
$workers = [];
$projectJoinedEmployees = $projectStakeholder->getProject()->getStakeholders()->filter(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ($is_guest, $projectStakeholder){
if( $is_guest !== "true" ){
return $stakeholder->getId() === $projectStakeholder->getId();
}
return $stakeholder;
})->map(function(/**@var $stakeholder ProjectStakeholders */$stakeholder) use ( $is_guest, $projectStakeholder ){
return $stakeholder->getWorkerInProjects()->getValues();
});
$serializedWorkersInProject = json_decode($serializer->serialize( $projectJoinedEmployees , 'json', [
'groups' => [
'timesheet.for.stakeholder'
],
AbstractNormalizer::IGNORED_ATTRIBUTES => [
// 'worker_timesheets'
]
]) , true );
$serializedWorkersInProject = call_user_func_array('array_merge', $serializedWorkersInProject);
// $stakeholders[]["id"] = $projectStakeholder->getId();
// $stakeholders[]["projectName"] = $projectStakeholder->getProject()->getName();
// $stakeholders[]["year"] = $accessedYear;
array_map( function($workerInProject) use ( $projectStakeholder, &$finalCost, &$stakeholder, $timesheetReader, $accessedYear ){
$workerActivity = $workerInProject['worker_activity'];
// Worker Timesheet Source
$foundedYear = array_filter( $workerActivity['worker_timesheets'], function( $timesheetForYear ) use ( $accessedYear ){
return $timesheetForYear['year'] === intval($accessedYear);
});
// Update Worker Element with timesheet
if( $foundedYear ){
#dump($foundedYear);
$foundedYear = array_values($foundedYear);
$foundedYear = $foundedYear[0];
$pattern = '/^m\d+_d\d+?$/';
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
$activeColumns = array_values($activeColumns);
foreach ($foundedYear as $key => $item ) {
if( !in_array($key, $activeColumns) ){
unset($foundedYear[$key]);
}
}
// unset($foundedYear['year']);
foreach ( range(1, 12) as $monthIndex ) {
$timesheetReader->setMonth($monthIndex);
$workerMonthTimeCollection = $workerMonthCostCollection = [];
$pattern = '/m' . $monthIndex . '_d\d/';
// Get days of current month
$activeColumns = array_filter( array_keys($foundedYear), function($item) use ($pattern) {
return preg_match($pattern, $item);
});
foreach ( $activeColumns as $dayKey ) {
$timesheetReader->setDayKey($dayKey)->setData($foundedYear[$dayKey]);
// $readData = $timesheetReader->readTimeExtend();
$readData = $timesheetReader->readTimeExtendRolesBasic();
if( array_key_exists($timesheetReader::KEY_TIME_PROP, $readData )){
switch ($readData[$timesheetReader::KEY_COST_TYPE]) {
case $timesheetReader::KEY_COST_TYPE_ACTIVE:
$workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
$workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
break;
case $timesheetReader::KEY_COST_TYPE_INACTIVE:
// $workerMonthInactiveTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
// $workerMonthInactiveCostCollection[] = $readData[$timesheetReader::KEY_COST];
break;
}
// $workerMonthTimeCollection[] = $readData[$timesheetReader::KEY_TIME_PROP];
// $workerMonthCostCollection[] = $readData[$timesheetReader::KEY_COST];
}
}
$stakeholder['months'][$monthIndex][] = [
"times" => array_sum($workerMonthTimeCollection),
"costs" => array_sum($workerMonthCostCollection),
];
}
}
}, $serializedWorkersInProject );
/**
* $stakeholder['months'] has multiple times Worker defined
* For example month 11 Has 3 worker defined each of worker Has For Project and Month
* 2 Values times and Cost Should they values collected
* On Bottom Doing this operation
*/
foreach ($stakeholder['months'] as $monthIndex => $monthEntries ) {
$monthTimesSimplify = []; // Stakeholder Months has multiple Month times (Worker Entry) do it simplify
$monthCostsSimplify = []; // Stakeholder Months has multiple Month Costs (Worker Entry) do it simplify
foreach ($monthEntries as $monthEntry) {
$monthTimesSimplify[] = $monthEntry['times'];
$monthCostsSimplify[] = $monthEntry['costs'];
}
$stakeholder['months'][$monthIndex] = [
'times' => array_sum($monthTimesSimplify),
'costs' => array_sum($monthCostsSimplify)
];
}
/**
* For Project Months values have been simplified
* Now Collect All simplified Times And costs from Entry
*/
$projectForYearFinalTimesCollection = [];
$projectForYearFinalCostsCollection = [];
foreach ($stakeholder['months'] as $monthIndex => $simplifiedMonth ) {
$projectForYearFinalTimesCollection[] = floatval( $simplifiedMonth['times'] );
$projectForYearFinalCostsCollection[] = floatval( $simplifiedMonth['costs'] );
}
$stakeholder['yearTimes'] = array_sum($projectForYearFinalTimesCollection);
$stakeholder["yearCosts"] = array_sum($projectForYearFinalCostsCollection);
$stakeholders[] = $stakeholder;
});
$years[$accessedYear] = $stakeholders;
}, $accessedYears );
} catch (\Exception $exception ){
return $this->json([
'message' => $exception->getMessage(),
"severity" => "error"
], Response::HTTP_CONFLICT );
}
#dd();
#dd($years);
try{
if( !is_null($finalCost)){
foreach ($finalCost as $_year => $yearValue ) {
$finalCost[$_year] = array_sum($yearValue);
}
}
} catch (\Exception $exception ){
return $this->json([
'message' => $exception->getMessage(),
"severity" => "success"
], Response::HTTP_NOT_FOUND );
}
$output = null;
$pdfOutputTimesheet->setPrintedBy( $this->getUser()->getEmail());
$output = $pdfOutputTimesheet->customerTimesheet(
$translator->trans('Timesheet') . ' ' . $customer->getCompany(),
$translator->trans('Timesheet Plan by Years of') . ' ' . $customer->getCompany(),
$years,
$finalCost,
'F'
);
return $this->json([
'message' => $translator->trans('Timesheet created successfully!'),
"severity" => "success",
'output'=>$output
]);
}
/**
* Relocate project toArchive | toTrash
* @Route("/re-classify/{classify}/{project_id}", name="app_api_project_toarchive", methods={"POST"}, options={"project_id": null})
* @ParamConverter("project", options={"mapping": {"project_id": "id"}})
*/
public function reClassify ( ?Projects $project, EntityManagerInterface $manager, Request $request, SerializerInterface $serializer, TranslatorInterface $translator, string $classify = "all", int $project_id = null): Response {
$processedProjectIds = $request->request->get('projects') ?? [];
/**@var $user User*/
$user = $this->getUser();
#dd($project_id);
if(!$project_id && !count($processedProjectIds)){
return $this->json([
"message" => $translator->trans("Project not defined"),
"severity" => "warning"
]);
}
if(!$project && !count($processedProjectIds)){
return $this->json([
"message" => $translator->trans("Project not found"),
"severity" => "error"
]);
}
$projectIds = [];
if(count($processedProjectIds)){
$projectIds = $processedProjectIds;
} else {
$projectIds[] = $project->getId();
}
try {
$projects = [];
if(count($processedProjectIds)){
$projects = $manager->getRepository(Projects::class)->findBy(["id" => $processedProjectIds]);
} else {
$projects[] = $project;
}
// dd($projects);
(new ArrayCollection($projects))->map(function(/**@var Projects $project*/ $project) use ($classify, $manager) {
switch ($classify){
case "archive":
$project->setIsArchived(true);
break;
case "unarchive":
$project->setIsArchived(null);
break;
case "trash":
$project->setIsRecycle(true);
break;
case "untrash":
$project->setIsRecycle(null);
break;
}
$manager->persist($project);
$manager->flush();
dump($project->getId(), $classify, $project->isRecycle(), $project->isArchived());
});
#dd();
} catch (\Exception $exception) {
return $this->json([
"message"=> $exception->getMessage(),
"severity" => "error"
], $exception->getCode() );
}
// $archived = [];
// $trashed = [];
// $active = [];
// $projects = new ArrayCollection($manager->getRepository(Projects::class)->findAll());
// $projects->map( function( /**@var Projects $project */$project) use(&$archived, &$trashed, &$active){
// if( !$project->isRecycle()){
// if($project->isArchived()){
// $archived[] = $project;
// } else {
// $active[] = $project;
// }
// } else {
// $trashed[] = $project;
// }
// });
dd('reClassify_12');
return $this->json([
"message"=> "Successfully",
"severity" => "success",
"projectIds" => $projectIds,
// "disposed" => [
// "archived" => $this->serializeProjects($archived, $serializer),
// "trashed" => $this->serializeProjects($trashed, $serializer),
// "active" => $this->serializeProjects($active, $serializer)
// ]
"disposed" => $this->getUserAccessedProjects( $user, $manager, $serializer )
], Response::HTTP_OK);
}
/**
* @Route("/payment-report/{project_id}", name="app_api_project_payment_report", methods={"POST"}, options={"project_id": null})
* @ParamConverter("project", options={"mapping": {"project_id": "id"}})
* @throws \Exception
*/
public function paymentReport(?Projects $project, PdfOutputProjectPaymentReport $pdfOutputProjectPaymentReport, TranslatorInterface $translator ): Response {
if(!$project){
return $this->json([
"message" => "Project not found",
"severity" => "error"
], Response::HTTP_NOT_FOUND);
}
$collected = [];
$totalInvoice = [];
$totalPaidInvoice = [];
$dataColumnNames = [
$translator->trans('Order number'),
$translator->trans('Position-ID'),
$translator->trans('Price'),
$translator->trans('Sent at'),
$translator->trans('Completed!'),
$translator->trans('Elapsed days'),
$translator->trans('Voucher'),
$project->getOwner()->getCompany() . " " . $translator->trans('Order number'),
$project->getOwner()->getCompany() . " " . $translator->trans('CP'),
$project->getOwner()->getCompany() . " " . $translator->trans('Telephone'),
];
$dataColumnWidths = [
70, 50, 70,70,70,70,80,100,80,122
];
$project->getProjectOrders()->map( function(/**@var $projectOrder ProjectOrders*/ $projectOrder) use (&$collected, &$totalInvoice, &$totalPaidInvoice ){
// $collected[] = $projectOrder->getInvoiceType() ? $projectOrder->getInvoiceType()->getName(): "No invouce type for " . $projectOrder->getOrderNr();
if($projectOrder->getInvoiceType()){
if( $projectOrder->getInvoiceType()->getName() === "Voucher" ){
$projectOrder->getProjectOrderUndertakings()->map(function(/**@var $orderUndertaking ProjectOrderUndertakings*/ $orderUndertaking) use (&$collected, &$totalInvoice, &$totalPaidInvoice ){
// if( is_null($orderUndertaking->getCompletedAt()) ){
if( is_null($orderUndertaking->getVoucher()) ){
$completed_at = null;
// $waiting_day = $orderUndertaking->getSentAt()->diff(new DateTimeImmutable('now'))->days;
// if( $orderUndertaking->getVoucher()){
// if( $orderUndertaking->getVoucher()->getCompletedAt() ){
// $completed_at = $orderUndertaking->getVoucher()->getCompletedAt();
// $waiting_day = $orderUndertaking->getSentAt()->diff($completed_at)->days;
// $totalPaidInvoice[] = floatval($orderUndertaking->getPrice());
// }
// }
// $waiting_day = $orderUndertaking->getSentAt()->diff()->days;
$waiting_day = (new DateTimeImmutable('now'))->diff( $orderUndertaking->getSentAt())->days;
// $remaining = 60 - $waiting_day;
$remaining = $waiting_day;
$color = "transparent";
$txtColor = "black";
if ($remaining <= 10) {
// 50'den büyükse
$color = "#5cffa1";
} elseif ($remaining <= 30) {
$color = "#ffd800";
// 21-50 arası
} elseif ($remaining < 50) {
// 1-20 arası
$color = "#ff6a00";
} else {
// 0 veya daha az
$color = "red";
$txtColor = "white";
}
if($completed_at){
$txtColor = "white";
$color = "green";
}
$data = [
"order_nr" => $orderUndertaking->getProjectOrder()->getOrderNr(),
"price" => $orderUndertaking->getPrice(),
"position_nr" => $orderUndertaking->getPositionNr(),
"sent_at" => $orderUndertaking->getSentAt(),
"completed_at" => $completed_at,
// wait for day 60
// "remaining_day" => 60 - $waiting_day,
"remaining_day" => $waiting_day,
"color" => $color,
"txtColor" => $txtColor,
"voucher_nr" => $orderUndertaking->getVoucher() ? $orderUndertaking->getVoucher()->getVoucherNr() : "",
// Isi verene ait siparis numarasi
"order_owner_order_nr" => $orderUndertaking->getProjectOrder()->getProjectOwnerOrderNr(),
"order_owner_contact" => [
"name" => $orderUndertaking->getProjectOrder()->getContactPerson()->getName(),
"surname" => $orderUndertaking->getProjectOrder()->getContactPerson()->getSurname(),
"tel" => $orderUndertaking->getProjectOrder()->getContactPerson()->getTel(),
]
];
$totalInvoice[] = floatval($orderUndertaking->getPrice());
$collected[] = $data;
}
});
}
}
});
$missingPayment = array_sum($totalInvoice) - array_sum($totalPaidInvoice);
$output = null;
$pdfOutputProjectPaymentReport->setPrintedBy( $this->getUser()->getEmail());
$output = $pdfOutputProjectPaymentReport->report(
$project->getName(),
$translator->trans('Payment status'),
$project->getProjectId(),
$collected,
$dataColumnNames,
$dataColumnWidths,
[
"total" => array_sum($totalInvoice),
"paid" => array_sum($totalPaidInvoice),
"missing" => $missingPayment,
],
'F'
);
return $this->json([
"message" => "Successfully",
"severity" => "success",
"data" => $collected,
"output" => $output,
"dataColumnNames" => $dataColumnNames
], Response::HTTP_OK );
}
// ⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆
/**
* @Route("/all-timesheets-pdf-as-year/{year}", name="all_timesheets_pdf_as_year", methods={"POST"}, defaults={"year"=null})
* @param PdfOutputTimesheet $pdfOutputTimesheet
* @param StatusCodes $codes
* @param TranslatorInterface $translator
* @param EntityManagerInterface $manager
* @param int|null $year
* @return Response
*/
public function allTimesheetPDFAsYear( PdfOutputTimesheet $pdfOutputTimesheet, StatusCodes $codes, TranslatorInterface $translator, EntityManagerInterface $manager, ?int $year = null): Response
{
$timesheets = null;
if (!is_null($year)) {
$timesheets = $manager->getRepository(WorkerTimesheet::class)->findBy(["year" => $year]);
}
$parsedData = null;
if ($timesheets) {
$parsedData = (new ArrayCollection($timesheets))->map(function (/**@var $workerTimesheet WorkerTimesheet */ $workerTimesheet) {
return [
"name" => substr($workerTimesheet->getWorker()->getName(), 0,1) . ". " . $workerTimesheet->getWorker()->getSurname() . ' by ' . $workerTimesheet->getWorker()->getWorkerActuallyActivity()->getCustomer()->getCompany(),
"timesheetMonths" => $workerTimesheet->getWorkerTimeInPlaceMonths()
];
});
}
// $this->workerTimeSheetDir . DIRECTORY_SEPARATOR . $filename . '.pdf'
# return $this->json($pdfOutputTimesheet->resultForYear('Suleyman Topaloglu', $year, $parsedData, 'D' ));
$output = null;
try{
$pdfOutputTimesheet->setPrintedBy( $this->getUser()->getEmail());
$output = $pdfOutputTimesheet->resultForYear(
'Romon GmbH for ' . $year,
$year,
$parsedData,
'F'
);
} catch (\Exception $exception){
$codes->set( 401 );
return $this->json([
'message' => $exception->getMessage(),
"severity" => "error"
]);
}
return $this->json([
'message' => $translator->trans('Timesheet created successfully!'),
"severity" => "success",
"output" => $output
]);
}
/**
* @Route("/add-project-addendum-cost/{project_id}", name="add_project_addendum_cost", methods={"POST"}, defaults={"project_id": null})
* @param Projects|null $project
* @param StatusCodes $codes
* @param AisDate $aisDate
* @param TranslatorInterface $translator
* @param EntityManagerInterface $manager
* @param Request $request
* @param int $project_id
* @return Response
* @throws \Exception
* @ParamConverter("project", options={"mapping":{"project_id":"id"}})
*/
public function addProjectAddendumCost( ?Projects $project, StatusCodes $codes, AisDate $aisDate, TranslatorInterface $translator, EntityManagerInterface $manager, Request $request, int $project_id ): Response
{
if( !$project ){
$codes->set(404);
return $this->json([
'message' => $translator->trans('Project not found!'),
"severity" => "error",
"variant"=>"snackbar"
]);
}
$params = $request->request;
$costObj = new ProjectAddendumCosts();
$costObj
->setAmount($params->get('amount'))
->setAddedAt(new \DateTimeImmutable($params->get('added_at')))
->setAddedBy($this->getUser())
// ->setProject($project)
;
$project->addProjectAddendumCost($costObj);
try{
// $manager->persist( $costObj );
$manager->persist( $project );
$manager->flush();
$manager->refresh( $project );
} catch (\Exception $exception){
$codes->set( 401 );
return $this->json([
'message' => $exception->getMessage(),
"severity" => "error"
]);
}
return $this->json([
'message' => $translator->trans('Addendum Cost added successfully!'),
"severity" => "success",
"totalCost" => $project->getTotalCost(),
'addedCost'=>[
'id' => $costObj->getId(),
'project' => $project->getId(),
'addedAt' => $costObj->getAddedAt(),
'addedBy' => [
"id" => $costObj->getAddedBy()->getId(),
"username" => $costObj->getAddedBy()->getEmail(),
],
'amount' => $costObj->getAmount(),
]
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]);
}
// Upload excel
/**
* @Route("/upload-cost-list/{project_id}", name="upload_cost_list", defaults={"project_id": null })
* @param Projects $project
* @param $uploadedFilesDir
* @param TranslatorInterface $translator
* @param EntityManagerInterface $manager
* @param StatusCodes $codes
* @param Request $request
* @return Response
*/
function uploadCostList( Projects $project, $uploadedFilesDir, TranslatorInterface $translator, EntityManagerInterface $manager, StatusCodes $codes, Request $request ): Response{
if(!$project){
return $this->json([
"message" => $translator->trans('Project not found'),
"severity" => "warning"
], Response::HTTP_NOT_FOUND );
}
$file = $request->files->get('costs_file');
if( !$file ){
$codes->set(Response::HTTP_NOT_FOUND);
return $this->json([
'code'=>404,
"message"=>$translator->trans('File not loaded'),
]);
}
#dd($file);
$filePathName = md5(uniqid()) . $file->getClientOriginalName();
// apply md5 function to generate an unique identifier for the file and concat it with the file extension
try {
$file->move( $uploadedFilesDir, $filePathName );
$spreadsheet = IOFactory::load( $uploadedFilesDir . DIRECTORY_SEPARATOR . $filePathName );
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, false );
// Delete file again!
// unlink($uploadedFilesDir . DIRECTORY_SEPARATOR . $filePathName );
// Check through is Correct file
$header = array_shift($sheetData); // $sheetData[0];
$source = [
"Status", "Int. Beleg-Nr." ,"Rechnungs-Nr." ,"Eingangsdatum" ,"Zahlungsstatus" ,
"Firmenname" ,"Zahlart" ,"Projekt" ,"Fällig am" ,"Bruttobetrag" ,"Offener Betrag" ,
"Projekt-Nr." ,"Kategorie" ,"Offene Überweisungen" ,"Zahlungsausgang"
];
if( count(array_diff($source, $header))){
return $this->json([
"message" => $translator->trans('Invalid file, file columns title does\'t compare with nested column title, please check your file, '),
"severity" => "info"
], Response::HTTP_UNAUTHORIZED );
}
$index_of_invoice_nr = array_search("Int. Beleg-Nr.", $source);
$index_of_project_id = array_search("Projekt-Nr.", $source);
$transfer_for = $request->request->get('transfer_for');
// Filter already in found
// $alreadyAdded = $project->getProjectExpenses()->map(function(/**@var $projectExpense ProjectExpense */ $projectExpense ) {
// return $projectExpense->getReceiptNr();
// })->toArray();
$alreadyAdded = (new ArrayCollection($manager->getRepository(ProjectExpense::class)->findAll()))->map(function(/**@var $projectExpense ProjectExpense */ $projectExpense ) {
return $projectExpense->getReceiptNr();
})->toArray();
#dd($alreadyAdded);
$addables = array_values(array_filter( $sheetData, function($item) use ( $index_of_invoice_nr, $index_of_project_id, $alreadyAdded, $transfer_for ){
#dd($item[$index_of_invoice_nr]);
return $transfer_for === "all" ?
!in_array($item[$index_of_invoice_nr], $alreadyAdded ) :
!in_array($item[$index_of_invoice_nr], $alreadyAdded ) && $item[$index_of_project_id] === $transfer_for ;
},ARRAY_FILTER_USE_BOTH ));
#dd($addables);
// Default chosen_ones all
$chosen_ones = array_map(function($item) use ( $index_of_invoice_nr ) {
return $item[$index_of_invoice_nr];
}, $addables);
#dd($chosen_ones);
// $addables = array_values(array_filter( $sheetData, function($item) use ( $index_of_invoice_nr, $alreadyAdded ){
// return !in_array($item[$index_of_invoice_nr], $alreadyAdded );
// },ARRAY_FILTER_USE_BOTH ));
#dd(array_values($addables));
} catch (FileException $e) {
return $this->json([
'code'=>$e->getCode(),
"message"=>$e->getMessage(),
]);
}
return $this->json([
"code" => Response::HTTP_OK,
"header" => $header,
"collection" => $addables,
"chosenOnes" => $chosen_ones,
"message"=>$translator->trans('Uploaded successfully'),
"fileName" => $filePathName
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
/**
* @Route("/upload-cost-list-transfer/{project_id}", name="upload_cost_list_transfer", defaults={"project_id": null })
* @param Projects $project
* @param $uploadedFilesDir
* @param EntityManagerInterface $manager
* @param TranslatorInterface $translator
* @param Request $request
* @return Response
* @throws \Exception
*/
function uploadCostListTransfer( Projects $project, $uploadedFilesDir, EntityManagerInterface $manager, TranslatorInterface $translator, Request $request ): Response
{
if (!$project) {
return $this->json([
"message" => $translator->trans('Project not found'),
"severity" => "warning"
], Response::HTTP_NOT_FOUND);
}
$chosen_ones = !empty($request->request->get('chosen_ones')) ? preg_split("/\,/", $request->request->get('chosen_ones') ) : [];
$file_name = $request->request->get('file_name');
$spreadsheet = IOFactory::load( $uploadedFilesDir . DIRECTORY_SEPARATOR . $file_name );
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, false );
// Delete file again!
// unlink($uploadedFilesDir . DIRECTORY_SEPARATOR . $filePathName );
$prepared = array_map( function( $selected ) use( $sheetData ){
$d = array_filter($sheetData, function($data) use ($selected){
return array_search($selected, $data);
});
return array_shift($d);
}, $chosen_ones );
if( !count($prepared) ){
return $this->json([
"message" => $translator->trans('Please select at last one transfer item'),
"severity" => "warning"
], Response::HTTP_UNAUTHORIZED);
}
#dd($request->request->all());
foreach ( $prepared as $item ) {
if( !empty($item[11] ) && $request->request->get('transfer_for') === "all" ){
$project = $manager->getRepository(Projects::class)->findOneBy(["project_id"=>$item[11]]);
#dd($project);
}
if( $project ){
$project_expense = new ProjectExpense();
$project_expense
->setStatus($item[0])
->setReceiptNr($item[1])
->setInvoiceNr($item[2])
->setReceiptAt(new \DateTimeImmutable($item[3]))
->setPaymentStatus($item[4])
->setCompanyName($item[5])
->setPaymentMethod($item[6])
->setProject($project)
->setDueAt(new \DateTimeImmutable($item[8]))
// ->setTotalAmount( money_format('%i', preg_replace("/\,/", "", $item[9] )))
->setTotalAmount( floatval(preg_replace("/,/", null, $item[9] ) ) )
// ->setOutstandingBalance( money_format('%i', preg_replace("/\,/", "", $item[10] )) )
->setOutstandingBalance( floatval(preg_replace("/,/", null, $item[10] ) ) )
->setCategory($item[12])
->setOpenTransfer($item[13])
->setPaidAt(new \DateTimeImmutable($item[14]));
$manager->persist($project_expense);
$project = null;
}
}
try{
$manager->flush();
} catch (\Exception $exception){
return $this->json([
"message" => $exception->getMessage(),
"severity" => "warning"
], Response::HTTP_NOT_FOUND);
}
return $this->json([
"message" => $translator->trans('Transfer successfully'),
"severity" => "warning"
], Response::HTTP_OK);
}
// Read excel
/**
* @Route("/read-uploaded-cost-list", name="read_uploaded_cost_list")
* @param $uploadedFilesDir
* @param Request $request
* @return Response
*/
function readUploadedCostList( $uploadedFilesDir, Request $request ): Response{
#dd($uploadedFilesDir);
$spreadsheet = IOFactory::load( $uploadedFilesDir . DIRECTORY_SEPARATOR . "Export_Eingangsrechnung.xls");
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, false );
dd($sheetData);
return $this->json(
[
"message" => "Successfully",
"severity" => "success"
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
// Transform
/**
* @Route("/transfer-uploaded-cost-list", name="transfer_uploaded_cost_list")
* @param Request $request
* @return Response
*/
function transferUploadedCostList( Request $request ): Response{
return $this->json(
[
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
/**
* @Route("/print-project-foreword/{project_id}", name="print_project_foreword", methods={"POST", "GET"})
* @ParamConverter("project", options={"mapping":{"project_id":"id"}})
* @param Projects $project
* @param Request $request
* @return Response
*/
function printProjectForeword( Projects $project, Request $request, PdfOutputTimesheet $pdfOutputTimesheet ): Response{
if( !$project ){
// Project not found!
return $this->json(
[
"message" => "Project not found",
"severity" => "error"
], Response::HTTP_NOT_FOUND, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
if( !$project->getQrCode() ){
return $this->json(
[
"message" => "Project QR-Core not ready please save project and try again",
"severity" => "warning",
], Response::HTTP_METHOD_NOT_ALLOWED, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
#dd($uploadedFilesDir);
$pdfOutputTimesheet->setPrintedBy('Suleyman Topaloglu');
$output = $pdfOutputTimesheet->printProjectForeword( $project, 'F' );
return $this->json(
[
"message" => "Successfully",
"severity" => "success",
'output'=>$output
], Response::HTTP_OK, [], [
AbstractNormalizer::IGNORED_ATTRIBUTES => [
]
]
);
}
}