Move the dispatch and assign rider to job order to the service. #270

This commit is contained in:
Korina Cordero 2019-09-27 09:59:55 +00:00
parent 37c0945db9
commit bd8696311c
4 changed files with 505 additions and 205 deletions

View file

@ -251,12 +251,12 @@ class JobOrderController extends Controller
return $this->render('job-order/form.html.twig', $params);
}
public function openEditSubmit(Request $req, JobOrderHandlerInterface $joc, $id)
public function openEditSubmit(Request $req, JobOrderHandlerInterface $jo_handler, $id)
{
$this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.');
$error_array = [];
$error_array = $joc->generateJobOrder($req, $id);
$error_array = $jo_handler->generateJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
@ -310,14 +310,14 @@ class JobOrderController extends Controller
return $this->render('job-order/form.html.twig', $params);
}
public function incomingSubmit(Request $req, JobOrderHandlerInterface $joc)
public function incomingSubmit(Request $req, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_in.list', null, 'No access.');
// initialize error list
$error_array = [];
$id = -1;
$error_array = $joc->generateJobOrder($req, $id);
$error_array = $jo_handler->generateJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
@ -736,111 +736,13 @@ class JobOrderController extends Controller
return $this->render('job-order/form.html.twig', $params);
}
public function processingSubmit(Request $req, ValidatorInterface $validator, MQTTClient $mclient, $id)
public function processingSubmit(Request $req, JobOrderHandlerInterface $jo_handler, MQTTClient $mclient, $id)
{
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
// get object data
$em = $this->getDoctrine()->getManager();
$obj = $em->getRepository(JobOrder::class)->find($id);
$processor = $obj->getProcessedBy();
$user = $this->getUser();
// check if we're the one processing, return error otherwise
if ($processor == null)
throw $this->createAccessDeniedException('Not the processor');
if ($processor != null && $processor->getID() != $user->getID())
throw $this->createAccessDeniedException('Not the processor');
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// check if cancelled already
if (!$obj->canDispatch())
{
throw $this->createNotFoundException('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 = $validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
$error_array = $jo_handler->dispatchJobOrder($req, $id, $mclient);
// check if any errors were found
if (!empty($error_array))
@ -852,23 +754,6 @@ class JobOrderController extends Controller
], 422);
}
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setUser($this->getUser())
->setJobOrder($obj);
$em->persist($event);
// validated! save the entity
$em->flush();
// send event to mobile app
$payload = [
'event' => 'outlet_assign'
];
$mclient->sendEvent($obj, $payload);
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
@ -957,71 +842,14 @@ class JobOrderController extends Controller
return $this->render('job-order/form.html.twig', $params);
}
public function assigningSubmit(Request $req, ValidatorInterface $validator, MQTTCLient $mclient, APNSClient $aclient, $id)
public function assigningSubmit(Request $req, ValidatorInterface $validator, JobOrderHandlerInterface $jo_handler, MQTTCLient $mclient, APNSClient $aclient, $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 we can assign
if (!$obj->canAssign())
throw $this->createNotFoundException('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.';
}
}
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'))
->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();
}
}
$error_array = $jo_handler->assignJobOrder($req, $id, $mclient, $aclient);
// check if any errors were found
if (!empty($error_array)) {
@ -1032,31 +860,6 @@ class JobOrderController extends Controller
], 422);
}
// set rider unavailable
$rider->setAvailable(false);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::RIDER_ASSIGN)
->setUser($this->getUser())
->setJobOrder($obj);
$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);
// sned push notification
$aclient->sendPush($obj, "A RESQ rider is on his way to you.");
// return successful response
return $this->json([
'success' => 'Changes have been saved!'

View file

@ -12,6 +12,7 @@ use App\Entity\JobOrder;
use App\Entity\Battery;
use App\Entity\JOEvent;
use App\Entity\CustomerVehicle;
use App\Entity\Hub;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\ServiceType;
@ -21,6 +22,8 @@ use App\Ramcar\JOStatus;
use App\Service\InvoiceGeneratorInterface;
use App\Service\JobOrderHandlerInterface;
use App\Service\MQTTClient;
use App\Service\APNSClient;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
@ -39,6 +42,8 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
$this->security = $security;
$this->validator = $validator;
}
// creates/updates job order
public function generateJobOrder(Request $req, $id)
{
// initialize error list
@ -161,6 +166,243 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
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 $this->createAccessDeniedException('Not the processor');
if ($processor != null && $processor->getID() != $user->getID())
throw $this->createAccessDeniedException('Not the processor');
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// check if cancelled already
if (!$obj->canDispatch())
{
throw $this->createNotFoundException('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 = $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;
}
// assigning job order
public function assignJobOrder(Request $req, $id, MQTTCLient $mclient, APNSClient $aclient)
{
// get object data
$em = $this->em;
$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 we can assign
if (!$obj->canAssign())
throw $this->createNotFoundException('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 = $validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// set rider unavailable
$rider->setAvailable(false);
// 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();
// send event to mobile app
$payload = [
'event' => 'driver_assigned'
];
$mclient->sendEvent($obj, $payload);
$mclient->sendRiderEvent($obj, $payload);
// sned push notification
$aclient->sendPush($obj, "A RESQ rider is on his way to you.");
}
return $error_array;
}
// TODO: move this to InvoiceGenerator
protected function processInvoice($jo, $promo_id, $invoice_items, &$error_array)
{
// instantiate the invoice criteria
@ -220,6 +462,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
}
}
//TODO: move this to InvoiceGenerator
protected function invoicePromo(InvoiceCriteria $criteria, $promo_id)
{
// return error if there's a problem, false otherwise
@ -244,6 +487,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
return false;
}
// TODO: move this to InvoiceGenerator
protected function invoiceBatteries(InvoiceCriteria $criteria, $items)
{
// check service type

View file

@ -12,6 +12,7 @@ use App\Entity\JobOrder;
use App\Entity\Battery;
use App\Entity\JOEvent;
use App\Entity\CustomerVehicle;
use App\Entity\Hub;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\ServiceType;
@ -21,6 +22,8 @@ use App\Ramcar\JOStatus;
use App\Service\InvoiceGeneratorInterface;
use App\Service\JobOrderHandlerInterface;
use App\Service\MQTTClient;
use App\Service\APNSClient;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
@ -39,6 +42,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$this->security = $security;
$this->validator = $validator;
}
// creates/updates job order
public function generateJobOrder(Request $req, $id)
{
// initialize error list
@ -161,6 +166,243 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
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 $this->createAccessDeniedException('Not the processor');
if ($processor != null && $processor->getID() != $user->getID())
throw $this->createAccessDeniedException('Not the processor');
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// check if cancelled already
if (!$obj->canDispatch())
{
throw $this->createNotFoundException('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 = $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;
}
// assigning job order
public function assignJobOrder(Request $req, $id, MQTTCLient $mclient, APNSClient $aclient)
{
// get object data
$em = $this->em;
$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 we can assign
if (!$obj->canAssign())
throw $this->createNotFoundException('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 = $validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// set rider unavailable
$rider->setAvailable(false);
// 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();
// send event to mobile app
$payload = [
'event' => 'driver_assigned'
];
$mclient->sendEvent($obj, $payload);
$mclient->sendRiderEvent($obj, $payload);
// sned push notification
$aclient->sendPush($obj, "A RESQ rider is on his way to you.");
}
return $error_array;
}
// TODO: move this to InvoiceGenerator
protected function processInvoice($jo, $promo_id, $invoice_items, &$error_array)
{
// instantiate the invoice criteria
@ -220,6 +462,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
}
}
//TODO: move this to InvoiceGenerator
protected function invoicePromo(InvoiceCriteria $criteria, $promo_id)
{
// return error if there's a problem, false otherwise
@ -244,6 +487,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
return false;
}
// TODO: move this to InvoiceGenerator
protected function invoiceBatteries(InvoiceCriteria $criteria, $items)
{
// check service type

View file

@ -4,8 +4,17 @@ namespace App\Service;
use Symfony\Component\HttpFoundation\Request;
use App\Service\MQTTClient;
use App\Service\APNSClient;
interface JobOrderHandlerInterface
{
// generate job order
public function generateJobOrder(Request $req, int $id);
// dispatch job order
public function dispatchJobOrder(Request $req, int $id, MQTTClient $mclient);
// assigning job order
public function assignJobOrder(Request $req, int $id, MQTTCLient $mclient, APNSClient $aclient);
}