From db2904f4de462b7174a05766d3e5f645bf95ce05 Mon Sep 17 00:00:00 2001 From: Ramon Gutierrez Date: Mon, 19 Feb 2018 23:28:50 +0800 Subject: [PATCH] Add fulfillment job order list and form #15 --- config/acl.yaml | 2 + config/menu.yaml | 4 + config/routes/job_order.yaml | 22 ++ src/Controller/JobOrderController.php | 200 ++++++++++++++---- templates/job-order/form.html.twig | 140 +++++++----- .../job-order/list.fulfillment.html.twig | 132 ++++++++++++ 6 files changed, 414 insertions(+), 86 deletions(-) create mode 100644 templates/job-order/list.fulfillment.html.twig diff --git a/config/acl.yaml b/config/acl.yaml index 9edbb5cf..ce8eb67a 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -189,6 +189,8 @@ access_keys: label: Processing - id: jo_assign.list label: Assigning + - id: jo_fulfill.list + label: Fulfillment - id: support label: Customer Support Access diff --git a/config/menu.yaml b/config/menu.yaml index 7c72fbc9..aa4f7a67 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -93,6 +93,10 @@ main_menu: acl: jo_assign.list label: Assigning parent: joborder + - id: jo_fulfill + acl: jo_fulfill.list + label: Fulfillment + parent: joborder - id: support acl: support.menu diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index 78a6204d..1563f374 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -58,3 +58,25 @@ jo_gen_invoice: path: /job-order/generate-invoice controller: App\Controller\JobOrderController::generateInvoice methods: [POST] + +jo_fulfill: + path: /job-order/fulfillment + controller: App\Controller\JobOrderController::listFulfillment + methods: [GET] + +jo_fulfill_rows: + path: /job-order/fulfillment-rows + controller: App\Controller\JobOrderController::getRows + methods: [POST] + defaults: + tier: "fulfill" + +jo_fulfill_form: + path: /job-order/fulfillment/{id} + controller: App\Controller\JobOrderController::fulfillmentForm + methods: [GET] + +jo_fulfill_submit: + path: /job-order/fulfillment/{id} + controller: App\Controller\JobOrderController::fulfillmentSubmit + methods: [POST] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 330164aa..7a2d4e1c 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -194,6 +194,16 @@ class JobOrderController extends BaseController $edit_route = 'jo_assign_form'; $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'; + $jo_status = [ + JOStatus::ASSIGNED, + JOStatus::IN_PROGRESS + ]; + break; default: $exception = $this->createAccessDeniedException('No access.'); throw $exception; @@ -221,6 +231,15 @@ class JobOrderController extends BaseController return $this->render('job-order/list.assigning.html.twig', $params); } + public function listFulfillment() + { + $params = $this->initParameters('jo_fulfill'); + + $params['table_refresh_rate'] = $this->container->getParameter('job_order_refresh_interval'); + + return $this->render('job-order/list.fulfillment.html.twig', $params); + } + public function listRows($tier) { // check which job order tier is being called for and confirm access @@ -597,37 +616,6 @@ class JobOrderController extends BaseController $params['discount_apply'] = DiscountApply::getCollection(); $params['trade_in_types'] = TradeInType::getCollection(); - // get closest hubs - $hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 10, 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; - } - - $params['hubs'][] = $hub; - } - $params['obj'] = $obj; $params['submit_url'] = $this->generateUrl('jo_assign_submit', ['id' => $obj->getID()]); $params['return_url'] = $this->generateUrl('jo_assign'); @@ -715,19 +703,155 @@ class JobOrderController extends BaseController } + + + + + + + public function fulfillmentForm(MapTools $map_tools, $id) + { + $this->denyAccessUnlessGranted('jo_assign.list', null, 'No access.'); + + $em = $this->getDoctrine()->getManager(); + + $params = $this->initParameters('jo_assign'); + $params['mode'] = 'update-fulfillment'; + + // get row data + $obj = $em->getRepository(JobOrder::class)->find($id); + + // make sure this row exists + if (empty($obj)) + { + throw $this->createNotFoundException('The job order does not exist'); + } + + // check status + if (!in_array($obj->getStatus(), [JOStatus::ASSIGNED, JOStatus::IN_PROGRESS])) + { + throw $this->createNotFoundException('The job order does not have a fulfillment status'); + } + + // check if hub is assigned to current user + $user_hubs = $this->getUser()->getHubs(); + if (!in_array($obj->getHub()->getID(), $user_hubs)) + { + throw $this->createNotFoundException('The job order is not on a hub assigned to this user'); + } + + // get parent associations + $params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll(); + $params['customers'] = $em->getRepository(Customer::class)->findAll(); + $params['service_types'] = ServiceType::getCollection(); + $params['warranty_classes'] = WarrantyClass::getCollection(); + $params['statuses'] = JOStatus::getCollection(); + $params['promos'] = $em->getRepository(Promo::class)->findAll(); + $params['discount_apply'] = DiscountApply::getCollection(); + $params['trade_in_types'] = TradeInType::getCollection(); + + $params['obj'] = $obj; + $params['submit_url'] = $this->generateUrl('jo_fulfill_submit', ['id' => $obj->getID()]); + $params['return_url'] = $this->generateUrl('jo_fulfill'); + + // response + return $this->render('job-order/form.html.twig', $params); + } + + public function fulfillmentSubmit(Request $req, ValidatorInterface $validator, $id) + { + $this->denyAccessUnlessGranted('jo_assign.list', null, 'No access.'); + + // initialize error list + $error_array = []; + + // get object data + $em = $this->getDoctrine()->getManager(); + $obj = $em->getRepository(JobOrder::class)->find($id); + + // make sure this object exists + if (empty($obj)) + throw $this->createNotFoundException('The item does not exist'); + + // check if lat and lng are provided + if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) { + $error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.'; + } + + 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('web') + ->setStatus(JOStatus::FULFILLED) + ->setDeliveryInstructions($req->request->get('delivery_instructions')) + ->setAgentNotes($req->request->get('agent_notes')) + ->setDeliveryAddress($req->request->get('delivery_address')); + + // validate + $errors = $validator->validate($obj); + + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + } + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + // validated! save the entity + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + + + + + + + + + // TODO: re-enable search, figure out how to group the orWhere filters into one, so can execute that plus the pending filter // check if datatable filter is present and append to query protected function setQueryFilters($datatable, &$query, $qb, $hubs, $tier, $status) { - $query->where('q.status = :status') - ->setParameter('status', $status); - - // on assigning, filter by assigned hub - if ($tier == 'assign') + switch ($tier) { - $query->andWhere('q.hub IN (:hubs)') - ->setParameter('hubs', $hubs, Connection::PARAM_STR_ARRAY); + case 'fulfill': + $query->where('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; + default: + $query->where('q.status = :status') + ->setParameter('status', $status); } // get only pending rows diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index bc91ef46..e66a6433 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -425,7 +425,7 @@
{% endif %} - {% if mode == 'update-assigning' %} + {% if mode in ['update-assigning', 'update-fulfillment'] %}
{% if obj.getHub %}
@@ -469,56 +469,100 @@
{% endif %} -
-
-
-

