619 lines
19 KiB
PHP
619 lines
19 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Ramcar\DayOfWeek;
|
|
use App\Entity\Rider;
|
|
use App\Entity\RiderSchedule;
|
|
use App\Entity\Hub;
|
|
use App\Entity\User;
|
|
use App\Entity\JobOrder;
|
|
|
|
use App\Service\FileUploader;
|
|
use App\Service\MQTTClient;
|
|
|
|
use Doctrine\ORM\Query;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
|
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
|
|
|
use Catalyst\MenuBundle\Annotation\Menu;
|
|
|
|
use DateTime;
|
|
|
|
class RiderController extends Controller
|
|
{
|
|
/**
|
|
* @Menu(selected="rider_list")
|
|
*/
|
|
public function index()
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.list', null, 'No access.');
|
|
|
|
return $this->render('rider/list.html.twig');
|
|
}
|
|
|
|
public function rows(Request $req)
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.list', null, 'No access.');
|
|
|
|
// get query builder
|
|
$qb = $this->getDoctrine()
|
|
->getRepository(Rider::class)
|
|
->createQueryBuilder('q');
|
|
|
|
// build expression now since we're reusing it
|
|
$hub_label = $qb->expr()->concat('hub.name', $qb->expr()->literal(' '), 'hub.branch');
|
|
|
|
// get datatable params
|
|
$datatable = $req->request->get('datatable');
|
|
|
|
// count total records
|
|
$tquery = $qb->select('COUNT(q)')
|
|
->leftJoin('q.hub', 'hub');
|
|
|
|
// add filters to count query
|
|
$this->setQueryFilters($datatable, $tquery, $hub_label);
|
|
|
|
$total = $tquery->getQuery()
|
|
->getSingleScalarResult();
|
|
|
|
// get current page number
|
|
$page = $datatable['pagination']['page'] ?? 1;
|
|
|
|
$perpage = $datatable['pagination']['perpage'];
|
|
$offset = ($page - 1) * $perpage;
|
|
|
|
// add metadata
|
|
$meta = [
|
|
'page' => $page,
|
|
'perpage' => $perpage,
|
|
'pages' => ceil($total / $perpage),
|
|
'total' => $total,
|
|
'sort' => 'asc',
|
|
'field' => 'id'
|
|
];
|
|
|
|
// build query
|
|
$query = $qb->select('q')
|
|
->addSelect($hub_label . 'as hub_name');
|
|
|
|
// add filters to query
|
|
$this->setQueryFilters($datatable, $query, $hub_label);
|
|
|
|
// check if sorting is present, otherwise use default
|
|
if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) {
|
|
$prefix = '';
|
|
|
|
if (!in_array($datatable['sort']['field'], ['hub_name']))
|
|
$prefix = 'q.';
|
|
|
|
$order = $datatable['sort']['sort'] ?? 'asc';
|
|
$query->orderBy($prefix . $datatable['sort']['field'], $order);
|
|
} else {
|
|
$query->orderBy('q.id', 'asc');
|
|
}
|
|
|
|
// get rows for this page
|
|
$obj_rows = $query->setFirstResult($offset)
|
|
->setMaxResults($perpage)
|
|
->getQuery()
|
|
->getResult();
|
|
|
|
// process rows
|
|
$rows = [];
|
|
foreach ($obj_rows as $orow) {
|
|
// add row data
|
|
$row['id'] = $orow[0]->getID();
|
|
$row['image_file'] = $orow[0]->getImageFile();
|
|
$row['first_name'] = $orow[0]->getFirstName();
|
|
$row['last_name'] = $orow[0]->getLastName();
|
|
$row['plate_number'] = $orow[0]->getPlateNumber();
|
|
$row['contact_num'] = $orow[0]->getContactNumber();
|
|
$row['hub_name'] = $orow['hub_name'];
|
|
|
|
// add row metadata
|
|
$row['meta'] = [
|
|
'update_url' => '',
|
|
'delete_url' => ''
|
|
];
|
|
|
|
// add crud urls
|
|
if ($this->isGranted('rider.update'))
|
|
$row['meta']['update_url'] = $this->generateUrl('rider_update', ['id' => $row['id']]);
|
|
if ($this->isGranted('rider.delete'))
|
|
$row['meta']['delete_url'] = $this->generateUrl('rider_delete', ['id' => $row['id']]);
|
|
|
|
$rows[] = $row;
|
|
}
|
|
|
|
// response
|
|
return $this->json([
|
|
'meta' => $meta,
|
|
'data' => $rows
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @Menu(selected="rider_list")
|
|
*/
|
|
public function addForm()
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.add', null, 'No access.');
|
|
|
|
$params['obj'] = new Rider();
|
|
$params['mode'] = 'create';
|
|
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
|
// get parent associations
|
|
$params['hubs'] = $em->getRepository(Hub::class)->findAll();
|
|
$params['days_of_week'] = DayOfWeek::getCollection();
|
|
|
|
// response
|
|
return $this->render('rider/form.html.twig', $params);
|
|
}
|
|
|
|
protected function setObject($obj, $req)
|
|
{
|
|
$obj->setFirstName($req->request->get('first_name'))
|
|
->setLastName($req->request->get('last_name'))
|
|
->setContactNumber($req->request->get('contact_no'))
|
|
->setPlateNumber($req->request->get('plate_number'))
|
|
->setImageFile($req->request->get('image_file'))
|
|
->setActive($req->request->get('flag_active') ? true : false)
|
|
->setUsername($req->request->get('username'));
|
|
}
|
|
|
|
public function addSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator)
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.add', null, 'No access.');
|
|
|
|
/*
|
|
error_log(print_r($req->request->all(), true));
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
*/
|
|
|
|
// create new row
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = new Rider();
|
|
|
|
// set and save values
|
|
$this->setObject($obj, $req);
|
|
|
|
// initialize error list
|
|
$error_array = [];
|
|
|
|
// get password inputs
|
|
$password = $req->request->get('password');
|
|
$confirm_password = $req->request->get('confirm_password');
|
|
|
|
// custom validation for password fields
|
|
if (!$password) {
|
|
$error_array['password'] = 'This value should not be blank.';
|
|
} else if ($password != $confirm_password) {
|
|
$error_array['confirm_password'] = 'Passwords do not match.';
|
|
} else {
|
|
// encode password
|
|
$enc = $ef->getEncoder(new User());
|
|
$encoded_password = $enc->encodePassword($req->request->get('password'), '');
|
|
|
|
// set password
|
|
$obj->setPassword($encoded_password);
|
|
}
|
|
|
|
// custom validation for associations
|
|
$hub_id = $req->request->get('hub');
|
|
|
|
if ($hub_id) {
|
|
$hub = $em->getRepository(Hub::class)
|
|
->find($hub_id);
|
|
|
|
if (empty($hub))
|
|
$error_array['hub'] = 'Invalid hub selected.';
|
|
else
|
|
$obj->setHub($hub);
|
|
}
|
|
|
|
// validate
|
|
$errors = $validator->validate($obj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
}
|
|
|
|
// save schedules
|
|
$days_of_week = DayOfWeek::getCollection();
|
|
|
|
$time_start_input = $req->request->get('time_start');
|
|
$time_end_input = $req->request->get('time_end');
|
|
$break_start_input = $req->request->get('break_start');
|
|
$break_end_input = $req->request->get('break_end');
|
|
$has_schedule = $req->request->get('has_schedule');
|
|
|
|
// intitialize has schedule to an array
|
|
if ($has_schedule == null)
|
|
$has_schedule = [];
|
|
|
|
foreach ($days_of_week as $key => $day) {
|
|
if (in_array($key, $has_schedule)) {
|
|
$serror_array = [];
|
|
|
|
$sobj = new RiderSchedule();
|
|
|
|
$sobj->setDayOfWeek($key)
|
|
->setTimeStart($time_start_input[$key])
|
|
->setTimeEnd($time_end_input[$key])
|
|
->setBreakStart($break_start_input[$key])
|
|
->setBreakEnd($break_end_input[$key])
|
|
->setRider($obj);
|
|
|
|
// validate
|
|
$errors = $validator->validate($sobj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$serror_array[$error->getPropertyPath() . "_" . $key] = $error->getMessage();
|
|
}
|
|
|
|
if (empty($serror_array)) {
|
|
$obj->addSchedule($sobj);
|
|
} else {
|
|
$error_array = array_merge($error_array, $serror_array);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if any errors were found
|
|
if (!empty($error_array)) {
|
|
// return validation failure response
|
|
return $this->json([
|
|
'success' => false,
|
|
'errors' => $error_array
|
|
], 422);
|
|
} else {
|
|
// validated! save the entity
|
|
$em->persist($obj);
|
|
$em->flush();
|
|
|
|
// return successful response
|
|
return $this->json([
|
|
'success' => 'Changes have been saved!'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Menu(selected="rider_list")
|
|
*/
|
|
public function updateForm($id)
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.update', null, 'No access.');
|
|
|
|
$params['mode'] = 'update';
|
|
|
|
// get row data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$row = $em->getRepository(Rider::class)->find($id);
|
|
|
|
// make sure this row exists
|
|
if (empty($row))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
|
// get parent associations
|
|
$params['hubs'] = $em->getRepository(Hub::class)->findAll();
|
|
$params['days_of_week'] = DayOfWeek::getCollection();
|
|
|
|
$params['obj'] = $row;
|
|
|
|
// response
|
|
return $this->render('rider/form.html.twig', $params);
|
|
}
|
|
|
|
public function updateSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator, $id)
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.update', null, 'No access.');
|
|
|
|
// get row data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = $em->getRepository(Rider::class)->find($id);
|
|
|
|
// make sure this row exists
|
|
if (empty($obj))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// set and save values
|
|
$this->setObject($obj, $req);
|
|
|
|
// initialize error list
|
|
$error_array = [];
|
|
|
|
// get password inputs
|
|
$password = $req->request->get('password');
|
|
$confirm_password = $req->request->get('confirm_password');
|
|
|
|
// custom validation for password fields
|
|
if ($password || $confirm_password) {
|
|
if ($password != $confirm_password) {
|
|
$error_array['confirm_password'] = 'Passwords do not match.';
|
|
} else {
|
|
// encode password
|
|
$enc = $ef->getEncoder(new User());
|
|
$encoded_password = $enc->encodePassword($req->request->get('password'), '');
|
|
|
|
// set password
|
|
$obj->setPassword($encoded_password);
|
|
}
|
|
}
|
|
|
|
// custom validation for associations
|
|
$hub_id = $req->request->get('hub');
|
|
|
|
if ($hub_id) {
|
|
$hub = $em->getRepository(Hub::class)
|
|
->find($hub_id);
|
|
|
|
if (empty($hub))
|
|
$error_array['hub'] = 'Invalid hub selected.';
|
|
else
|
|
$obj->setHub($hub);
|
|
} else {
|
|
$obj->clearHub();
|
|
}
|
|
|
|
// validate
|
|
$errors = $validator->validate($obj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
}
|
|
|
|
// save schedules
|
|
$days_of_week = DayOfWeek::getCollection();
|
|
|
|
$time_start_input = $req->request->get('time_start');
|
|
$time_end_input = $req->request->get('time_end');
|
|
$break_start_input = $req->request->get('break_start');
|
|
$break_end_input = $req->request->get('break_end');
|
|
$has_schedule = $req->request->get('has_schedule');
|
|
|
|
// intitialize has schedule to an array
|
|
if ($has_schedule == null)
|
|
$has_schedule = [];
|
|
|
|
foreach ($days_of_week as $key => $day) {
|
|
if (in_array($key, $has_schedule)) {
|
|
$serror_array = [];
|
|
|
|
$sobj = $em->getRepository(RiderSchedule::class)->findOneBy([
|
|
'rider' => $obj,
|
|
'day_of_week' => $key
|
|
]);
|
|
|
|
// create new schedule row if not found
|
|
if (empty($sobj)) {
|
|
$sobj = new RiderSchedule();
|
|
$sobj->setDayOfWeek($key)
|
|
->setRider($obj);
|
|
}
|
|
|
|
$sobj->setTimeStart($time_start_input[$key])
|
|
->setTimeEnd($time_end_input[$key])
|
|
->setBreakStart($break_start_input[$key])
|
|
->setBreakEnd($break_end_input[$key]);
|
|
|
|
// validate
|
|
$errors = $validator->validate($sobj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$serror_array[$error->getPropertyPath() . "_" . $key] = $error->getMessage();
|
|
}
|
|
|
|
if (empty($serror_array)) {
|
|
if (empty($sobj->getID()))
|
|
$obj->addSchedule($sobj);
|
|
} else {
|
|
$error_array = array_merge($error_array, $serror_array);
|
|
}
|
|
}
|
|
}
|
|
|
|
// cleanup
|
|
// delete all schedules not in list
|
|
$schedules = $obj->getSchedules();
|
|
foreach ($schedules as $schedule)
|
|
{
|
|
if (!in_array($schedule->getDayOfWeek(), $has_schedule))
|
|
{
|
|
$obj->removeSchedule($schedule);
|
|
$em->remove($schedule);
|
|
}
|
|
}
|
|
|
|
// check if any errors were found
|
|
if (!empty($error_array)) {
|
|
// return validation failure response
|
|
return $this->json([
|
|
'success' => false,
|
|
'errors' => $error_array
|
|
], 422);
|
|
} else {
|
|
// validated! save the entity
|
|
$em->flush();
|
|
|
|
// return successful response
|
|
return $this->json([
|
|
'success' => 'Changes have been saved!'
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function destroy($id)
|
|
{
|
|
$this->denyAccessUnlessGranted('rider.delete', null, 'No access.');
|
|
|
|
// get row data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$row = $em->getRepository(Rider::class)->find($id);
|
|
|
|
if (empty($row))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// delete this row
|
|
$em->remove($row);
|
|
$em->flush();
|
|
|
|
// response
|
|
$response = new Response();
|
|
$response->setStatusCode(Response::HTTP_OK);
|
|
$response->send();
|
|
}
|
|
|
|
public function uploadImage(Request $req, FileUploader $uploader)
|
|
{
|
|
// retrieve temporary info for file
|
|
$file = $req->files->get('image_file');
|
|
|
|
// upload the file
|
|
$filename = $uploader->upload($file);
|
|
|
|
// return response
|
|
return $this->json([
|
|
'success' => true,
|
|
'filename' => $filename
|
|
]);
|
|
}
|
|
|
|
// check if datatable filter is present and append to query
|
|
protected function setQueryFilters($datatable, &$query, $hub_label) {
|
|
if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) {
|
|
$query->where($hub_label . ' LIKE :filter')
|
|
->orWhere('q.first_name LIKE :filter')
|
|
->orWhere('q.last_name LIKE :filter')
|
|
->orWhere('q.contact_num LIKE :filter')
|
|
->orWhere('q.plate_number LIKE :filter')
|
|
->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%');
|
|
}
|
|
}
|
|
|
|
public function popupInfo(EntityManagerInterface $em, $id)
|
|
{
|
|
$rider = $em->getRepository(Rider::class)->find($id);
|
|
if ($rider == null)
|
|
return new Response('No rider data');
|
|
|
|
return $this->render('rider/popup.html.twig', [ 'rider' => $rider ]);
|
|
}
|
|
|
|
/**
|
|
* @ParamConverter("rider", class="App\Entity\Rider")
|
|
*/
|
|
public function riderActiveJO(EntityManagerInterface $em, MQTTClient $mclient, Rider $rider, $jo_id)
|
|
{
|
|
$jo = $em->getRepository(JobOrder::class)->find($jo_id);
|
|
$rider->setActiveJobOrder($jo);
|
|
$em->flush();
|
|
|
|
// TODO: trigger what needs triggering in rider app
|
|
$payload = [
|
|
'event' => 'cancelled',
|
|
'reason' => 'Reprioritization',
|
|
'jo_id' => $jo->getID(),
|
|
];
|
|
$mclient->sendRiderEvent($jo, $payload);
|
|
|
|
|
|
return $this->redirecttoRoute('rider_update', ['id' => $rider->getID()]);
|
|
}
|
|
|
|
/**
|
|
* @ParamConverter("rider", class="App\Entity\Rider")
|
|
* @ParamConverter("jo", class="App\Entity\JobOrder", options={"id": "jo_id"})
|
|
*/
|
|
public function priorityUpJO(EntityManagerInterface $em, Rider $rider, JobOrder $jo)
|
|
{
|
|
$jos = $rider->getOpenJobOrders();
|
|
|
|
// set new priority
|
|
$old_prio = $jo->getPriority();
|
|
$new_prio = $old_prio - 1;
|
|
$jo->setPriority($new_prio);
|
|
|
|
// go through all rider open JOs and set priority when needed
|
|
foreach ($jos as $rider_jo)
|
|
{
|
|
// check if it's the same
|
|
if ($rider_jo->getID() == $jo->getID())
|
|
continue;
|
|
|
|
// if priority is the same as old priority, move it down
|
|
if ($new_prio == $rider_jo->getPriority())
|
|
$rider_jo->setPriority($rider_jo->getPriority() + 1);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $this->redirecttoRoute('rider_update', ['id' => $rider->getID()]);
|
|
}
|
|
|
|
/**
|
|
* @ParamConverter("rider", class="App\Entity\Rider")
|
|
* @ParamConverter("jo", class="App\Entity\JobOrder", options={"id": "jo_id"})
|
|
*/
|
|
public function priorityDownJO(EntityManagerInterface $em, Rider $rider, JobOrder $jo)
|
|
{
|
|
$jos = $rider->getOpenJobOrders();
|
|
|
|
// set new priority
|
|
$old_prio = $jo->getPriority();
|
|
$new_prio = $old_prio + 1;
|
|
$jo->setPriority($new_prio);
|
|
|
|
// go through all rider open JOs and set priority when needed
|
|
foreach ($jos as $rider_jo)
|
|
{
|
|
// check if it's the same
|
|
if ($rider_jo->getID() == $jo->getID())
|
|
continue;
|
|
|
|
// if priority is the same as old priority, move it down
|
|
if ($new_prio == $rider_jo->getPriority())
|
|
$rider_jo->setPriority($rider_jo->getPriority() - 1);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $this->redirecttoRoute('rider_update', ['id' => $rider->getID()]);
|
|
}
|
|
|
|
/**
|
|
* @ParamConverter("rider", class="App\Entity\Rider")
|
|
*/
|
|
public function ajaxAvailable(EntityManagerInterface $em, Rider $rider)
|
|
{
|
|
//$jo = $rider->getRiderActiveJobOrder();
|
|
$jo_results = $rider->getActiveJobOrder();
|
|
if (empty($jo_results))
|
|
$avail = 'available';
|
|
else
|
|
$avail = 'unavailable';
|
|
|
|
$response = new Response(
|
|
$avail,
|
|
Response::HTTP_OK,
|
|
['content-type' => 'text/plain']
|
|
);
|
|
return $response;
|
|
}
|
|
}
|