resq/src/Service/JobOrderHandler/CMBJobOrderHandler.php

2644 lines
91 KiB
PHP

<?php
namespace App\Service\JobOrderHandler;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\PessimisticLockException;
use App\Entity\JobOrder;
use App\Entity\BatteryManufacturer;
use App\Entity\JOEvent;
use App\Entity\CustomerVehicle;
use App\Entity\Vehicle;
use App\Entity\Hub;
use App\Entity\Promo;
use App\Entity\Rider;
use App\Entity\JORejection;
use App\Entity\Warranty;
use App\Entity\Customer;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\CMBServiceType;
use App\Ramcar\CMBTradeInType;
use App\Ramcar\JOEventType;
use App\Ramcar\JOStatus;
use App\Ramcar\CMBWarrantyClass;
use App\Ramcar\DiscountApply;
use App\Ramcar\CMBModeOfPayment;
use App\Ramcar\TransactionOrigin;
use App\Ramcar\FacilitatedType;
use App\Ramcar\JORejectionReason;
use App\Service\InvoiceGeneratorInterface;
use App\Service\JobOrderHandlerInterface;
use App\Service\RiderAssignmentHandlerInterface;
use App\Service\WarrantyHandler;
use App\Service\MQTTClient;
use App\Service\APNSClient;
use App\Service\MapTools;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
use Mosquitto\Client as MosquittoClient;
use DateTime;
use DateInterval;
use FPDF;
class CMBJobOrderHandler implements JobOrderHandlerInterface
{
protected $em;
protected $ic;
protected $security;
protected $validator;
protected $translator;
protected $rah;
protected $country_code;
protected $wh;
protected $template_hash;
public function __construct(Security $security, EntityManagerInterface $em,
InvoiceGeneratorInterface $ic, ValidatorInterface $validator,
TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah,
string $country_code, WarrantyHandler $wh)
{
$this->em = $em;
$this->ic = $ic;
$this->security = $security;
$this->validator = $validator;
$this->translator = $translator;
$this->rah = $rah;
$this->country_code = $country_code;
$this->wh = $wh;
$this->loadTemplates();
}
// get job order rows
public function getRows(Request $req, $tier)
{
// check which job order tier is being called for and confirm access
$tier_params = $this->checkTier($tier);
// get current user
$user = $this->security->getUser();
if ($user == null)
throw new AccessDeniedHttpException('No access.');
$hubs = $user->getHubs();
// get query builder
$qb = $this->em->getRepository(JobOrder::class)
->createQueryBuilder('q');
// get datatable params
$datatable = $req->request->get('datatable');
// count total records
$tquery = $qb->select('COUNT(q)');
$this->setQueryFilters($datatable, $tquery, $qb, $hubs, $tier, $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
$qb = $this->em->getRepository(JobOrder::class)
->createQueryBuilder('q');
$query = $qb->select('q');
$this->setQueryFilters($datatable, $query, $qb, $hubs, $tier, $tier_params['jo_status']);
// check if sorting is present, otherwise use default
if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) {
$order = $datatable['sort']['sort'] ?? 'asc';
$query->orderBy('q.' . $datatable['sort']['field'], $order);
} else {
$query->orderBy('q.date_schedule', 'asc');
}
// get rows for this page
$query_obj = $query->setFirstResult($offset)
->setMaxResults($perpage)
->getQuery();
// error_log($query_obj->getSQL());
$obj_rows = $query_obj->getResult();
$statuses = JOStatus::getCollection();
$service_types = CMBServiceType::getCollection();
// process rows
$rows = [];
foreach ($obj_rows as $orow) {
// add row data
$row['id'] = $orow->getID();
$row['customer_name'] = $orow->getCustomer()->getFirstName() . ' ' . $orow->getCustomer()->getLastName();
$row['delivery_address'] = $orow->getDeliveryAddress();
$row['date_schedule'] = $orow->getDateSchedule()->format("d M Y g:i A");
$row['type'] = $orow->isAdvanceOrder() ? 'Advanced Order' : 'Immediate';
$row['service_type'] = $service_types[$orow->getServiceType()] ?? 'Unknown';
$row['status'] = $statuses[$orow->getStatus()];
$row['flag_advance'] = $orow->isAdvanceOrder();
$row['plate_number'] = $orow->getCustomerVehicle()->getPlateNumber();
$row['is_mobile'] = $orow->getSource() == TransactionOrigin::MOBILE_APP;
$processor = $orow->getProcessedBy();
if ($processor == null)
$row['processor'] = '';
else
$row['processor'] = $orow->getProcessedBy()->getFullName();
$assignor = $orow->getAssignedBy();
if ($assignor == null)
$row['assignor'] = '';
else
$row['assignor'] = $orow->getAssignedBy()->getFullName();
$rows[] = $row;
}
$params['meta'] = $meta;
$params['rows'] = $rows;
$params['tier_params'] = $tier_params;
return $params;
}
// get job orders
public function getJobOrders(Request $req)
{
// get search term
$term = $req->query->get('search');
// get querybuilder
$qb = $this->em->getRepository(JobOrder::class)
->createQueryBuilder('q');
// build expression now since we're reusing it
$jo_label = $qb->expr()->concat($qb->expr()->literal('#'), 'q.id', $qb->expr()->literal(' - '), 'c.first_name', $qb->expr()->literal(' '), 'c.last_name', $qb->expr()->literal(' (Plate No: '), 'v.plate_number', $qb->expr()->literal(')'));
// count total records
$tquery = $qb->select('COUNT(q)')
->join('q.customer', 'c')
->join('q.cus_vehicle', 'v');
// add filters to count query
if (!empty($term)) {
$tquery->where($jo_label . ' LIKE :filter')
->setParameter('filter', '%' . $term . '%');
}
$total = $tquery->getQuery()
->getSingleScalarResult();
// pagination vars
$page = $req->query->get('page') ?? 1;
$perpage = 20;
$offset = ($page - 1) * $perpage;
$pages = ceil($total / $perpage);
$has_more_pages = $page < $pages ? true : false;
// build main query
$query = $qb->select('q')
->addSelect($jo_label . ' as jo_label')
->addSelect('c.first_name as cust_first_name')
->addSelect('c.last_name as cust_last_name')
->addSelect('v.plate_number as vehicle_plate_number');
// add filters if needed
if (!empty($term)) {
$query->where($jo_label . ' LIKE :filter')
->setParameter('filter', '%' . $term . '%');
}
// get rows
$obj_rows = $query->orderBy('q.id', 'asc')
->setFirstResult($offset)
->setMaxResults($perpage)
->getQuery()
->getResult();
// build job order array
$job_orders = [];
foreach ($obj_rows as $jo) {
$service_type = CMBServiceType::getName($jo[0]->getServiceType());
$job_orders[] = [
'id' => $jo[0]->getID(),
'text' => $jo['jo_label'] . ' - ' . $service_type
];
}
$params['job_orders'] = $job_orders;
$params['has_more_pages'] = $has_more_pages;
return $params;
}
// creates/updates job order
public function generateJobOrder(Request $req, $id)
{
// initialize error list
$error_array = [];
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
if (empty($jo))
{
// new job order
$jo = 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)) {
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
$stype = $req->request->get('service_type');
// set and save values
$jo->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($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setCustomer($cust_vehicle->getCustomer())
->setCustomerVehicle($cust_vehicle)
->setSource($req->request->get('source'))
->setStatus(JOStatus::PENDING)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'));
// check if user is null, meaning call to create came from API
if ($user != null)
{
$jo->setCreatedBy($user);
}
// check if reference JO is set and validate
if (!empty($req->request->get('ref_jo'))) {
// get reference JO
$ref_jo = $em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
if (empty($ref_jo)) {
$error_array['ref_jo'] = 'Invalid reference job order specified.';
} else {
$jo->setReferenceJO($ref_jo);
}
}
// call service to generate job order and invoice
$invoice_items = $req->request->get('invoice_items', []);
$promo_id = $req->request->get('invoice_promo');
$invoice_change = $req->request->get('invoice_change', 0);
// check if invoice changed
if ($invoice_change)
{
$this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array);
}
// validate
$errors = $this->validator->validate($jo);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if errors are found
if (empty($error_array))
{
// validated, no error. save the job order
$em->persist($jo);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CREATE)
->setJobOrder($jo);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
$em->flush();
}
}
return $error_array;
}
public function processOneStepJobOrder(Request $req, $id)
{
// initialize error list
$error_array = [];
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
if (empty($jo))
{
// new job order
$jo = 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 new customer
if ($req->request->get('new_customer'))
{
if (empty($req->request->get('customer_customer_notes')))
{
$error_array['customer_customer_notes'] = 'Customer notes cannot be null.';
}
$new_cust = new Customer();
$new_cv = new CustomerVehicle();
// find the vehicle using vid
$new_vehicle = $em->getRepository(Vehicle::class)->find($req->request->get('vid'));
if (empty($new_vehicle))
{
$error_array['cv_mfg'] = 'Invalid manufacturer specified.';
$error_array['cv_make'] = 'Invalid make specified.';
}
else
{
$new_cust->setLastName($req->request->get('customer_last_name'))
->setFirstName($req->request->get('customer_first_name'))
->setPhoneMobile($req->request->get('customer_phone_mobile'))
->setPhoneLandline($req->request->get('customer_phone_landline'))
->setPhoneOffice($req->request->get('customer_phone_office'))
->setPhoneFax($req->request->get('customer_phone_fax'))
->setCustomerNotes($req->request->get('customer_customer_notes'));
$new_cv->setCustomer($new_cust)
->setVehicle($new_vehicle)
->setPlateNumber($req->request->get('cv_plate'))
->setModelYear($req->request->get('cv_year'))
->setColor('')
->setStatusCondition('')
->setFuelType('')
->setActive()
->setWarrantyCode($req->request->get('warranty_code'));
if (($req->request->get('service_type')) == CMBServiceType::BATTERY_REPLACEMENT_NEW)
{
$new_cv->setHasMotoliteBattery(true);
}
else
{
$new_cv->setHasMotoliteBattery(false);
}
// link JO to new customer
$jo->setCustomer($new_cust);
$jo->setCustomerVehicle($new_cv);
$em->persist($new_cust);
$em->persist($new_cv);
}
}
else
{
// 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.';
}
else
{
$jo->setCustomerVehicle($cust_vehicle);
$jo->setCustomer($cust_vehicle->getCustomer());
// save serial into cv
$cust_vehicle->setWarrantyCode($req->request->get('warranty_code'));
$em->persist($cust_vehicle);
}
}
}
// check if hub AND rider is selected
if ((empty($req->request->get('hub_id'))) &&
(empty($req->request->get('rider_id')))) {
$error_array['hub'] = 'No hub selected.';
} else {
if (empty($req->request->get('rider_id'))) {
$error_array['rider'] = 'No rider selected.';
} else {
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub_id'));
if (empty($hub)) {
$error_array['hub'] = 'Invalid hub specified.';
} else {
// get rider
$rider = $em->getRepository(Rider::class)->find($req->request->get('rider_id'));
if (empty($rider)) {
$error_array['rider'] = 'Invalid rider specified.';
}
}
}
}
if (empty($error_array))
{
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
$stype = $req->request->get('service_type');
// set and save values
$jo->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($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::ASSIGNED)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'))
->setHub($hub)
->setRider($rider);
// check if user is null, meaning call to create came from API
if ($user != null)
{
$jo->setCreatedBy($user);
}
// check if reference JO is set and validate
if (!empty($req->request->get('ref_jo'))) {
// get reference JO
$ref_jo = $em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
if (empty($ref_jo)) {
$error_array['ref_jo'] = 'Invalid reference job order specified.';
} else {
$jo->setReferenceJO($ref_jo);
}
}
// call service to generate job order and invoice
$invoice_items = $req->request->get('invoice_items', []);
$promo_id = $req->request->get('invoice_promo');
$invoice_change = $req->request->get('invoice_change', 0);
// check if invoice changed
if ($invoice_change)
{
$this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array);
}
// validate
$errors = $this->validator->validate($jo);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if errors are found
if (empty($error_array))
{
// validated, no error. save the job order
$em->persist($jo);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CREATE)
->setJobOrder($jo);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
$em->flush();
}
}
return $error_array;
}
// dispatch job order
public function dispatchJobOrder(Request $req, int $id, MQTTClient $mclient)
{
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$processor = $obj->getProcessedBy();
$user = $this->security->getUser();;
// check if we're the one processing, return error otherwise
if ($processor == null)
throw new AccessDeniedHttpException('Not the processor');
if ($processor != null && $processor->getID() != $user->getID())
throw new AccessDeniedHttpException('Not the processor');
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('The item does not exist');
// check if cancelled already
if (!$obj->canDispatch())
{
throw new NotFoundHttpException('Could not dispatch. Job Order is not pending.');
// TODO: have this handled better, so UI shows the error
// $error_array['dispatch'] = 'Could not dispatch. Job Order is not pending.';
}
// 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 hub is set
if (empty($req->request->get('hub')))
{
$error_array['hub'] = 'No hub selected.';
}
else
{
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub'));
if (empty($hub))
{
$error_array['hub'] = 'Invalid hub specified.';
}
}
// check facilitated type
$fac_type = $req->request->get('facilitated_type');
if (!empty($fac_type))
{
if (!FacilitatedType::validate($fac_type))
$fac_type = null;
}
else
$fac_type = null;
// check facilitated by
$fac_by_id = $req->request->get('facilitated_by');
$fac_by = null;
if (!empty($fac_by_id))
{
$fac_by = $em->getRepository(Hub::class)->find($fac_by_id);
if (empty($fac_by))
$fac_by = null;
}
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'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::RIDER_ASSIGN)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setFacilitatedType($fac_type)
->setFacilitatedBy($fac_by)
->setHub($hub);
// validate
$errors = $this->validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
// validated! save the entity
$em->flush();
// send event to mobile app
$payload = [
'event' => 'outlet_assign'
];
$mclient->sendEvent($obj, $payload);
}
return $error_array;
}
// assign job order
public function assignJobOrder(Request $req, $id)
{
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('The item does not exist');
// check if we can assign
if (!$obj->canAssign())
throw new NotFoundHttpException('Cannot assign rider to this job order.');
// 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.';
}
}
// get current user
$user = $this->security->getUser();
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'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::ASSIGNED)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setDateAssign(new DateTime())
->setRider($rider);
if ($user != null)
{
$obj->setAssignedBy($user);
}
// validate
$errors = $this->validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::RIDER_ASSIGN)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
// validated! save the entity
$em->flush();
// call rider assignment handler's assignJobOrder
$this->rah->assignJobOrder($obj, $rider);
}
return $error_array;
}
// fulfill job order
public function fulfillJobOrder(Request $req, $id)
{
// initialize error list
$error_array = [];
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('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.';
}
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'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'));
// validate
$errors = $this->validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
$obj->fulfill();
if (empty($error_array))
{
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::FULFILL)
->setJobOrder($obj);
// get current user
$user = $this->security->getUser();
if ($user != null)
{
$event->setUser($user);
}
$event->setUser($user);
$em->persist($event);
// save to customer vehicle battery record
$this->updateVehicleBattery($obj);
// save serial to customer vehicle
$cust_vehicle = $obj->getCustomerVehicle();
$cust_vehicle->setWarrantyCode($req->request->get('warranty_code'));
$em->persist($cust_vehicle);
// get rider
$rider = $obj->getRider();
$image_url = $req->getScheme() . '://' . $req->getHttpHost() . $req->getBasePath() . '/assets/images/user.gif';
if ($rider->getImageFile() != null)
$image_url = $req->getScheme() . '://' . $req->getHttpHost() . $req->getBasePath() . '/uploads/' . $rider->getImageFile();
// call rider assignment handler's fulfillJobOrder
$this->rah->fulfillJobOrder($obj, $image_url, $rider);
// create the warranty if new battery only
if ($this->checkIfNewBattery($obj))
{
$serial = $req->request->get('warranty_code') ;
$warranty_class = $obj->getWarrantyClass();
$first_name = $obj->getCustomer()->getFirstName();
$last_name = $obj->getCustomer()->getLastName();
$mobile_number = $obj->getCustomer()->getPhoneMobile();
// check if date fulfilled is null
if ($obj->getDateFulfill() == null)
$date_purchase = $obj->getDateCreate();
else
$date_purchase = $obj->getDateFulfill();
// validate plate number
// $plate_number = $this->wh->cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber());
$plate_number = Warranty::cleanPlateNumber($obj->getCustomerVehicle()->getPlateNumber());
if ($plate_number != false)
{
$batt_list = array();
$invoice = $obj->getInvoice();
if (!empty($invoice))
{
// get battery
$invoice_items = $invoice->getItems();
foreach ($invoice_items as $item)
{
$battery = $item->getBattery();
if ($battery != null)
{
$batt_list[] = $item->getBattery();
}
}
}
$this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class);
}
}
// validated! save the entity
$em->flush();
}
}
// cancel job order
public function cancelJobOrder(Request $req, int $id, MQTTClient $mclient)
{
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('The item does not exist');
$cancel_reason = $req->request->get('cancel_reason');
$obj->cancel($cancel_reason);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CANCEL)
->setJobOrder($obj);
// get current user
$user = $this->security->getUser();
if ($user != null)
{
$event->setUser($user);
}
$event->setUser($user);
$em->persist($event);
// save
$em->flush();
// send mobile app event
$payload = [
'event' => 'cancelled',
'reason' => $cancel_reason,
'jo_id' => $obj->getID(),
];
$mclient->sendEvent($obj, $payload);
$mclient->sendRiderEvent($obj, $payload);
}
// set hub for job order
public function setHub($req, $id, $mclient)
{
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$user = $this->security->getUser();
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('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 hub is set
if (empty($req->request->get('hub'))) {
$error_array['hub'] = 'No hub selected.';
} else {
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub'));
if (empty($hub)) {
$error_array['hub'] = 'Invalid hub specified.';
}
}
if (empty($error_array))
{
// rider mqtt event
// NOTE: need to send this before saving because rider will be cleared
$rider_payload = [
'event' => 'cancelled',
'reason' => 'Reassigned',
'jo_id' => $obj->getID(),
];
$mclient->sendRiderEvent($obj, $rider_payload);
// 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'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::RIDER_ASSIGN)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setHub($hub)
->clearRider();
if ($user != null)
{
$obj->setProcessedBy($user);
}
$em->persist($obj);
// validate
$errors = $this->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)) {
// add event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
// validated! save the entity
$em->flush();
// user mqtt event
$payload = [
'event' => 'outlet_assign'
];
$mclient->sendEvent($obj, $payload);
}
return $error_array;
}
// reject hub for job order
public function rejectHub($req, $id)
{
// get object data
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
$processor = $jo->getProcessedBy();
$user = $this->security->getUser();
// check if we're the one processing, return error otherwise
if ($processor == null)
throw new AccessDeniedHttpException('Not the processor');
if ($user != null)
{
if ($processor != null && $processor->getID() != $user->getID())
throw new AccessDeniedHttpException('Not the processor');
}
// initialize error list
$error_array = [];
// make sure job order exists
if (empty($jo))
throw new NotFoundHttpException('The item does not exist');
// check if hub is set
if (empty($req->request->get('hub')))
{
$error_array['hub'] = 'No hub selected.';
}
else
{
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub'));
if (empty($hub))
{
$error_array['hub'] = 'Invalid hub specified.';
}
}
// check if this hub has already been rejected on this job order
$robj = $em->getRepository(JORejection::class)->findOneBy([
'job_order' => $jo,
'hub' => $hub
]);
if (!empty($robj))
$error_array['hub'] = 'This hub has already been rejected for the current job order.';
// check if reason is set
if (empty($req->request->get('reason')))
$error_array['reason'] = 'No reason selected.';
else if (!JORejectionReason::validate($req->request->get('reason')))
$error_array['reason'] = 'Invalid reason specified.';
if (empty($error_array))
{
// coordinates
$obj = new JORejection();
// set and save values
$obj->setDateCreate(new DateTime())
->setHub($hub)
->setJobOrder($jo)
->setReason($req->request->get('reason'))
->setRemarks($req->request->get('remarks'))
->setContactPerson($req->request->get('contact_person'));
if ($user != null)
{
$obj->setUser($user);
}
// validate
$errors = $this->validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// validated! save the entity
$em->persist($obj);
$em->flush();
}
return $error_array;
}
// set rider for job order
public function setRider($req, $id, $mclient)
{
// initialize error list
$error_array = [];
// get object data
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$user = $this->security->getUser();
// make sure this object exists
if (empty($obj))
throw new NotFoundHttpException('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)) {
// rider mqtt event
// NOTE: need to send this before saving because rider will be cleared
$rider_payload = [
'event' => 'cancelled',
'reason' => 'Reassigned',
'jo_id' => $obj->getID(),
];
$mclient->sendRiderEvent($obj, $rider_payload);
// 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'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::ASSIGNED)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setDateAssign(new DateTime())
->setRider($rider);
if ($user != null)
{
$obj->setAssignedBy($user);
}
// validate
$errors = $this->validator->validate($obj);
$em->persist($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))
{
// add event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::RIDER_ASSIGN)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
// validated! save the entity
$em->flush();
// send event to mobile app
$payload = [
'event' => 'driver_assigned'
];
$mclient->sendEvent($obj, $payload);
$mclient->sendRiderEvent($obj, $payload);
}
return $error_array;
}
// unlock processor
public function unlockProcessor($id)
{
// clear lock
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
if ($jo != null)
{
$jo->setProcessedBy(null);
$em->flush();
}
}
// unlock assignor
public function unlockAssignor($id)
{
// clear lock
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
if ($jo != null)
{
$jo->setAssignedBy(null);
$em->flush();
}
}
// initialize incoming job order form
public function initializeIncomingForm()
{
$params['obj'] = new JobOrder();
$params['mode'] = 'create';
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_incoming_form');
// return params
return $params;
}
public function initializeOneStepForm()
{
$params['obj'] = new JobOrder();
$params['mode'] = 'onestep';
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_onestep');
// return params
return $params;
}
public function initializeOneStepEditForm($id, $map_tools)
{
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$params['obj'] = $obj;
$params['mode'] = 'onestep-edit';
$params['cvid'] = $obj->getCustomerVehicle()->getID();
$params['vid'] = $obj->getCustomerVehicle()->getVehicle()->getID();
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get the hubs
// TODO: move this snippet to a function
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
$params['hubs'] = [];
// format duration and distance into friendly time
foreach ($hubs as $hub) {
// duration
$seconds = $hub['duration'];
if (!empty($seconds) && $seconds > 0) {
$hours = floor($seconds / 3600);
$minutes = ceil(($seconds / 60) % 60);
$hub['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
} else {
$hub['duration'] = false;
}
// distance
$meters = $hub['distance'];
if (!empty($meters) && $meters > 0) {
$hub['distance'] = round($meters / 1000) . " km";
} else {
$hub['distance'] = false;
}
// counters
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
// check for rejection
$hub['flag_rejected'] = false;
$hub_id = $hub['hub']->getID();
$params['hubs'][] = $hub;
}
// get template to display
$params['template'] = $this->getTwigTemplate('jo_onestep_edit_form');
return $params;
}
// initialize open edit job order form
public function initializeOpenEditForm($id)
{
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
$params['obj'] = $jo;
$params['mode'] = 'open_edit';
$params['cvid'] = $jo->getCustomerVehicle()->getID();
$params['vid'] = $jo->getCustomerVehicle()->getVehicle()->getID();
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_open_edit_form');
return $params;
}
// initialize incoming vehicle form
public function initializeIncomingVehicleForm(int $cvid)
{
$params['mode'] = 'create_vehicle';
$params['cvid'] = $cvid;
$em = $this->em;
// get customer vehicle
$cv = $em->getRepository(CustomerVehicle::class)->find($cvid);
$params['vid'] = $cv->getVehicle()->getID();
// make sure this customer vehicle exists
if (empty($cv))
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not exist');
}
$jo = new JobOrder();
$jo->setCustomerVehicle($cv)
->setCustomer($cv->getCustomer());
$params['obj'] = $jo;
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_incoming_vehicle_form');
return $params;
}
// initialize all job orders form for a specific job order id
public function initializeAllForm($id)
{
$em = $this->em;
$params['mode'] = 'update-all';
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
throw new NotFoundHttpException('The job order does not exist');
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_all_form');
$params['obj'] = $obj;
$params['status_cancelled'] = JOStatus::CANCELLED;
// timeline stuff (descending by time)
$params['timeline'] = [
[
'date' => date("M j"),
'time' => date("g:i A"),
'event' => "Event 4",
'color' => "#f4516c"
],
[
'date' => date("M j"),
'time' => date("g:i A"),
'event' => "Event 3",
'color' => "#34bfa3"
],
[
'date' => date("M j"),
'time' => date("g:i A"),
'event' => "Event 2",
'color' => "#716aca"
],
[
'date' => date("M j"),
'time' => date("g:i A"),
'event' => "Event 1",
'color' => "#ffb822"
],
];
return $params;
}
// initialize dispatch/processing job order form
public function initializeProcessingForm($id, $map_tools)
{
$em = $this->em;
// manual transaction since we're locking
$em->getConnection()->beginTransaction();
try
{
// lock and get data
$obj = $em->getRepository(JobOrder::class)->find($id, LockMode::PESSIMISTIC_READ);
// make sure this job order exists
if (empty($obj))
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not exist');
}
// check status
if ($obj->getStatus() != JOStatus::PENDING)
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not have a pending status');
}
// check if we are the processor
$processor = $obj->getProcessedBy();
// get current user
$user = $this->security->getUser();
if ($user != null)
{
// TODO: go back to list page and display alert / flash that says they cannot access it because they
// are not the processor
if ($processor != null && $processor->getID() != $user->getID())
{
$em->getConnection()->rollback();
throw new AccessDeniedHttpException('Not the processor');
}
// make this user be the processor
$obj->setProcessedBy($user);
}
$em->flush();
$em->getConnection()->commit();
}
catch(PessimisticLockException $e)
{
throw new AccessDeniedHttpException('Not the processor');
}
// NOTE: we are able to lock, everything should be fine now
$params['mode'] = 'update-processing';
$params['status_cancelled'] = JOStatus::CANCELLED;
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get rejections
$rejections = $obj->getHubRejections();
// get rejection reasons
$params['rejection_reasons'] = JORejectionReason::getCollection();
// get closest hubs
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
$params['hubs'] = [];
// format duration and distance into friendly time
foreach ($hubs as $hub) {
// duration
$seconds = $hub['duration'];
if (!empty($seconds) && $seconds > 0) {
$hours = floor($seconds / 3600);
$minutes = ceil(($seconds / 60) % 60);
$hub['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
} else {
$hub['duration'] = false;
}
// distance
$meters = $hub['distance'];
if (!empty($meters) && $meters > 0) {
$hub['distance'] = round($meters / 1000) . " km";
} else {
$hub['distance'] = false;
}
// counters
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
// check for rejection
$hub['flag_rejected'] = false;
$hub_id = $hub['hub']->getID();
foreach ($rejections as $robj)
{
if ($robj->getHub()->getID() === $hub_id)
{
$hub['flag_rejected'] = true;
break;
}
}
$params['hubs'][] = $hub;
}
$params['obj'] = $obj;
// get template to display
$params['template'] = $this->getTwigTemplate('jo_processing_form');
return $params;
}
// initialize assign job order form
public function initializeAssignForm($id)
{
$em = $this->em;
// manual transaction since we're locking
$em->getConnection()->beginTransaction();
$params['mode'] = 'update-assigning';
try
{
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not exist');
}
// check status
if ($obj->getStatus() != JOStatus::RIDER_ASSIGN)
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not have an assigning status');
}
// check if super user
$user = $this->security->getUser();
if ($user != null)
{
if ($user->isSuperAdmin())
{
// do nothing, just allow page to be accessed
}
else
{
// check if hub is assigned to current user
$user_hubs = $user->getHubs();
if (!in_array($obj->getHub()->getID(), $user_hubs))
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order is not on a hub assigned to this user');
}
// check if we are the assignor
$assignor = $obj->getAssignedBy();
if ($assignor != null && $assignor->getID() != $user->getID())
{
$em->getConnection()->rollback();
throw new AccessDeniedHttpException('Not the assignor');
}
// make this user be the assignor
$obj->setAssignedBy($user);
}
}
$em->flush();
$em->getConnection()->commit();
}
catch (PessimisticLockException $e)
{
throw new AccessDeniedHttpException('Not the assignor');
}
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_assigning_form');
$params['obj'] = $obj;
$params['status_cancelled'] = JOStatus::CANCELLED;
return $params;
}
// initialize fulflll job order form
public function initializeFulfillmentForm($id)
{
$em = $this->em;
$params['mode'] = 'update-fulfillment';
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
{
throw new NotFoundHttpException('The job order does not exist');
}
// check status
if (!in_array($obj->getStatus(), [JOStatus::ASSIGNED, JOStatus::IN_PROGRESS]))
{
throw new NotFoundHttpException('The job order does not have a fulfillment status');
}
// get current user
$user = $this->security->getUser();
// check if hub is assigned to current user
$user_hubs = $user->getHubs();
if (!in_array($obj->getHub()->getID(), $user_hubs))
{
throw new NotFoundHttpException('The job order is not on a hub assigned to this user');
}
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_fulfillment_form');
$params['obj'] = $obj;
$params['status_cancelled'] = JOStatus::CANCELLED;
return $params;
}
// initialize hub form
public function initializeHubForm($id, $map_tools)
{
$em = $this->em;
$params['mode'] = 'update-reassign-hub';
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
{
throw new NotFoundHttpException('The job order does not exist');
}
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get rejections
$rejections = $obj->getHubRejections();
// get rejection reasons
$params['rejection_reasons'] = JORejectionReason::getCollection();
// get closest hubs
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
$params['status_cancelled'] = JOStatus::CANCELLED;
$params['hubs'] = [];
// format duration and distance into friendly time
foreach ($hubs as $hub) {
// duration
$seconds = $hub['duration'];
if (!empty($seconds) && $seconds > 0) {
$hours = floor($seconds / 3600);
$minutes = ceil(($seconds / 60) % 60);
$hub['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
} else {
$hub['duration'] = false;
}
// distance
$meters = $hub['distance'];
if (!empty($meters) && $meters > 0) {
$hub['distance'] = round($meters / 1000) . " km";
} else {
$hub['distance'] = false;
}
// counters
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
// check for rejection
$hub['flag_rejected'] = false;
$hub_id = $hub['hub']->getID();
foreach ($rejections as $robj)
{
if ($robj->getHub()->getID() === $hub_id)
{
$hub['flag_rejected'] = true;
break;
}
}
$params['hubs'][] = $hub;
}
$params['obj'] = $obj;
// get template to display
$params['template'] = $this->getTwigTemplate('jo_open_hub_form');
return $params;
}
// initialize rider form
public function initializeRiderForm($id)
{
$em = $this->em;
$params['mode'] = 'update-reassign-rider';
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not exist');
}
// check status
if ($obj->getStatus() == JOStatus::PENDING)
{
$em->getConnection()->rollback();
throw new NotFoundHttpException('The job order does not have an assigned hub');
}
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
$params['obj'] = $obj;
$params['status_cancelled'] = JOStatus::CANCELLED;
// get template to display
$params['template'] = $this->getTwigTemplate('jo_open_rider_form');
return $params;
}
// generate pdf form for job order
public function generatePDFForm($req, $id, $proj_path)
{
$em = $this->em;
$translator = $this->translator;
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
throw new NotFoundHttpException('The job order does not exist');
// set output filename
$filename = 'job-order-' . $obj->getID() . '.pdf';
// translate the title and the logo for the pdf
$translated_title = $translator->trans('jo_title_pdf');
$translated_logo = $translator->trans('image_jo_pdf');
$translated_delivery_instructions_label = $translator->trans('delivery_instructions_label');
// generate the pdf
$pdf = new FPDF('P', 'mm', 'letter');
$pdf->AddPage();
$pdf->setTitle($translated_title . ' #' . $obj->getID());
$pdf->SetFillColor(211, 211, 211);
// style defaults
$margin = 10;
$page_width = $pdf->GetPageWidth() - ($margin * 2);
$table_col_width = $page_width / 12;
$line_height = 5;
$jo_line_height = 10;
$table_line_height = 7;
$font_face = 'Arial';
$body_font_size = 9;
$header_font_size = 9;
$jo_font_size = 16;
$col1_x = $margin;
$col2_x = 120;
$label_width = 40;
$val_width = 60;
// insert the logo
$image_path = $proj_path . $translated_logo;
$pdf->Image($image_path, $col1_x, 10);
// insert JO number
$pdf->SetFont($font_face, 'B', $jo_font_size);
$pdf->SetX($col2_x);
$pdf->Cell($label_width, $jo_line_height, 'JO Number:');
$pdf->SetTextColor(9, 65, 150);
$pdf->Cell(0, $jo_line_height, $obj->getID());
// insert customer info
$customer = $obj->getCustomer();
$pdf->SetFont($font_face, '', $body_font_size);
$pdf->SetTextColor(0, 0, 0);
$pdf->Ln($line_height * 7);
// get current Y
$y = $pdf->GetY();
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Customer Name:');
$pdf->MultiCell($val_width, $line_height, $customer ? $customer->getFirstName() . ' ' . $customer->getLastName() : '', 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Mobile Phone:');
$pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneMobile() ? $this->country_code . $customer->getPhoneMobile() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Delivery Date:');
$pdf->MultiCell($val_width, $line_height, $obj->getDateSchedule() ? $obj->getDateSchedule()->format("m/d/Y") : '', 0, 'left');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Landline:');
$pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneLandline() ? $this->country_code . $customer->getPhoneLandline() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Office Phone:');
$pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneOffice() ? $this->country_code . $customer->getPhoneOffice() : '', 0, 'L');
$pdf->SetX($col2_x);
$pdf->Cell($label_width, $line_height, 'Fax:');
$pdf->MultiCell($val_width, $line_height, $customer && $customer->getPhoneFax() ? $this->country_code . $customer->getPhoneFax() : '', 0, 'L');
// insert vehicle info
$cv = $obj->getCustomerVehicle();
$vehicle = $cv->getVehicle();
$pdf->Ln();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell($label_width, $line_height, 'Vehicle Details');
$pdf->Ln($line_height * 2);
// get current Y
$y = $pdf->GetY();
$pdf->SetFont($font_face, '', $body_font_size);
$pdf->Cell($label_width, $line_height, 'Plate Number:');
$pdf->MultiCell($val_width, $line_height, $cv ? $cv->getPlateNumber() : '', 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Vehicle Color:');
$pdf->MultiCell(0, $line_height, $cv ? $cv->getColor() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Brand:');
$pdf->MultiCell($val_width, $line_height, $vehicle && $vehicle->getManufacturer() ? $vehicle->getManufacturer()->getName() : '', 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Model / Year:');
$pdf->MultiCell(0, $line_height, $cv ? $cv->getModelYear() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Make:');
$pdf->MultiCell($val_width, $line_height, $vehicle ? $vehicle->getMake() : '', 0, 'L');
// insert battery info
$battery = $cv->getCurrentBattery();
$pdf->Ln();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell($label_width, $line_height, 'Battery Details');
$pdf->Ln($line_height * 2);
$pdf->SetFont($font_face, '', $body_font_size);
// get current Y
$y = $pdf->GetY();
$pdf->Cell($label_width, $line_height, 'Current Battery:');
$pdf->MultiCell($val_width, $line_height, $battery && $battery->getManufacturer() && $battery->getModel() && $battery->getSize() ? $battery->getManufacturer()->getName() . ' ' . $battery->getModel()->getName() . ' ' . $battery->getSize()->getName() . ' (' . $battery->getProductCode() . ')' : '', 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Serial Number:');
$pdf->MultiCell(0, $line_height, $cv ? $cv->getWarrantyCode() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Wty. Exp. Date:');
$pdf->MultiCell($val_width, $line_height, $cv && $cv->getWarrantyExpiration() ? $cv->getWarrantyExpiration()->format("d/m/Y") : '', 0, 'L');
// insert transaction details
$pdf->Ln();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell($label_width, $line_height, 'Transaction Details');
$pdf->Ln($line_height * 2);
$pdf->SetFont($font_face, '', $body_font_size);
// get current Y
$y = $pdf->GetY();
$pdf->Cell($label_width, $line_height, 'Warranty Class:');
$pdf->MultiCell($val_width, $line_height, CMBWarrantyClass::getName($obj->getWarrantyClass()), 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Mode of Payment:');
$pdf->MultiCell(0, $line_height, CMBModeOfPayment::getName($obj->getModeOfPayment()), 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->Cell($label_width, $line_height, 'Delivery Address:');
$pdf->MultiCell($val_width, $line_height, $obj->getDeliveryAddress(), 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Landmark:');
$pdf->MultiCell(0, $line_height, $obj->getLandMark(), 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Dispatch Time:');
$pdf->MultiCell($val_width, $line_height, $obj->getDateSchedule() ? $obj->getDateSchedule()->format("g:i A") : '', 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->Cell($label_width, $line_height, 'Dispatched By:');
$pdf->MultiCell(0, $line_height, $obj->getProcessedBy() ? $obj->getProcessedBy()->getFullName() : '', 0, 'L');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
// insert delivery instructions
$pdf->SetY($y);
$pdf->Ln();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell(0, $line_height, $translated_delivery_instructions_label);
$pdf->Ln();
$pdf->SetFont($font_face, '', $body_font_size);
$pdf->MultiCell(0, $line_height, $obj->getDeliveryInstructions(), 1, 'L');
// insert invoice details
$pdf->Ln();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell($label_width, $line_height, 'Invoice Details');
$pdf->Ln();
// invoice table headers
$invoice = $obj->getInvoice();
$pdf->SetFont($font_face, 'B', $header_font_size);
$pdf->Cell($table_col_width * 6, $table_line_height, 'Item', 1, 0, 'L', 1);
$pdf->Cell($table_col_width * 2, $table_line_height, 'Quantity', 1, 0, 'R', 1);
$pdf->Cell($table_col_width * 2, $table_line_height, 'Unit Price', 1, 0, 'R', 1);
$pdf->Cell($table_col_width * 2, $table_line_height, 'Amount', 1, 1, 'R', 1);
$pdf->SetFont($font_face, '', $body_font_size);
// build invoice items table
if ($invoice && !empty($invoice->getItems()))
{
foreach ($invoice->getItems() as $item)
{
$pdf->Cell($table_col_width * 6, $table_line_height, $item->getTitle(), 1);
$pdf->Cell($table_col_width * 2, $table_line_height, number_format($item->getQuantity()), 1, 0, 'R');
$pdf->Cell($table_col_width * 2, $table_line_height, number_format($item->getPrice(), 2), 1, 0, 'R');
$pdf->Cell($table_col_width * 2, $table_line_height, number_format($item->getPrice() * $item->getQuantity(), 2), 1, 1, 'R');
}
}
else
{
$pdf->Cell($table_col_width * 12, 7, 'No items', 1, 1);
}
$pdf->Ln($line_height * 2);
// get current Y
$y = $pdf->GetY();
// insert invoice footer details
$pdf->Cell($label_width, $line_height, 'Transaction Type:');
$pdf->MultiCell($val_width, $line_height, CMBServiceType::getName($obj->getServiceType()), 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->SetFont($font_face, 'B');
$pdf->Cell($label_width, $line_height, 'SUBTOTAL:');
$pdf->SetFont($font_face, '');
$pdf->MultiCell(0, $line_height, $invoice ? number_format($invoice->getVATExclusivePrice(), 2) : '', 0, 'R');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'OR Name:');
$pdf->MultiCell($val_width, $line_height, $obj->getORName(), 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->SetFont($font_face, 'B');
$pdf->Cell($label_width, $line_height, 'TAX:');
$pdf->SetFont($font_face, '');
$pdf->MultiCell(0, $line_height, $invoice ? number_format($invoice->getVAT(), 2) : '', 0, 'R');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Emp. ID/Card No./Ref. By:');
$pdf->MultiCell($val_width, $line_height, $obj->getPromoDetail(), 0, 'L');
// get Y after left cell
$y1 = $pdf->GetY();
$pdf->SetXY($col2_x, $y);
$pdf->SetFont($font_face, 'B');
$pdf->Cell($label_width, $line_height, 'DISCOUNT:');
$pdf->SetFont($font_face, '');
$pdf->MultiCell(0, $line_height, $invoice ? number_format($invoice->getDiscount(), 2) : '', 0, 'R');
// get Y after right cell
$y2 = $pdf->GetY();
// get row height
$y = max($y1, $y2);
$pdf->SetXY($col1_x, $y);
$pdf->Cell($label_width, $line_height, 'Discount Type:');
$pdf->MultiCell($val_width, $line_height, $invoice && $invoice->getPromo() ? $invoice->getPromo()->getName() : '', 0, 'L');
$pdf->SetXY($col2_x, $y);
$pdf->SetFont($font_face, 'B');
$pdf->Cell($label_width, $line_height, 'FINAL AMOUNT:');
$pdf->MultiCell(0, $line_height, $invoice ? number_format($invoice->getTotalPrice(), 2) : '', 0, 'R');
$pdf->SetFont($font_face, '');
$params['obj'] = $pdf;
$params['filename'] = $filename;
return $params;
}
public function getTwigTemplate($id)
{
if (isset($this->template_hash[$id]))
{
return $this->template_hash[$id];
}
return null;
}
public function updateVehicleBattery(JobOrder $jo)
{
// check if new battery
if (!($this->checkIfNewBattery($jo)))
return;
// customer vehicle
$cv = $jo->getCustomerVehicle();
if ($cv == null)
return;
// invoice
$invoice = $jo->getInvoice();
if ($invoice == null)
return;
// invoice items
$items = $invoice->getItems();
if (count($items) <= 0)
return;
// get first battery from invoice
$battery = null;
foreach ($items as $item)
{
$battery = $item->getBattery();
if ($battery != null)
break;
}
// no battery in order
if ($battery == null)
return;
// warranty expiration
// use GetWarrantyPrivate for passenger warranty
$warr_months = 0;
$warr = $jo->getWarrantyClass();
if ($warr == CMBWarrantyClass::WTY_PASSENGER)
$warr_months = $battery->getWarrantyPrivate();
else if ($warr == CMBWarrantyClass::WTY_COMMERCIAL)
$warr_months = $battery->getWarrantyCommercial();
$warr_date = new DateTime();
$warr_date->add(new DateInterval('P' . $warr_months . 'M'));
// update customer vehicle battery
$cv->setCurrentBattery($battery)
->setHasMotoliteBattery(true)
->setWarrantyExpiration($warr_date);
}
public function getOtherParameters()
{
// get riders for dropdown
$params['riders'] = $this->em->getRepository(Rider::class)->findAll();
return $params;
}
public function checkIfNewBattery(JobOrder $jo)
{
if ($jo->getServiceType() == CMBServiceType::BATTERY_REPLACEMENT_NEW)
return true;
return false;
}
protected function fillDropdownParameters(&$params)
{
$em = $this->em;
// db loaded
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
$params['promos'] = $em->getRepository(Promo::class)->findAll();
// list of hubs
$hubs = $em->getRepository(Hub::class)->findBy([], ['name' => 'ASC']);
$fac_hubs = [];
foreach ($hubs as $hub)
{
$fac_hubs[$hub->getID()] = $hub->getName() . ' - ' . $hub->getBranch();
}
// name values
$params['service_types'] = CMBServiceType::getCollection();
$params['warranty_classes'] = CMBWarrantyClass::getCollection();
$params['modes_of_payment'] = CMBModeOfPayment::getCollection();
$params['statuses'] = JOStatus::getCollection();
$params['discount_apply'] = DiscountApply::getCollection();
$params['trade_in_types'] = CMBTradeInType::getCollection();
$params['facilitated_types'] = FacilitatedType::getCollection();
$params['facilitated_hubs'] = $fac_hubs;
$params['sources'] = TransactionOrigin::getCollection();
}
protected function initFormTags(&$params)
{
// default to editing, as we have more forms editing than creating
$params['ftags'] = [
'title' => 'Job Order Form',
'vehicle_dropdown' => false,
'invoice_edit' => false,
'set_map_coordinate' => true,
'preset_vehicle' => false,
'ticket_table' => true,
'cancel_button' => true,
];
}
protected function fillFormTags(&$params)
{
$this->initFormTags($params);
switch ($params['mode'])
{
case 'create':
$params['ftags']['vehicle_dropdown'] = true;
$params['ftags']['set_map_coordinate'] = false;
$params['ftags']['invoice_edit'] = true;
$params['ftags']['ticket_table'] = false;
$params['ftags']['cancel_button'] = false;
break;
case 'create_vehicle':
$params['ftags']['set_map_coordinate'] = false;
$params['ftags']['invoice_edit'] = true;
$params['ftags']['preset_vehicle'] = true;
$params['ftags']['ticket_table'] = false;
$params['ftags']['cancel_button'] = false;
break;
case 'open_edit':
$params['ftags']['invoice_edit'] = true;
$params['ftags']['preset_vehicle'] = true;
break;
case 'onestep':
$params['ftags']['vehicle_dropdown'] = true;
$params['ftags']['set_map_coordinate'] = false;
$params['ftags']['invoice_edit'] = true;
$params['ftags']['ticket_table'] = false;
$params['ftags']['cancel_button'] = false;
break;
case 'onestep-edit':
$params['ftags']['invoice_edit'] = true;
$params['ftags']['preset_vehicle'] = true;
break;
}
}
protected function loadTemplates()
{
$this->template_hash = [];
// add all twig templates for job order to hash
// TODO: put this in an array declaration
// $this->template_hash = [
// 'blah' => 'blah',
// ];
$this->template_hash['jo_incoming_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_open_edit_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_incoming_vehicle_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_processing_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_assigning_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_fulfillment_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_open_hub_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_open_rider_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_all_form'] = 'job-order/cmb.form.html.twig';
$this->template_hash['jo_list_processing'] = 'job-order/list.processing.html.twig';
$this->template_hash['jo_list_assigning'] = 'job-order/list.assigning.html.twig';
$this->template_hash['jo_list_fulfillment'] = 'job-order/list.fulfillment.html.twig';
$this->template_hash['jo_list_open'] = 'job-order/list.open.html.twig';
$this->template_hash['jo_list_all'] = 'job-order/list.all.html.twig';
$this->template_hash['jo_onestep'] = 'job-order/cmb.form.onestep.html.twig';
$this->template_hash['jo_onestep_edit_form'] = 'job-order/cmb.form.onestep.html.twig';
}
protected function checkTier($tier)
{
// check specified tier
switch ($tier) {
case 'proc':
$tier_key = 'jo_proc';
$tier_name = 'Dispatch';
$rows_route = 'jo_proc_rows';
$edit_route = 'jo_proc_form';
$unlock_route = 'jo_proc_unlock';
$jo_status = JOStatus::PENDING;
break;
case 'assign':
$tier_key = 'jo_assign';
$tier_name = 'Assigning';
$rows_route = 'jo_assign_rows';
$edit_route = 'jo_assign_form';
$unlock_route = 'jo_assign_unlock';
$jo_status = JOStatus::RIDER_ASSIGN;
break;
case 'fulfill':
$tier_key = 'jo_fulfill';
$tier_name = 'Fullfillment';
$rows_route = 'jo_fulfill_rows';
$edit_route = 'jo_fulfill_form';
$unlock_route = '';
$jo_status = [
JOStatus::ASSIGNED,
JOStatus::IN_PROGRESS
];
break;
case 'open':
$tier_key = 'jo_open';
$tier_name = 'Open';
$rows_route = 'jo_open_rows';
$edit_route = '';
$unlock_route = '';
$jo_status = [
JOStatus::PENDING,
JOStatus::RIDER_ASSIGN,
JOStatus::ASSIGNED,
JOStatus::IN_PROGRESS,
JOStatus::IN_TRANSIT,
];
break;
case 'all':
$tier_key = 'jo_open';
$tier_name = 'Open';
$rows_route = 'jo_open_rows';
$edit_route = 'jo_all_form';
$unlock_route = '';
$jo_status = '';
break;
default:
throw new AccessDeniedHttpException('No access.');
}
// check acl
if (!($this->security->isGranted($tier_key . '.list')))
throw new AccessDeniedHttpException('No access.');
// return params if allowed access
return [
'key' => $tier_key,
'name' => $tier_name,
'rows_route' => $rows_route,
'edit_route' => $edit_route,
'unlock_route' => $unlock_route,
'jo_status' => $jo_status
];
}
// 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, $hubs, $tier, $status)
{
switch ($tier)
{
case 'fulfill':
if (isset($datatable['query']['data-rows-search']))
{
$query->innerJoin('q.cus_vehicle', 'cv')
->innerJoin('q.customer', 'c')
->where('cv.plate_number like :filter')
->orWhere('c.phone_mobile like :filter')
->orWhere('c.first_name like :filter or c.last_name like :filter')
->setParameter('filter', $datatable['query']['data-rows-search'] . '%');
}
if (isset($datatable['query']['rider']))
{
$query->innerJoin('q.rider', 'r')
->andWhere('r.id = :rider_id')
->setParameter('rider_id', $datatable['query']['rider']);
}
if (isset($datatable['query']['schedule_date']))
{
$start = $datatable['query']['schedule_date'][0] . ' ' . '00:00:00';
$end = $datatable['query']['schedule_date'][1] . ' ' . '23:59:00';
$date_start = DateTime::createFromFormat('m/d/Y H:i:s', $start);
$date_end = DateTime::createFromFormat('m/d/Y H:i:s', $end);
$query->andWhere('q.date_schedule >= :date_start')
->andWhere('q.date_schedule <= :date_end')
->setParameter('date_start', $date_start)
->setParameter('date_end', $date_end);
}
$query->andWhere('q.status IN (:statuses)')
->andWhere('q.hub IN (:hubs)')
->setParameter('statuses', $status, Connection::PARAM_STR_ARRAY)
->setParameter('hubs', $hubs, Connection::PARAM_STR_ARRAY);
break;
case 'assign':
$query->where('q.status = :status')
->andWhere('q.hub IN (:hubs)')
->setParameter('status', $status)
->setParameter('hubs', $hubs, Connection::PARAM_STR_ARRAY);
break;
case 'open':
if (isset($datatable['query']['data-rows-search']))
{
$query->innerJoin('q.cus_vehicle', 'cv')
->innerJoin('q.customer', 'c')
->where('q.status IN (:statuses)')
->andWhere('cv.plate_number like :filter or c.first_name like :filter or c.last_name like :filter or c.phone_mobile like :filter')
->setParameter('statuses', $status, Connection::PARAM_STR_ARRAY)
->setParameter('filter', $datatable['query']['data-rows-search'] . '%');
}
else
{
$query->where('q.status IN (:statuses)')
->setParameter('statuses', $status, Connection::PARAM_STR_ARRAY);
}
if (isset($datatable['query']['rider']))
{
$query->innerJoin('q.rider', 'r')
->andWhere('r.id = :rider_id')
->setParameter('rider_id', $datatable['query']['rider']);
}
if (isset($datatable['query']['schedule_date']))
{
$start = $datatable['query']['schedule_date'][0] . ' ' . '00:00:00';
$end = $datatable['query']['schedule_date'][1] . ' ' . '23:59:00';
$date_start = DateTime::createFromFormat('m/d/Y H:i:s', $start);
$date_end = DateTime::createFromFormat('m/d/Y H:i:s', $end);
$query->andWhere('q.date_schedule >= :date_start')
->andWhere('q.date_schedule <= :date_end')
->setParameter('date_start', $date_start)
->setParameter('date_end', $date_end);
}
break;
case 'all':
if (isset($datatable['query']['data-rows-search']))
{
$query->innerJoin('q.cus_vehicle', 'cv')
->innerJoin('q.customer', 'c')
->where('cv.plate_number like :filter')
->orWhere('c.phone_mobile like :filter')
->orWhere('c.first_name like :filter or c.last_name like :filter')
->setParameter('filter', $datatable['query']['data-rows-search'] . '%');
}
if (isset($datatable['query']['rider']))
{
$query->innerJoin('q.rider', 'r')
->andWhere('r.id = :rider_id')
->setParameter('rider_id', $datatable['query']['rider']);
}
if (isset($datatable['query']['schedule_date']))
{
$start = $datatable['query']['schedule_date'][0] . ' ' . '00:00:00';
$end = $datatable['query']['schedule_date'][1] . ' ' . '23:59:00';
$date_start = DateTime::createFromFormat('m/d/Y H:i:s', $start);
$date_end = DateTime::createFromFormat('m/d/Y H:i:s', $end);
$query->andWhere('q.date_schedule >= :date_start')
->andWhere('q.date_schedule <= :date_end')
->setParameter('date_start', $date_start)
->setParameter('date_end', $date_end);
}
break;
default:
$query->where('q.status = :status')
->setParameter('status', $status);
}
}
}