577 lines
21 KiB
PHP
577 lines
21 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Ramcar\BaseController;
|
|
use App\Ramcar\ServiceType;
|
|
use App\Ramcar\JOStatus;
|
|
use App\Entity\JobOrder;
|
|
use App\Entity\BatteryManufacturer;
|
|
use App\Entity\Customer;
|
|
use App\Entity\CustomerVehicle;
|
|
use App\Entity\Outlet;
|
|
use App\Entity\Rider;
|
|
|
|
use App\Service\MapTools;
|
|
|
|
use Doctrine\ORM\Query;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
|
|
|
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
|
|
|
use DateTime;
|
|
|
|
class JobOrderController extends BaseController
|
|
{
|
|
public function incomingForm()
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_in.list', null, 'No access.');
|
|
|
|
$params = $this->initParameters('jo_in');
|
|
$params['obj'] = new JobOrder();
|
|
$params['mode'] = 'create';
|
|
$params['submit_url'] = $this->generateUrl('jo_in_submit');
|
|
$params['return_url'] = $this->generateUrl('jo_in');
|
|
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
|
// get parent associations
|
|
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
|
$params['customers'] = $em->getRepository(Customer::class)->findAll();
|
|
$params['outlet'] = $em->getRepository(Outlet::class)->findAll();
|
|
$params['rider'] = $em->getRepository(Rider::class)->findAll();
|
|
$params['service_types'] = ServiceType::getCollection();
|
|
$params['statuses'] = JOStatus::getCollection();
|
|
|
|
// response
|
|
return $this->render('job-order/form.html.twig', $params);
|
|
}
|
|
|
|
public function incomingSubmit(Request $req, ValidatorInterface $validator)
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_in.list', null, 'No access.');
|
|
|
|
// initialize error list
|
|
$error_array = [];
|
|
|
|
// create new row
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = new JobOrder();
|
|
|
|
// check if lat and lng are provided
|
|
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
|
|
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
|
|
}
|
|
|
|
// check if customer vehicle is set
|
|
if (empty($req->request->get('customer_vehicle'))) {
|
|
$error_array['customer_vehicle'] = 'No vehicle selected.';
|
|
} else {
|
|
// get customer vehicle
|
|
$cust_vehicle = $em->getRepository(CustomerVehicle::class)->find($req->request->get('customer_vehicle'));
|
|
|
|
if (empty($cust_vehicle)) {
|
|
$error_array['customer_vehicle'] = 'Invalid vehicle specified.';
|
|
}
|
|
}
|
|
|
|
if (empty($error_array)) {
|
|
// coordinates
|
|
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
|
|
|
|
// set and save values
|
|
$obj->setDateCreate(DateTime::createFromFormat("d M Y", $req->request->get('date_transaction')))
|
|
->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
|
|
->setCoordinates($point)
|
|
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
|
|
->setCreatedBy($this->getUser())
|
|
->setServiceType($req->request->get('service_type'))
|
|
->setCustomer($cust_vehicle->getCustomer())
|
|
->setCustomerVehicle($cust_vehicle)
|
|
->setSource('web')
|
|
->setStatus($req->request->get('status'))
|
|
->setDeliveryInstructions($req->request->get('delivery_instructions'))
|
|
->setAgentNotes($req->request->get('agent_notes'))
|
|
->setDeliveryAddress($req->request->get('delivery_address'));
|
|
|
|
// validate
|
|
$errors = $validator->validate($obj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
}
|
|
}
|
|
|
|
// check if any errors were found
|
|
if (!empty($error_array)) {
|
|
// return validation failure response
|
|
return $this->json([
|
|
'success' => false,
|
|
'errors' => $error_array
|
|
], 422);
|
|
}
|
|
|
|
// validated! save the entity
|
|
$em->persist($obj);
|
|
$em->flush();
|
|
|
|
// return successful response
|
|
return $this->json([
|
|
'success' => 'Changes have been saved!'
|
|
]);
|
|
}
|
|
|
|
protected function checkTier($tier)
|
|
{
|
|
// check specified tier
|
|
switch ($tier) {
|
|
case 'proc':
|
|
$tier_key = 'jo_proc';
|
|
$tier_name = 'Processing';
|
|
$rows_route = 'jo_proc_rows';
|
|
$edit_route = 'jo_proc_form';
|
|
$jo_status = JOStatus::PENDING;
|
|
break;
|
|
case 'assign':
|
|
$tier_key = 'jo_assign';
|
|
$tier_name = 'Assigning';
|
|
$rows_route = 'jo_assign_rows';
|
|
$edit_route = 'jo_assign_form';
|
|
$jo_status = JOStatus::RIDER_ASSIGN;
|
|
break;
|
|
default:
|
|
$exception = $this->createAccessDeniedException('No access.');
|
|
throw $exception;
|
|
}
|
|
|
|
// check acl
|
|
$this->denyAccessUnlessGranted($tier_key . '.list', null, 'No access.');
|
|
|
|
// return params if allowed access
|
|
return [
|
|
'key' => $tier_key,
|
|
'name' => $tier_name,
|
|
'rows_route' => $rows_route,
|
|
'edit_route' => $edit_route,
|
|
'jo_status' => $jo_status
|
|
];
|
|
}
|
|
|
|
public function listRows($tier)
|
|
{
|
|
// check which job order tier is being called for and confirm access
|
|
$tier_params = $this->checkTier($tier);
|
|
|
|
$params = $this->initParameters($tier_params['key']);
|
|
|
|
$params['tier_name'] = $tier_params['name'];
|
|
$params['rows_route'] = $tier_params['rows_route'];
|
|
|
|
// response
|
|
return $this->render('job-order/list.html.twig', $params);
|
|
}
|
|
|
|
public function getRows(Request $req, $tier)
|
|
{
|
|
// check which job order tier is being called for and confirm access
|
|
$tier_params = $this->checkTier($tier);
|
|
|
|
// get query builder
|
|
$qb = $this->getDoctrine()
|
|
->getRepository(JobOrder::class)
|
|
->createQueryBuilder('q');
|
|
|
|
// get datatable params
|
|
$datatable = $req->request->get('datatable');
|
|
|
|
// count total records
|
|
$tquery = $qb->select('COUNT(q)')
|
|
->join('q.cus_vehicle', 'cv')
|
|
->join('q.customer', 'c');
|
|
|
|
$this->setQueryFilters($datatable, $tquery, $qb, $tier_params['jo_status']);
|
|
|
|
$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('cv.plate_number as plate_number')
|
|
->addSelect('c.first_name as customer_name')
|
|
->addSelect('c.last_name as cust_last_name');
|
|
|
|
$this->setQueryFilters($datatable, $query, $qb, $tier_params['jo_status']);
|
|
|
|
// check if sorting is present, otherwise use default
|
|
if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) {
|
|
$prefix = '';
|
|
|
|
if (!in_array($datatable['sort']['field'], ['plate_number', 'customer_name']))
|
|
$prefix = 'q.';
|
|
|
|
$order = $datatable['sort']['sort'] ?? 'asc';
|
|
$query->orderBy($prefix . $datatable['sort']['field'], $order);
|
|
} else {
|
|
$query->orderBy('q.date_schedule', 'asc');
|
|
}
|
|
|
|
// get rows for this page
|
|
$obj_rows = $query->setFirstResult($offset)
|
|
->setMaxResults($perpage)
|
|
->getQuery()
|
|
->getResult();
|
|
|
|
// process rows
|
|
$rows = [];
|
|
foreach ($obj_rows as $orow) {
|
|
// get service type name
|
|
$service_type = false;
|
|
$service_types = ServiceType::getCollection();
|
|
foreach ($service_types as $key => $service) {
|
|
if ($key == $orow[0]->getServiceType()) {
|
|
$service_type = $service;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// add row data
|
|
$row['id'] = $orow[0]->getID();
|
|
$row['date_schedule'] = $orow[0]->getDateSchedule()->format("d M Y");
|
|
$row['date_schedule_time'] = $orow[0]->getDateSchedule()->format("h:i A");
|
|
$row['service_type'] = $service_type;
|
|
$row['plate_number'] = $orow['plate_number'];
|
|
$row['customer_name'] = $orow['customer_name'] . " " . $orow['cust_last_name'];
|
|
$row['mobile_numbers'] = implode("<br>", $orow[0]->getCustomer()->getMobileNumberList());
|
|
$row['source'] = ucfirst($orow[0]->getSource());
|
|
$row['flag_advance'] = $orow[0]->isAdvanceOrder();
|
|
|
|
// add crud urls
|
|
$row['meta']['update_url'] = $this->generateUrl($tier_params['edit_route'], ['id' => $row['id']]);
|
|
|
|
$rows[] = $row;
|
|
}
|
|
|
|
// response
|
|
return $this->json([
|
|
'meta' => $meta,
|
|
'data' => $rows
|
|
]);
|
|
}
|
|
|
|
public function processingForm(MapTools $map_tools, $id)
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
|
|
|
|
$params = $this->initParameters('jo_proc');
|
|
$params['mode'] = 'update-processing';
|
|
|
|
// get row data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = $em->getRepository(JobOrder::class)->find($id);
|
|
|
|
// make sure this row exists
|
|
if (empty($obj))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// get parent associations
|
|
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
|
$params['customers'] = $em->getRepository(Customer::class)->findAll();
|
|
$params['service_types'] = ServiceType::getCollection();
|
|
$params['statuses'] = JOStatus::getCollection();
|
|
|
|
// get closest outlets
|
|
$outlets = $map_tools->getClosestOutlets($obj->getCoordinates(), 10, date("H:i:s"));
|
|
|
|
$params['outlets'] = [];
|
|
|
|
// format duration and distance into friendly time
|
|
foreach ($outlets as $outlet) {
|
|
// duration
|
|
$seconds = $outlet['duration'];
|
|
|
|
if (!empty($seconds) && $seconds > 0) {
|
|
$hours = floor($seconds / 3600);
|
|
$minutes = ceil(($seconds / 60) % 60);
|
|
|
|
$outlet['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
|
|
} else {
|
|
$outlet['duration'] = false;
|
|
}
|
|
|
|
// distance
|
|
$meters = $outlet['distance'];
|
|
|
|
if (!empty($meters) && $meters > 0) {
|
|
$outlet['distance'] = round($meters / 1000) . " km";
|
|
} else {
|
|
$outlet['distance'] = false;
|
|
}
|
|
|
|
$params['outlets'][] = $outlet;
|
|
}
|
|
|
|
$params['obj'] = $obj;
|
|
$params['submit_url'] = $this->generateUrl('jo_proc_submit', ['id' => $obj->getID()]);
|
|
$params['return_url'] = $this->generateUrl('jo_proc');
|
|
|
|
// response
|
|
return $this->render('job-order/form.html.twig', $params);
|
|
}
|
|
|
|
public function processingSubmit(Request $req, ValidatorInterface $validator, $id)
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
|
|
|
|
// initialize error list
|
|
$error_array = [];
|
|
|
|
// get object data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = $em->getRepository(JobOrder::class)->find($id);
|
|
|
|
// make sure this object exists
|
|
if (empty($obj))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// check if lat and lng are provided
|
|
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
|
|
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
|
|
}
|
|
|
|
// check if outlet is set
|
|
if (empty($req->request->get('outlet'))) {
|
|
$error_array['outlet'] = 'No outlet selected.';
|
|
} else {
|
|
// get outlet
|
|
$outlet = $em->getRepository(Outlet::class)->find($req->request->get('outlet'));
|
|
|
|
if (empty($outlet)) {
|
|
$error_array['outlet'] = 'Invalid outlet specified.';
|
|
}
|
|
}
|
|
|
|
if (empty($error_array)) {
|
|
// coordinates
|
|
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
|
|
|
|
// set and save values
|
|
$obj->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
|
|
->setCoordinates($point)
|
|
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
|
|
->setServiceType($req->request->get('service_type'))
|
|
->setSource('web')
|
|
->setStatus($req->request->get('status'))
|
|
->setDeliveryInstructions($req->request->get('delivery_instructions'))
|
|
->setAgentNotes($req->request->get('agent_notes'))
|
|
->setDeliveryAddress($req->request->get('delivery_address'))
|
|
->setOutlet($outlet);
|
|
|
|
// validate
|
|
$errors = $validator->validate($obj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
}
|
|
}
|
|
|
|
// check if any errors were found
|
|
if (!empty($error_array)) {
|
|
// return validation failure response
|
|
return $this->json([
|
|
'success' => false,
|
|
'errors' => $error_array
|
|
], 422);
|
|
}
|
|
|
|
// validated! save the entity
|
|
$em->flush();
|
|
|
|
// return successful response
|
|
return $this->json([
|
|
'success' => 'Changes have been saved!'
|
|
]);
|
|
}
|
|
|
|
public function assigningForm(MapTools $map_tools, $id)
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_assign.list', null, 'No access.');
|
|
|
|
$params = $this->initParameters('jo_assign');
|
|
$params['mode'] = 'update-assigning';
|
|
|
|
// get row data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = $em->getRepository(JobOrder::class)->find($id);
|
|
|
|
// make sure this row exists
|
|
if (empty($obj))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// get parent associations
|
|
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
|
$params['customers'] = $em->getRepository(Customer::class)->findAll();
|
|
$params['service_types'] = ServiceType::getCollection();
|
|
$params['statuses'] = JOStatus::getCollection();
|
|
|
|
// get closest outlets
|
|
$outlets = $map_tools->getClosestOutlets($obj->getCoordinates(), 10, date("H:i:s"));
|
|
|
|
$params['outlets'] = [];
|
|
|
|
// format duration and distance into friendly time
|
|
foreach ($outlets as $outlet) {
|
|
// duration
|
|
$seconds = $outlet['duration'];
|
|
|
|
if (!empty($seconds) && $seconds > 0) {
|
|
$hours = floor($seconds / 3600);
|
|
$minutes = ceil(($seconds / 60) % 60);
|
|
|
|
$outlet['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
|
|
} else {
|
|
$outlet['duration'] = false;
|
|
}
|
|
|
|
// distance
|
|
$meters = $outlet['distance'];
|
|
|
|
if (!empty($meters) && $meters > 0) {
|
|
$outlet['distance'] = round($meters / 1000) . " km";
|
|
} else {
|
|
$outlet['distance'] = false;
|
|
}
|
|
|
|
$params['outlets'][] = $outlet;
|
|
}
|
|
|
|
$params['obj'] = $obj;
|
|
$params['submit_url'] = $this->generateUrl('jo_assign_submit', ['id' => $obj->getID()]);
|
|
$params['return_url'] = $this->generateUrl('jo_assign');
|
|
|
|
// response
|
|
return $this->render('job-order/form.html.twig', $params);
|
|
}
|
|
|
|
public function assigningSubmit(Request $req, ValidatorInterface $validator, $id)
|
|
{
|
|
$this->denyAccessUnlessGranted('jo_assign.list', null, 'No access.');
|
|
|
|
// initialize error list
|
|
$error_array = [];
|
|
|
|
// get object data
|
|
$em = $this->getDoctrine()->getManager();
|
|
$obj = $em->getRepository(JobOrder::class)->find($id);
|
|
|
|
// make sure this object exists
|
|
if (empty($obj))
|
|
throw $this->createNotFoundException('The item does not exist');
|
|
|
|
// check if lat and lng are provided
|
|
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
|
|
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
|
|
}
|
|
|
|
// check if rider is set
|
|
if (empty($req->request->get('rider'))) {
|
|
$error_array['rider'] = 'No rider selected.';
|
|
} else {
|
|
// get rider
|
|
$rider = $em->getRepository(Rider::class)->find($req->request->get('rider'));
|
|
|
|
if (empty($rider)) {
|
|
$error_array['rider'] = 'Invalid rider specified.';
|
|
}
|
|
}
|
|
|
|
if (empty($error_array)) {
|
|
// coordinates
|
|
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
|
|
|
|
// set and save values
|
|
$obj->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
|
|
->setCoordinates($point)
|
|
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
|
|
->setServiceType($req->request->get('service_type'))
|
|
->setSource('web')
|
|
->setStatus($req->request->get('status'))
|
|
->setDeliveryInstructions($req->request->get('delivery_instructions'))
|
|
->setAgentNotes($req->request->get('agent_notes'))
|
|
->setDeliveryAddress($req->request->get('delivery_address'))
|
|
->setAssignedBy($this->getUser())
|
|
->setDateAssign(new DateTime())
|
|
->setRider($rider);
|
|
|
|
// validate
|
|
$errors = $validator->validate($obj);
|
|
|
|
// add errors to list
|
|
foreach ($errors as $error) {
|
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
}
|
|
}
|
|
|
|
// check if any errors were found
|
|
if (!empty($error_array)) {
|
|
// return validation failure response
|
|
return $this->json([
|
|
'success' => false,
|
|
'errors' => $error_array
|
|
], 422);
|
|
}
|
|
|
|
// validated! save the entity
|
|
$em->flush();
|
|
|
|
// return successful response
|
|
return $this->json([
|
|
'success' => 'Changes have been saved!'
|
|
]);
|
|
}
|
|
|
|
|
|
// TODO: re-enable search, figure out how to group the orWhere filters into one, so can execute that plus the pending filter
|
|
|
|
// check if datatable filter is present and append to query
|
|
protected function setQueryFilters($datatable, &$query, $qb, $status) {
|
|
error_log($status);
|
|
$query->where('q.status = :status')
|
|
->setParameter('status', $status);
|
|
|
|
// get only pending rows
|
|
/*
|
|
$query->where($qb->expr()->orX(
|
|
$qb->expr()where('q.status', 'pending');
|
|
));
|
|
|
|
|
|
// apply filters
|
|
if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) {
|
|
$query->where('q.delivery_address LIKE :filter')
|
|
->orWhere($qb->expr()->concat('c.first_name', $qb->expr()->literal(' '), 'c.last_name') . ' LIKE :filter')
|
|
->orWhere('cv.plate_number LIKE :filter')
|
|
->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%');
|
|
}
|
|
*/
|
|
}
|
|
}
|