- Rider Assignment -

-
-
-
- - -
- - - - - - - - - - - - - - - - {% if obj.getHub %} - {% for rider in obj.getHub.getRiders %} - - - - - - - - - {% endfor %} - {% endif %} - -
First NameLast NameContact No.Plate NumberStatus
- No items to display. -
-
-
{{ rider.getFirstName }}{{ rider.getLastName }}{{ rider.getContactNumber }}{{ rider.getPlateNumber }}
+
+ + {% if mode == 'update-assigning' %} +
+
+

+ Rider Assignment +

+
+
+
+ + +
+ + + + + + + + + + + + + + + + + {% if obj.getHub %} + {% for rider in obj.getHub.getRiders %} + + + + + + + + + {% endfor %} + {% endif %} + +
First NameLast NameContact No.Plate NumberStatus
+ No items to display. +
+
+
{{ rider.getFirstName }}{{ rider.getLastName }}{{ rider.getContactNumber }}{{ rider.getPlateNumber }}
+
-
+ {% endif %} + + {% if mode == 'update-fulfillment' %} +
+
+

+ Rider Details +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+
+
+
+ {% endif %} {% endif %}
@@ -526,7 +570,7 @@
- + {% if mode != 'create' %} Cancel {% endif %} diff --git a/templates/job-order/list.fulfillment.html.twig b/templates/job-order/list.fulfillment.html.twig new file mode 100644 index 00000000..b4964103 --- /dev/null +++ b/templates/job-order/list.fulfillment.html.twig @@ -0,0 +1,132 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

+ Job Orders (Fulfillment) +

+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %}