<?php
namespace App\Controller\Api\v3;
use App\Controller\Api\Service\EmployeeActivityService;
use App\Controller\Api\Service\HourCapAnalysisService;
use App\Controller\Api\Service\PartnerService;
use App\Controller\Api\Service\ProjectService;
use App\Controller\Api\Service\ReferenceService;
use App\Controller\Api\Service\TimesheetService;
use App\Entity\WorkerTimesheet;
use App\Enum\SeverityInterface;
use App\Service\SerializeService\PartnerSerialize;
use App\Service\SerializeService\ProjectSerialize;
use App\Service\SerializeService\ReferenceSerialize;
use App\Service\SerializeService\TimesheetSerialize;
use App\Service\StreamingService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/api/v3/timesheet")
*/
class TimesheetController extends AbstractController
{
/**
* ✅
* @Route("/employees-with-master-data", name="api_v3_timesheet_employees_with_master_data")
* @param TranslatorInterface $translator
* @param EmployeeActivityService $employeeActivityService
* @param PartnerService $partnerService
* @param PartnerSerialize $partnerSerialize
* @param ProjectService $projectService
* @param ProjectSerialize $projectSerialize
* @param ReferenceSerialize $referenceSerialize
* @param ReferenceService $referenceService
* @param TimesheetService $timesheetService
* @param TimesheetSerialize $timesheetSerialize
* @return StreamedResponse
*/
public function employeesWithWithMasterData(TranslatorInterface $translator,
EmployeeActivityService $employeeActivityService,
PartnerService $partnerService, PartnerSerialize $partnerSerialize,
ProjectService $projectService, ProjectSerialize $projectSerialize,
ReferenceSerialize $referenceSerialize, ReferenceService $referenceService,
TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize
): StreamedResponse
{
$streamed = new StreamingService([
"localText" => ["completed" => $translator->trans('Loaded')]
]);
$streamed->appendStream(
"employees",
$translator->trans('Loading employees'),
function() use ($timesheetService, $timesheetSerialize){
$data = $timesheetService
->setParams(new InputBag([]))
->findByPayload();
return $timesheetSerialize->setEntity($data["dataset"])->serializeMonth($data["m"]);
}
);
$streamed->appendStream(
"partners",
$translator->trans('Loading partners'),
fn() => $partnerSerialize->setEntity($partnerService->fetchPartnersForMainList())->serializeFull()
);
$streamed->appendStream(
"projects",
$translator->trans('Loading projects'),
fn() => $projectSerialize->setEntity($projectService->fetchAll())->serializeForMainList()
);
$streamed->appendStream(
"timesheet_status",
$translator->trans('Loading ts statuses'),
fn() => $referenceSerialize->setEntity($referenceService->timesheetStatuses())->setGroups([
"timsheet@base"
])->render()
);
return $streamed->flush();
}
/**
* ✅
* @Route("/find-by-payload", name="api_v3_timesheet_find_by_year_and_month", methods={"POST"})
* @return StreamedResponse
* @throws \Exception
*/
public function findByPayload(TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize, Request $request ): Response {
$data = $timesheetService
->setParams($request->request)
->findByPayload();
$serialized = $timesheetSerialize->setEntity($data["dataset"])->serializeMonth($data['m']);
return $this->json([
"message" => "Success",
"severity" => "success",
"employees" => $serialized
], Response::HTTP_OK );
}
/**
* ✅
* @Route("/unregistered-employees", name="api_v3_timesheet_unregistered_employees", methods={"POST"})
* @return StreamedResponse
* @throws \Exception
*/
public function unregisteredEmployees(TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize, Request $request ): Response {
$data = $timesheetService
->setParams($request->request)
->unregisteredEmployees();
$serialized = $timesheetSerialize->setEntity($data["dataset"])->serializeMonth($data["m"]);
return $this->json([
"message" => "Success",
"severity" => "success",
"freeEmployees" => $serialized
], Response::HTTP_OK );
}
/**
* ✅
* @Route("/sync-register-employees", name="api_v3_timesheet_sync_register_employees", methods={"POST"})
* @return StreamedResponse
* @throws \Exception
*/
public function syncRegisterEmployees(TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize, Request $request ): Response {
$data = $timesheetService
->setParams($request->request)
->syncRegisterEmployees();
$ids = $data["dataset"]->map(fn($item) => $item->getId() );
$data = $timesheetService
->setParams($request->request)
->findByPayload($ids->toArray());
$serialized = $timesheetSerialize->setEntity($data["dataset"])->serializeMonth($data['m']);
#dd($serialized);
return $this->json([
"message" => "Success",
"severity" => "success",
"hotEmployees" => $serialized
], Response::HTTP_OK );
}
/**
* ✅
* @Route("/upsert", name="api_v3_timesheet_upsert", methods={"POST"})
* @return StreamedResponse
* @throws \Exception
*/
public function upsert(TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize, Request $request ): Response {
$processed = $timesheetService
->setParams($request->request)
->upsert();
if(!is_null($timesheetService->getException())){
return $this->json([
"message" => $timesheetService->getException()->getMessage(),
"severity" => SeverityInterface::ERROR
], Response::HTTP_NOT_ACCEPTABLE );
}
// Required WA_Id over Timesheet records
$ids = $processed->map(fn(WorkerTimesheet $item) => $item->getWorkerActivity()->getId() );
$period = json_decode($request->request->get('period'), true);
$domain = json_decode($request->request->get('domain'), true);
$domain = [
"project" => !is_null($domain["project"]) ? $domain["project"]["id"] : null,
"order" => !is_null($domain["order"]) ? $domain["order"]["id"] : null,
"branch" => !is_null($domain["branch"]) ? $domain["branch"]["id"] : null,
];
$newParams = array_merge($period, $domain);
$newParams = new InputBag($newParams);
$data = $timesheetService
->setParams($newParams)
->findByPayload($ids->toArray());
$serialized = $timesheetSerialize->setEntity($data["dataset"])->serializeMonth($data['m']);
return $this->json([
"message" => "Success",
"severity" => "success",
"hotEmployees" => $serialized
], Response::HTTP_OK );
}
/**
* ✅
* @Route("/movement", name="api_v3_timesheet_movement", methods={"POST"})
* @return StreamedResponse
* @throws \Exception
*/
public function movement(TimesheetService $timesheetService, TimesheetSerialize $timesheetSerialize, Request $request ): Response {
# $timesheetService->setEntity(new WorkerTimesheet())->setParams($request->request)->movement();
return $this->json([
"message" => "Success",
"severity" => "success",
"hotEmployees" => []
], Response::HTTP_OK );
}
/**
* ⚠️ GEÇİCİ — günlük 10 saat aşımı analizi ve taşıma önerisi (SALT OKUMA).
* Geçmiş kayıtlardaki aşımları bulur, fazlalığın hangi güne taşınabileceğini önerir.
* Hiçbir veriyi değiştirmez. Karar verildikten sonra bu route + servis + FE dialog silinir.
*
* @Route("/hour-cap-analysis", name="api_v3_timesheet_hour_cap_analysis", methods={"POST"})
* @param HourCapAnalysisService $hourCapAnalysisService
* @param Request $request
* @return Response
*/
public function hourCapAnalysis(HourCapAnalysisService $hourCapAnalysisService, Request $request): Response
{
$analysis = $hourCapAnalysisService
->setParams($request->request)
->analyze();
return $this->json([
"message" => "Success",
"severity" => "success",
"analysis" => $analysis
], Response::HTTP_OK );
}
}