From a030ec6679991fb639b05520c6b2000093651737 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 29 Sep 2020 04:27:11 +0000 Subject: [PATCH 1/5] Add routes and templates for advance order. #509 --- config/acl.yaml | 4 + config/cmb.menu.yaml | 8 + config/menu.yaml | 8 + config/routes/job_order.yaml | 40 + src/Controller/JobOrderController.php | 22 + .../JobOrderHandler/CMBJobOrderHandler.php | 35 +- .../job-order/cmb.form.advanceorder.html.twig | 1656 +++++++++++++++++ 7 files changed, 1772 insertions(+), 1 deletion(-) create mode 100644 templates/job-order/cmb.form.advanceorder.html.twig diff --git a/config/acl.yaml b/config/acl.yaml index 1d1a0c74..ea81ada5 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -272,6 +272,10 @@ access_keys: label: Hub View - id: jo_behind_schedule.list label: View Behind Schedule + - id: jo_advance_order.form + label: New Advance Order + - id: jo_assign_advance_order.form + label: Assign Advance Order - id: support label: Customer Support Access diff --git a/config/cmb.menu.yaml b/config/cmb.menu.yaml index ca756046..c61617eb 100644 --- a/config/cmb.menu.yaml +++ b/config/cmb.menu.yaml @@ -106,6 +106,14 @@ main_menu: acl: jo_onestep.form label: One-step Process parent: joborder + - id: jo_advance_order + acl: jo_advance_order.form + label: New Advance Order + parent: joborder + - id: jo_advance_order_assign + acl: jo_assign_advance_order.form + label: Assign Advance Order + parent: joborder - id: jo_walkin_form acl: jo_walkin.form label: Walk-in diff --git a/config/menu.yaml b/config/menu.yaml index ca756046..c216839b 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -106,6 +106,14 @@ main_menu: acl: jo_onestep.form label: One-step Process parent: joborder + - id: jo_advance_order_form + acl: jo_advance_order.form + label: New Advance Order + parent: joborder + - id: jo_advance_order_assign_form + acl: jo_assign_advance_order.form + label: Assign Advance Order + parent: joborder - id: jo_walkin_form acl: jo_walkin.form label: Walk-in diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index 4ec4279e..45623b22 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -264,3 +264,43 @@ jo_behind_schedule_rows: methods: [POST] defaults: tier: "behind_schedule" + +jo_advance_order_form: + path: /job-order/advance-order + controller: App\Controller\JobOrderController::advanceOrderForm + methods: [GET] + +jo_advance_order_submit: + path: /job-order/advance-order + controller: App\Controller\JobOrderController::advanceOrderSubmit + methods: [POST] + +jo_advance_order_edit_form: + path: /job-order/advance-order/{id}/edit + controller: App\Controller\JobOrderController::advanceOrderEditForm + methods: [GET] + +jo_advance_order_edit_submit: + path: /job-order/onestep/{id}/edit + controller: App\Controller\JobOrderController::advanceOrderEditSubmit + methods: [POST] + +jo_assign_advance_order_form: + path: /job-order/assign-advance-order + controller: App\Controller\JobOrderController::assignAdvanceOrderForm + methods: [GET] + +jo_assign_advance_order_submit: + path: /job-order/assign-advance-order + controller: App\Controller\JobOrderController::assignAdvanceOrderSubmit + methods: [POST] + +jo_assign_advance_order_edit_form: + path: /job-order/assign-advance-order/{id}/edit + controller: App\Controller\JobOrderController::assignAdvanceOrderEditForm + methods: [GET] + +jo_assign_advance_order_edit_submit: + path: /job-order/assign-advance-order/{id}/edit + controller: App\Controller\JobOrderController::assignAdvanceOrderEditSubmit + methods: [POST] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 1b7a451f..d8ff3b06 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1073,6 +1073,28 @@ class JobOrderController extends Controller ]); } + /** + * @Menu(selected="jo_advance_order_form") + */ + public function advanceOrderForm(EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, + GISManagerInterface $gis) + { + $this->denyAccessUnlessGranted('jo_advance_order.form', null, 'No access.'); + + $params = $jo_handler->initializeAdvanceOrderForm(); + $params['submit_url'] = $this->generateUrl('jo_advance_order_submit'); + $params['return_url'] = $this->generateUrl('jo_advance_order_form'); + $params['map_js_file'] = $gis->getJSJOFile(); + $params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll(); + $params['vmakes'] = $em->getRepository(Vehicle::class)->findAll(); + $params['hubs'] = $em->getRepository(Hub::class)->findAll(); + + $template = $params['template']; + + // response + return $this->render($template, $params); + } + /** * @Menu(selected="jo_hub_view") */ diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 1f6250f0..998bc41b 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -2881,6 +2881,32 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface return $params; } + public function initializeAdvanceOrderForm() + { + $new_jo = new JobOrder(); + + // set time schedule + $date_schedule = new DateTime(); + + // add 45 minutes to time + $date_schedule->add(new DateInterval('PT45M')); + $new_jo->setDateSchedule($date_schedule); + + $params['obj'] = $new_jo; + $params['mode'] = 'advanceorder'; + $params['jo_service_charges'] = []; + $params['current_date'] = new DateTime(); + + $this->fillDropdownParameters($params); + $this->fillFormTags($params); + + // get template to display + $params['template'] = $this->getTwigTemplate('jo_advanceorder_form'); + + // return params + return $params; + } + protected function fillDropdownParameters(&$params) { $em = $this->em; @@ -2973,7 +2999,13 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $params['ftags']['invoice_edit'] = true; $params['ftags']['preset_vehicle'] = true; break; - + case 'advanceorder': + $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; } } @@ -2998,6 +3030,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->template_hash['jo_walkin_edit_form'] = 'job-order/cmb.form.walkin.html.twig'; $this->template_hash['jo_popup'] = 'job-order/cmb.popup.html.twig'; $this->template_hash['jo_behind_schedule'] = 'job-order/cmb.list.behindschedule.html.twig'; + $this->template_hash['jo_advanceorder_form'] = 'job-order/cmb.form.advanceorder.html.twig'; } protected function checkTier($tier) diff --git a/templates/job-order/cmb.form.advanceorder.html.twig b/templates/job-order/cmb.form.advanceorder.html.twig new file mode 100644 index 00000000..6e11db8d --- /dev/null +++ b/templates/job-order/cmb.form.advanceorder.html.twig @@ -0,0 +1,1656 @@ +{% extends 'base.html.twig' %} + +{% block body %} + + + +
+ +
+
+
+
+
+
+ + + + {% if mode == "advanceorder" %} +

+ Advance Order Job Order +

+ {% else %} +

+ Advance Order Job Order #{{ obj.getID }} - {{ obj.getStatusText }} +

+ {% endif %} +
+
+
+
+ + +
+ {%if ftags.vehicle_dropdown %} +
+
+
+ + + +
+ +
+
+
+
+
+ + + +
+
+
+ {% else %} + + {% endif %} + {% if obj.getReferenceJO %} +
+
+
+ + + +
+
+
+ {% endif %} + +
+
+

+ Customer Details +

+ + + +
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+
+
+ + + +
+
+
+
+
+

+ Vehicle Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+ +
+
+
+
+

+ Battery Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+
+

+ Transaction Details +

+ + + +
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ +
+ + + + +
+ +
+
+ +
+ + + + +
+ +
+
+
+
+
+ + + +
+
+
+ + +
+
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+
+

+ Location +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + + + +
+ + + + +
+
+
+
+
+ +
+
+

+ {% if mode in ['view-all', 'update-fulfillment'] %} + Assigned Hub + {% else %} + Nearest Hubs + {% endif %} +

+
+
+
+ {% if mode != 'view-all' %} + + {% endif %} + + +
+ + + + + + + + + + + + +
HubBranchContact NumbersDistance in KM
+
+
+
+
+ + {% if mode in ['advanceorder-edit'] %} +
+
+
+

+ Other Information +

+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ +
+ {% for key, picture in jo_pictures %} + {% if key == 'image_1' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_2' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_3' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_4' %} +
+ + + +
+ +
+ {% endif %} + + {% endfor %} +
+ +
+ + + {% endif %} + +
+
+
+

+ Service Charges +

+
+
+ {% if mode != 'view-all' %} +
+ +
+ {% endif %} +
+ + {% for jo_sc in jo_service_charges %} +
+
+
+ +
+
+
+ +
+
+ +
+
+ {% endfor %} +
+ +
+
+
+

+ Invoice +

+
+
+
+ + + +
+ +
+
+
+ + {% if ftags.invoice_edit %} + + + {% else %} + + + {% endif %} +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + + + + + + + + + + {% if not obj.getInvoice or (obj.getInvoice and obj.getInvoice.getItems|length == 0) %} + + + + {% else %} + {% for item in obj.getInvoice.getItems %} + + + + + + + {% endfor %} + {% endif %} + +
ItemQuantityUnit PriceAmount
+ No items to display. +
{{ item.getTitle }}{{ item.getQuantity|number_format }}{{ item.getPrice|number_format(2) }}{{ (item.getPrice * item.getQuantity)|number_format(2) }}
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + +
+
+
+
+
+
+
+
+ {% if mode != 'view-all' %} + + {% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %} + Cancel Job Order + {% endif %} + {% endif %} + Back +
+
+
+
+ +
+
+
+
+{% endblock %} + +{% block scripts %} +{{ include('map/' ~ map_js_file) }} + + + + +{% endblock %} -- 2.43.5 From 55ac665938e06e9a1b0bbd4657c3b861b841bb4e Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 29 Sep 2020 07:55:35 +0000 Subject: [PATCH 2/5] Add edit advance JO. #509 --- config/acl.yaml | 4 + config/menu.yaml | 2 +- config/routes/job_order.yaml | 2 +- src/Controller/JobOrderController.php | 81 +++- .../JobOrderHandler/CMBJobOrderHandler.php | 371 +++++++++++++++++- templates/job-order/cmb.list.all.html.twig | 2 +- .../cmb.list.behindschedule.html.twig | 4 +- templates/job-order/cmb.list.open.html.twig | 4 +- 8 files changed, 456 insertions(+), 14 deletions(-) diff --git a/config/acl.yaml b/config/acl.yaml index ea81ada5..513fd650 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -274,8 +274,12 @@ access_keys: label: View Behind Schedule - id: jo_advance_order.form label: New Advance Order + - id: jo_advance_order.edit + label: New Advance Order Edit - id: jo_assign_advance_order.form label: Assign Advance Order + - id: jo_assign_advance_order.edit + label: Assign Advance Order Edit - id: support label: Customer Support Access diff --git a/config/menu.yaml b/config/menu.yaml index c216839b..248fb3b8 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -110,7 +110,7 @@ main_menu: acl: jo_advance_order.form label: New Advance Order parent: joborder - - id: jo_advance_order_assign_form + - id: jo_assign_advance_order_form acl: jo_assign_advance_order.form label: Assign Advance Order parent: joborder diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index 45623b22..eb296cfc 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -281,7 +281,7 @@ jo_advance_order_edit_form: methods: [GET] jo_advance_order_edit_submit: - path: /job-order/onestep/{id}/edit + path: /job-order/advance-order/{id}/edit controller: App\Controller\JobOrderController::advanceOrderEditSubmit methods: [POST] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index d8ff3b06..3b4887a6 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -228,7 +228,7 @@ class JobOrderController extends Controller } /** - * @Menu(selected="jo_all") + * @Menu(selected="jo_/viewall") */ public function listAll(JobOrderHandlerInterface $jo_handler) { @@ -284,18 +284,18 @@ class JobOrderController extends Controller $rows[$key]['meta']['reassign_rider_url'] = $this->generateUrl('jo_open_rider_form', ['id' => $jo_id]); // $rows[$key]['meta']['edit_url'] = $this->generateUrl('jo_open_edit_form', ['id' => $jo_id]); $rows[$key]['meta']['edit_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]); - $rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); + //$rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); } else if ($tier == 'behind_schedule') { $rows[$key]['meta']['edit_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]); - $rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); + //$rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); } else { // $rows[$key]['meta']['update_url'] = $this->generateUrl($tier_params['edit_route'], ['id' => $jo_id]); - $rows[$key]['meta']['update_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]); - $rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); + $rows[$key]['meta']['edit_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]); + //$rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]); $rows[$key]['meta']['pdf_url'] = $this->generateUrl('jo_pdf_form', ['id' => $jo_id]); } @@ -1095,6 +1095,77 @@ class JobOrderController extends Controller return $this->render($template, $params); } + public function advanceOrderSubmit(Request $req, JobOrderHandlerInterface $jo_handler, MQTTClient $mclient) + { + $this->denyAccessUnlessGranted('jo_advance_order.form', null, 'No access.'); + + // initialize error list + $error_array = []; + $id = -1; + $error_array = $jo_handler->processAdvanceOrderJobOrder($req, $id, $mclient); + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + /** + * @Menu(selected="jo_advance_order_edit_form") + */ + public function advanceOrderEditForm($id, EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, + GISManagerInterface $gis, MapTools $map_tools) + { + $this->denyAccessUnlessGranted('jo_advance_order.edit', null, 'No access.'); + + $params = $jo_handler->initializeAdvanceOrderEditForm($id, $map_tools); + $params['submit_url'] = $this->generateUrl('jo_advance_order_edit_submit', ['id' => $id]); + $params['return_url'] = $this->generateUrl('jo_open'); + $params['map_js_file'] = $gis->getJSJOFile(); + $params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll(); + $params['vmakes'] = $em->getRepository(Vehicle::class)->findAll(); + + $template = $params['template']; + + // response + return $this->render($template, $params); + } + + public function advanceOrderEditSubmit(Request $req, JobOrderHandlerInterface $jo_handler, $id, MQTTClient $mclient) + { + $this->denyAccessUnlessGranted('jo_advance_order.edit', null, 'No access.'); + + $error_array = []; + $error_array = $jo_handler->processAdvanceOrderJobOrder($req, $id, $mclient); + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + + /** * @Menu(selected="jo_hub_view") */ diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 998bc41b..3bc46ef2 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -2907,6 +2907,358 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface return $params; } + public function processAdvanceOrderJobOrder(Request $req, $id, MQTTClient $mclient) + { + // initialize error list + $error_array = []; + + $em = $this->em; + + $jo = $em->getRepository(JobOrder::class)->find($id); + $event_type = CMBJOEventType::OPEN_EDIT; + if (empty($jo)) + { + // new job order + $jo = new JobOrder(); + $event_type = CMBJOEventType::CREATE; + } + + // 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 responsible party is present + if (empty($req->request->get('responsible_party'))) + $error_array['responsible_party'] = 'Responsible party is required.'; + + // check if new customer + if ($req->request->get('new_customer', false)) + { + // validate mobile phone + $valid_mobile = $this->cust_handler->validateMobileNumber($req->request->get('phone_mobile')); + if (!($valid_mobile)) + $error_array['phone_mobile'] = 'Invalid mobile phone number.'; + + // check if plate number is in request + if (empty(trim($req->request->get('plate_number')))) + $error_array['plate_number'] = 'Plate number is required.'; + + // 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.'; + } + + if (empty($error_array)) + { + $new_cust = new Customer(); + $new_cv = new CustomerVehicle(); + + $new_cust->setLastName($req->request->get('last_name')) + ->setFirstName($req->request->get('first_name')) + ->setPhoneMobile($req->request->get('phone_mobile')) + ->setPhoneLandline($req->request->get('phone_landline')) + ->setPhoneOffice($req->request->get('phone_office')) + ->setCustomerNotes($req->request->get('customer_notes')); + + $new_cv->setCustomer($new_cust) + ->setVehicle($new_vehicle) + ->setPlateNumber(trim($req->request->get('plate_number'))) + ->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 is selected + if (empty($req->request->get('hub_id'))) + $error_array['hub'] = 'No hub selected.'; + else + { + // get hub + $hub = $em->getRepository(Hub::class)->find($req->request->get('hub_id')); + + if (empty($hub)) + $error_array['hub'] = 'Invalid hub specified.'; + } + + // delivery address + if (empty($req->request->get('delivery_address'))) + $error_array['delivery_address'] = 'Delivery address is required.'; + + // get discount and set to meta + $discount = $req->request->get('invoice_discount'); + + if (($discount > 60) || ($discount < 0)) + { + $error_array['invoice_discount'] = 'Invalid discount specified'; + } + + // get list of service charges + $service_charges = $req->request->get('service_charges', []); + + 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')) + ->setDeliveryInstructions($req->request->get('delivery_instructions')) + ->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) + ->setResponsibleParty($req->request->get('responsible_party', '')) + ->setStatus(JOStatus::RIDER_ASSIGN); + + $jo->addMeta('discount', $discount); + $jo->addMeta('service_charges', $service_charges); + + // 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 invoice + $invoice_items = $req->request->get('invoice_items', []); + $discount = $req->request->get('invoice_discount'); + $invoice_change = $req->request->get('invoice_change', 0); + + // check if invoice changed + if ($invoice_change) + { + $this->ic->generateInvoiceCriteria($jo, $discount, $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($event_type) + ->setJobOrder($jo); + + if ($user != null) + { + $event->setUser($user); + } + + $em->persist($event); + $em->flush(); + } + } + + return $error_array; + } + + public function initializeAdvanceOrderEditForm($id, $map_tools) + { + $em = $this->em; + $obj = $em->getRepository(JobOrder::class)->find($id); + + $params['obj'] = $obj; + $params['mode'] = 'advanceorder-edit'; + $params['cvid'] = $obj->getCustomerVehicle()->getID(); + $params['vid'] = $obj->getCustomerVehicle()->getVehicle()->getID(); + $params['current_date'] = new DateTime(); + + // get service charges + $sc_array = []; + $jo_service_charges = $obj->getMeta('service_charges'); + if (!(empty($jo_service_charges))) + { + foreach ($jo_service_charges as $jo_sc_id) + { + // find service charge + $sc_obj = $em->getRepository(ServiceCharge::class)->find($jo_sc_id); + + $sc_array[] = $sc_obj; + } + } + + $params['jo_service_charges'] = $sc_array; + + // get odometer + $odometer = $obj->getMeta('odometer'); + + $params['odometer'] = $odometer; + + // get customer email used in JO + $email = $obj->getMeta('customer_email'); + + $params['email'] = $email; + + // get images if any + $jo_extra = $obj->getJOExtra(); + $pic_array = []; + $params['signature'] = null; + if ($jo_extra != null) + { + $img_1 = $jo_extra->getImage1Filename(); + $img_2 = $jo_extra->getImage2Filename(); + $img_3 = $jo_extra->getImage3Filename(); + $img_4 = $jo_extra->getImage4Filename(); + + $other_images = $jo_extra->getOtherImages(); + + $cust_signature = $jo_extra->getCustomerSignature(); + + if ($img_1 != null) + $pic_array['image_1'] = $img_1; + if ($img_2 != null) + $pic_array['image_2'] = $img_2; + if ($img_3 != null) + $pic_array['image_3'] = $img_3; + if ($img_4 != null) + $pic_array['image_4'] = $img_4; + + if ($other_images != null) + { + foreach ($other_images as $img) + { + $pic_array['other_images'][] = $img; + } + } + + $params['signature'] = $cust_signature; + } + + $params['jo_pictures'] = $pic_array; + + $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_advanceorder_edit_form'); + + return $params; + } + protected function fillDropdownParameters(&$params) { $em = $this->em; @@ -3006,6 +3358,11 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $params['ftags']['ticket_table'] = false; $params['ftags']['cancel_button'] = false; break; + case 'advanceorder-edit': + $params['ftags']['invoice_edit'] = true; + $params['ftags']['preset_vehicle'] = true; + break; + } } @@ -3031,6 +3388,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->template_hash['jo_popup'] = 'job-order/cmb.popup.html.twig'; $this->template_hash['jo_behind_schedule'] = 'job-order/cmb.list.behindschedule.html.twig'; $this->template_hash['jo_advanceorder_form'] = 'job-order/cmb.form.advanceorder.html.twig'; + $this->template_hash['jo_advanceorder_edit_form'] = 'job-order/cmb.form.advanceorder.html.twig'; } protected function checkTier($tier) @@ -3286,11 +3644,20 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface if (empty($jo)) throw new NotFoundHttpException('The item does not exist'); + $edit_route = ''; // check transaction origin if ($jo->getSource() == CMBTransactionOrigin::WALK_IN) - return 'jo_walkin_edit_form'; + $edit_route = 'jo_walkin_edit_form'; else - return 'jo_onestep_edit_form'; + { + // need to check if onestep or not + if ($jo->getStatus() == JOStatus::ASSIGNED) + $edit_route = 'jo_onestep_edit_form'; + else + $edit_route = 'jo_advance_order_edit_form'; + } + + return $edit_route; } protected function generateDiscountOptions() diff --git a/templates/job-order/cmb.list.all.html.twig b/templates/job-order/cmb.list.all.html.twig index 17c7be16..49d04ae2 100644 --- a/templates/job-order/cmb.list.all.html.twig +++ b/templates/job-order/cmb.list.all.html.twig @@ -115,7 +115,7 @@ sortable: false, overflow: 'visible', template: function (row, index, datatable) { - var actions = ''; + var actions = ''; actions += ''; return actions; diff --git a/templates/job-order/cmb.list.behindschedule.html.twig b/templates/job-order/cmb.list.behindschedule.html.twig index 2ed1bbeb..5f9a9c57 100644 --- a/templates/job-order/cmb.list.behindschedule.html.twig +++ b/templates/job-order/cmb.list.behindschedule.html.twig @@ -103,8 +103,8 @@ sortable: false, overflow: 'visible', template: function (row, index, datatable) { - {% if is_granted('jo_onestep.edit') %} - var actions = ''; + {% if is_granted('jo_onestep.edit') or is_granted('jo_advance_order.edit') or is_granted('jo_assign_advance_order.edit') %} + var actions = ''; {% endif %} return actions; diff --git a/templates/job-order/cmb.list.open.html.twig b/templates/job-order/cmb.list.open.html.twig index aac00d65..21669275 100644 --- a/templates/job-order/cmb.list.open.html.twig +++ b/templates/job-order/cmb.list.open.html.twig @@ -114,8 +114,8 @@ sortable: false, overflow: 'visible', template: function (row, index, datatable) { - {% if is_granted('jo_onestep.edit') %} - var actions = ''; + {% if is_granted('jo_onestep.edit') or is_granted('jo_advance_order.edit') or is_granted('jo_assign_advance_order.edit') %} + var actions = ''; {% endif %} return actions; -- 2.43.5 From c4bf772f7084eb7d603900b9f1920cc8503ef6b0 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 29 Sep 2020 10:57:07 +0000 Subject: [PATCH 3/5] Add assign advance order to acl, menu, and route. #509 --- config/acl.yaml | 4 +- config/menu.yaml | 4 +- config/routes/job_order.yaml | 16 +- src/Controller/JobOrderController.php | 44 + .../JobOrderHandler/CMBJobOrderHandler.php | 12 + .../job-order/cmb.form.advanceorder.html.twig | 4 +- .../cmb.form.assignadvanceorder.html.twig | 1702 +++++++++++++++++ .../cmb.list.assignadvanceorder.html.twig | 210 ++ 8 files changed, 1987 insertions(+), 9 deletions(-) create mode 100644 templates/job-order/cmb.form.assignadvanceorder.html.twig create mode 100644 templates/job-order/cmb.list.assignadvanceorder.html.twig diff --git a/config/acl.yaml b/config/acl.yaml index 513fd650..23b0d863 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -276,10 +276,8 @@ access_keys: label: New Advance Order - id: jo_advance_order.edit label: New Advance Order Edit - - id: jo_assign_advance_order.form + - id: jo_assign_advance_order.list label: Assign Advance Order - - id: jo_assign_advance_order.edit - label: Assign Advance Order Edit - id: support label: Customer Support Access diff --git a/config/menu.yaml b/config/menu.yaml index 248fb3b8..3b9b92b1 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -110,8 +110,8 @@ main_menu: acl: jo_advance_order.form label: New Advance Order parent: joborder - - id: jo_assign_advance_order_form - acl: jo_assign_advance_order.form + - id: jo_assign_advance_order + acl: jo_assign_advance_order.list label: Assign Advance Order parent: joborder - id: jo_walkin_form diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index eb296cfc..46dd7434 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -285,13 +285,25 @@ jo_advance_order_edit_submit: controller: App\Controller\JobOrderController::advanceOrderEditSubmit methods: [POST] -jo_assign_advance_order_form: +jo_assign_advance_order: path: /job-order/assign-advance-order + controller: App\Controller\JobOrderController::listAssignAdvanceOrder + methods: [GET] + +jo_assign_advance_order_rows: + path: /job-order/assign-advance-joborder-rows + controller: App\Controller\JobOrderController::getRows + methods: [POST] + defaults: + tier: "assign_advance_order" + +jo_assign_advance_order_form: + path: /job-order/assign-advance-order/{id} controller: App\Controller\JobOrderController::assignAdvanceOrderForm methods: [GET] jo_assign_advance_order_submit: - path: /job-order/assign-advance-order + path: /job-order/assign-advance-order/{id} controller: App\Controller\JobOrderController::assignAdvanceOrderSubmit methods: [POST] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 3b4887a6..c50474bb 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1164,7 +1164,51 @@ class JobOrderController extends Controller ]); } + /** + * @Menu(selected="jo_assign_advance_order_form") + */ + public function assignAdvanceOrderForm(EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, + GISManagerInterface $gis) + { + $this->denyAccessUnlessGranted('jo_assign_advance_order.form', null, 'No access.'); + $params = $jo_handler->initializeAssignAdvanceOrderForm(); + $params['submit_url'] = $this->generateUrl('jo_assign_advance_order_submit'); + $params['return_url'] = $this->generateUrl('jo_assign_advance_order_form'); + $params['map_js_file'] = $gis->getJSJOFile(); + $params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll(); + $params['vmakes'] = $em->getRepository(Vehicle::class)->findAll(); + $params['hubs'] = $em->getRepository(Hub::class)->findAll(); + + $template = $params['template']; + + // response + return $this->render($template, $params); + } + + public function assignAdvanceOrderSubmit(Request $req, JobOrderHandlerInterface $jo_handler, MQTTClient $mclient) + { + $this->denyAccessUnlessGranted('jo_assign_advance_order.form', null, 'No access.'); + + // initialize error list + $error_array = []; + $id = -1; + $error_array = $jo_handler->processAssignAdvanceOrderJobOrder($req, $id, $mclient); + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } /** * @Menu(selected="jo_hub_view") diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 3bc46ef2..bcf146ff 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -3259,6 +3259,10 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface return $params; } + public function initializeAssignAdvanceOrderForm() + { + } + protected function fillDropdownParameters(&$params) { $em = $this->em; @@ -3454,6 +3458,14 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $unlock_route = ''; $jo_status = JOStatus::ASSIGNED; break; + case 'assign_advance_order': + $tier_key = 'jo_assign_advance_order'; + $tier_name = 'Assign Advance Order'; + $rows_route = 'jo_assign_advance_order_rows'; + $edit_route = ''; + $unlock_route = ''; + $jo_status = JOStatus::RIDER_ASSIGN; + break; default: throw new AccessDeniedHttpException('No access.'); } diff --git a/templates/job-order/cmb.form.advanceorder.html.twig b/templates/job-order/cmb.form.advanceorder.html.twig index 6e11db8d..2e44cea8 100644 --- a/templates/job-order/cmb.form.advanceorder.html.twig +++ b/templates/job-order/cmb.form.advanceorder.html.twig @@ -402,7 +402,7 @@

- {% if mode in ['view-all', 'update-fulfillment'] %} + {% if mode in ['view-all'] %} Assigned Hub {% else %} Nearest Hubs @@ -718,7 +718,7 @@
{% if mode != 'view-all' %} - + {% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %} Cancel Job Order {% endif %} diff --git a/templates/job-order/cmb.form.assignadvanceorder.html.twig b/templates/job-order/cmb.form.assignadvanceorder.html.twig new file mode 100644 index 00000000..9462f31e --- /dev/null +++ b/templates/job-order/cmb.form.assignadvanceorder.html.twig @@ -0,0 +1,1702 @@ +{% extends 'base.html.twig' %} + +{% block body %} + + + +
+ +
+
+
+
+
+
+ + + + {% if mode == "assignadvanceorder" %} +

+ Assign Advance Order Job Order +

+ {% else %} +

+ Assign Advance Order Job Order #{{ obj.getID }} - {{ obj.getStatusText }} +

+ {% endif %} +
+
+
+
+ + +
+ {%if ftags.vehicle_dropdown %} +
+
+
+ + + +
+ +
+
+
+
+
+ + + +
+
+
+ {% else %} + + {% endif %} + {% if obj.getReferenceJO %} +
+
+
+ + + +
+
+
+ {% endif %} + +
+
+

+ Customer Details +

+ + + +
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+
+
+ + + +
+
+
+
+
+

+ Vehicle Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+ +
+
+
+
+

+ Battery Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+
+

+ Transaction Details +

+ + + +
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ +
+ + + + +
+ +
+
+ +
+ + + + +
+ +
+
+
+
+
+ + + +
+
+
+ + +
+
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+
+

+ Location +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + + + +
+ + + + +
+
+
+
+
+ +
+
+

+ {% if mode in ['view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + Assigned Hub + {% else %} + Nearest Hubs + {% endif %} +

+
+
+
+ {% if mode != 'view-all' %} + + {% endif %} + + +
+ + + + + + + + + + + + +
HubBranchContact NumbersDistance in KM
+
+
+
+
+
+
+

+ {% if mode in ['view-all', 'assign-advance-order-edit'] %} + Assigned Rider + {% else %} + Rider Assignment + {% endif %} +

+
+
+
+ {% if mode != 'view-all' %} + + {% endif %} + + +
+ + + + + + + + + + + {% if mode in ['onestep-edit', 'view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + {% set avail_riders = obj.getHub.getAvailableRiders|default([]) %} + + + + + {% if obj.getHub %} + {% for rider in avail_riders %} + {% if mode in ['view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + + {% else %} + + {% endif %} + + + + + {% endfor %} + {% endif %} + {% endif %} + +
First NameLast NameContact No.Plate Number
+ No riders available. +
{{ rider.getFirstName }}{{ rider.getLastName }}{{ rider.getContactNumber }}{{ rider.getPlateNumber }}
+
+
+
+
+ + {% if mode in ['assign-advance-order-edit'] %} +
+
+
+

+ Other Information +

+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ +
+ {% for key, picture in jo_pictures %} + {% if key == 'image_1' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_2' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_3' %} +
+ + + +
+ +
+ {% endif %} + {% if key == 'image_4' %} +
+ + + +
+ +
+ {% endif %} + + {% endfor %} +
+ +
+ + + {% endif %} + +
+
+
+

+ Service Charges +

+
+
+ {% if mode != 'view-all' %} +
+ +
+ {% endif %} +
+ + {% for jo_sc in jo_service_charges %} +
+
+
+ +
+
+
+ +
+
+ +
+
+ {% endfor %} +
+ +
+
+
+

+ Invoice +

+
+
+
+ + + +
+ +
+
+
+ + {% if ftags.invoice_edit %} + + + {% else %} + + + {% endif %} +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + + + + + + + + + + {% if not obj.getInvoice or (obj.getInvoice and obj.getInvoice.getItems|length == 0) %} + + + + {% else %} + {% for item in obj.getInvoice.getItems %} + + + + + + + {% endfor %} + {% endif %} + +
ItemQuantityUnit PriceAmount
+ No items to display. +
{{ item.getTitle }}{{ item.getQuantity|number_format }}{{ item.getPrice|number_format(2) }}{{ (item.getPrice * item.getQuantity)|number_format(2) }}
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + +
+
+
+
+
+
+
+
+ {% if mode != 'view-all' %} + + {% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %} + Cancel Job Order + {% endif %} + {% endif %} + Back +
+
+
+
+ +
+
+
+
+{% endblock %} + +{% block scripts %} +{{ include('map/' ~ map_js_file) }} + + + + +{% endblock %} + diff --git a/templates/job-order/cmb.list.assignadvanceorder.html.twig b/templates/job-order/cmb.list.assignadvanceorder.html.twig new file mode 100644 index 00000000..752c1d22 --- /dev/null +++ b/templates/job-order/cmb.list.assignadvanceorder.html.twig @@ -0,0 +1,210 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

+ Advanced Order Job Orders +

+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} -- 2.43.5 From 931a212005e39737b529e0c5bfc918188a6e1bf0 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 30 Sep 2020 08:13:23 +0000 Subject: [PATCH 4/5] Add assign advance order screens. #509 --- config/acl.yaml | 2 + config/cmb.menu.yaml | 6 +- config/routes/job_order.yaml | 9 - src/Controller/JobOrderController.php | 28 +- .../JobOrderHandler/CMBJobOrderHandler.php | 442 +++++++- .../cmb.form.assignadvanceorder.html.twig | 1006 +++++++++++------ .../cmb.list.assignadvanceorder.html.twig | 2 +- 7 files changed, 1098 insertions(+), 397 deletions(-) diff --git a/config/acl.yaml b/config/acl.yaml index 23b0d863..8eeae664 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -278,6 +278,8 @@ access_keys: label: New Advance Order Edit - id: jo_assign_advance_order.list label: Assign Advance Order + - id: jo_assign_advance_order.form + label: Edit Assign Advance Order - id: support label: Customer Support Access diff --git a/config/cmb.menu.yaml b/config/cmb.menu.yaml index c61617eb..3b9b92b1 100644 --- a/config/cmb.menu.yaml +++ b/config/cmb.menu.yaml @@ -106,12 +106,12 @@ main_menu: acl: jo_onestep.form label: One-step Process parent: joborder - - id: jo_advance_order + - id: jo_advance_order_form acl: jo_advance_order.form label: New Advance Order parent: joborder - - id: jo_advance_order_assign - acl: jo_assign_advance_order.form + - id: jo_assign_advance_order + acl: jo_assign_advance_order.list label: Assign Advance Order parent: joborder - id: jo_walkin_form diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index 46dd7434..57f58fdf 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -307,12 +307,3 @@ jo_assign_advance_order_submit: controller: App\Controller\JobOrderController::assignAdvanceOrderSubmit methods: [POST] -jo_assign_advance_order_edit_form: - path: /job-order/assign-advance-order/{id}/edit - controller: App\Controller\JobOrderController::assignAdvanceOrderEditForm - methods: [GET] - -jo_assign_advance_order_edit_submit: - path: /job-order/assign-advance-order/{id}/edit - controller: App\Controller\JobOrderController::assignAdvanceOrderEditSubmit - methods: [POST] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index c50474bb..592c175e 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1164,17 +1164,32 @@ class JobOrderController extends Controller ]); } + /** + * @Menu(selected="jo_assign_advance_order") + */ + public function listAssignAdvanceOrder(JobOrderHandlerInterface $jo_handler) + { + $this->denyAccessUnlessGranted('jo_assign_advance_order.list', null, 'No access.'); + + $template = $jo_handler->getTwigTemplate('jo_list_assign_advanceorder'); + + $params = $jo_handler->getOtherParameters(); + $params['table_refresh_rate'] = $this->container->getParameter('job_order_refresh_interval'); + + return $this->render($template, $params); + } + /** * @Menu(selected="jo_assign_advance_order_form") */ - public function assignAdvanceOrderForm(EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, - GISManagerInterface $gis) + public function assignAdvanceOrderForm($id, EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, + GISManagerInterface $gis, MapTools $map_tools) { $this->denyAccessUnlessGranted('jo_assign_advance_order.form', null, 'No access.'); - $params = $jo_handler->initializeAssignAdvanceOrderForm(); - $params['submit_url'] = $this->generateUrl('jo_assign_advance_order_submit'); - $params['return_url'] = $this->generateUrl('jo_assign_advance_order_form'); + $params = $jo_handler->initializeAssignAdvanceOrderForm($id, $map_tools); + $params['submit_url'] = $this->generateUrl('jo_assign_advance_order_submit', ['id' => $id]); + $params['return_url'] = $this->generateUrl('jo_assign_advance_order'); $params['map_js_file'] = $gis->getJSJOFile(); $params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll(); $params['vmakes'] = $em->getRepository(Vehicle::class)->findAll(); @@ -1186,13 +1201,12 @@ class JobOrderController extends Controller return $this->render($template, $params); } - public function assignAdvanceOrderSubmit(Request $req, JobOrderHandlerInterface $jo_handler, MQTTClient $mclient) + public function assignAdvanceOrderSubmit(Request $req, JobOrderHandlerInterface $jo_handler, $id, MQTTClient $mclient) { $this->denyAccessUnlessGranted('jo_assign_advance_order.form', null, 'No access.'); // initialize error list $error_array = []; - $id = -1; $error_array = $jo_handler->processAssignAdvanceOrderJobOrder($req, $id, $mclient); // check if any errors were found diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index bcf146ff..05d9ce45 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -449,10 +449,12 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $jo = $em->getRepository(JobOrder::class)->find($id); $old_jo_status = null; $old_rider = null; + $event_type = CMBJOEventType::OPEN_EDIT; if (empty($jo)) { // new job order $jo = new JobOrder(); + $event_type = CMBJOEventType::CREATE; } else { @@ -715,7 +717,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface // the event $event = new JOEvent(); $event->setDateHappen(new DateTime()) - ->setTypeID(CMBJOEventType::CREATE) + ->setTypeID($event_type) ->setJobOrder($jo); if ($user != null) @@ -3259,8 +3261,434 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface return $params; } - public function initializeAssignAdvanceOrderForm() + public function initializeAssignAdvanceOrderForm($id, $map_tools) { + $em = $this->em; + $obj = $em->getRepository(JobOrder::class)->find($id); + + $params['obj'] = $obj; + $params['mode'] = 'assign-advanceorder'; + $params['cvid'] = $obj->getCustomerVehicle()->getID(); + $params['vid'] = $obj->getCustomerVehicle()->getVehicle()->getID(); + $params['current_date'] = new DateTime(); + + // get service charges + $sc_array = []; + $jo_service_charges = $obj->getMeta('service_charges'); + if (!(empty($jo_service_charges))) + { + foreach ($jo_service_charges as $jo_sc_id) + { + // find service charge + $sc_obj = $em->getRepository(ServiceCharge::class)->find($jo_sc_id); + + $sc_array[] = $sc_obj; + } + } + + $params['jo_service_charges'] = $sc_array; + + // get odometer + $odometer = $obj->getMeta('odometer'); + + $params['odometer'] = $odometer; + + // get customer email used in JO + $email = $obj->getMeta('customer_email'); + + $params['email'] = $email; + + // get images if any + $jo_extra = $obj->getJOExtra(); + $pic_array = []; + $params['signature'] = null; + if ($jo_extra != null) + { + $img_1 = $jo_extra->getImage1Filename(); + $img_2 = $jo_extra->getImage2Filename(); + $img_3 = $jo_extra->getImage3Filename(); + $img_4 = $jo_extra->getImage4Filename(); + + $other_images = $jo_extra->getOtherImages(); + + $cust_signature = $jo_extra->getCustomerSignature(); + + if ($img_1 != null) + $pic_array['image_1'] = $img_1; + if ($img_2 != null) + $pic_array['image_2'] = $img_2; + if ($img_3 != null) + $pic_array['image_3'] = $img_3; + if ($img_4 != null) + $pic_array['image_4'] = $img_4; + + if ($other_images != null) + { + foreach ($other_images as $img) + { + $pic_array['other_images'][] = $img; + } + } + + $params['signature'] = $cust_signature; + } + + $params['jo_pictures'] = $pic_array; + + $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_assign_advanceorder_form'); + + return $params; + } + + public function processAssignAdvanceOrderJobOrder(Request $req, $id, MQTTClient $mclient) + { + // initialize error list + $error_array = []; + + $em = $this->em; + + $jo = $em->getRepository(JobOrder::class)->find($id); + $old_jo_status = null; + $old_rider = null; + $event_type = CMBJOEventType::OPEN_EDIT; + if (empty($jo)) + { + // new job order + $jo = new JobOrder(); + $event_type = CMBJOEventType::CREATE; + } + else + { + // need to get old values of rider and status to see if we need to change JO status or not + $old_rider = $jo->getRider(); + $old_jo_status = $jo->getStatus(); + } + + // 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 responsible party is present + if (empty($req->request->get('responsible_party'))) + $error_array['responsible_party'] = 'Responsible party is required.'; + + // check if new customer + if ($req->request->get('new_customer', false)) + { + // validate mobile phone + $valid_mobile = $this->cust_handler->validateMobileNumber($req->request->get('phone_mobile')); + if (!($valid_mobile)) + $error_array['phone_mobile'] = 'Invalid mobile phone number.'; + + // check if plate number is in request + if (empty(trim($req->request->get('plate_number')))) + $error_array['plate_number'] = 'Plate number is required.'; + + // 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.'; + } + + if (empty($error_array)) + { + $new_cust = new Customer(); + $new_cv = new CustomerVehicle(); + + $new_cust->setLastName($req->request->get('last_name')) + ->setFirstName($req->request->get('first_name')) + ->setPhoneMobile($req->request->get('phone_mobile')) + ->setPhoneLandline($req->request->get('phone_landline')) + ->setPhoneOffice($req->request->get('phone_office')) + ->setCustomerNotes($req->request->get('customer_notes')); + + $new_cv->setCustomer($new_cust) + ->setVehicle($new_vehicle) + ->setPlateNumber(trim($req->request->get('plate_number'))) + ->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 + $rider_plate_number = ''; + 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.'; + } else { + // check if rider is still available + if (!($rider->isAvailable())) + $error_array['rider'] = 'Selected rider is unavailable.'; + + $rider_plate_number = $rider->getPlateNumber(); + } + } + } + } + + // delivery address + if (empty($req->request->get('delivery_address'))) + $error_array['delivery_address'] = 'Delivery address is required.'; + + // get discount and set to meta + $discount = $req->request->get('invoice_discount'); + + if (($discount > 60) || ($discount < 0)) + { + $error_array['invoice_discount'] = 'Invalid discount specified'; + } + + // get list of service charges + $service_charges = $req->request->get('service_charges', []); + + if (empty($error_array)) + { + // set priority based on rider's existing open job orders + $rider_jos = $rider->getOpenJobOrders(); + + // get maximum priority then add 1 + // NOTE: this can be a bit buggy due to concurrency issues + // ideally have to lock jo table, but that isn't feasible right now + $priority = 0; + foreach ($rider_jos as $rider_jo) + { + if ($priority < $rider_jo->getPriority()) + $priority = $rider_jo->getPriority() + 1; + } + + // 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')) + ->setDeliveryInstructions($req->request->get('delivery_instructions')) + ->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) + ->setPriority($priority) + ->setResponsibleParty($req->request->get('responsible_party', '')) + ->setRiderPlateNum($rider_plate_number); + + $jo->addMeta('discount', $discount); + $jo->addMeta('service_charges', $service_charges); + + // retain old jo status if it's an update JO + // check old rider if it is also a reassignment + // old_rider should be null if JO has been rejected + if (($old_rider == null) && ($old_jo_status == null)) + $jo->setStatus(JOStatus::ASSIGNED); + else + { + $new_rider = $jo->getRider(); + if ($new_rider != $old_rider) + { + // reassignment + $jo->setStatus(JOStatus::ASSIGNED); + $event_type = CMBJOEventType::RIDER_ASSIGN; + } + else + { + if ($old_jo_status != null) + $jo->setStatus($old_jo_status); + } + } + + // 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', []); + $discount = $req->request->get('invoice_discount'); + $invoice_change = $req->request->get('invoice_change', 0); + + // check if invoice changed + if ($invoice_change) + { + $this->ic->generateInvoiceCriteria($jo, $discount, $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($event_type) + ->setJobOrder($jo); + + if ($user != null) + { + $event->setUser($user); + } + + $em->persist($event); + $em->flush(); + + // check if JO has been reassigned + if ($old_rider != $jo->getRider()) + //if ($old_jo_status != $jo->getStatus()) + { + error_log('JO has been reassigned'); + // TODO: refactor later + $channel = 'rider/' . $rider->getID() . '/events'; + $payload = [ + 'event' => 'new_jo', + 'jo_id' => $jo->getID(), + ]; + + $mclient->publish($channel, json_encode($payload)); + } + } + } + + return $error_array; } protected function fillDropdownParameters(&$params) @@ -3366,6 +3794,10 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $params['ftags']['invoice_edit'] = true; $params['ftags']['preset_vehicle'] = true; break; + case 'assign-advanceorder': + $params['ftags']['invoice_edit'] = true; + $params['ftags']['preset_vehicle'] = true; + break; } } @@ -3393,6 +3825,8 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->template_hash['jo_behind_schedule'] = 'job-order/cmb.list.behindschedule.html.twig'; $this->template_hash['jo_advanceorder_form'] = 'job-order/cmb.form.advanceorder.html.twig'; $this->template_hash['jo_advanceorder_edit_form'] = 'job-order/cmb.form.advanceorder.html.twig'; + $this->template_hash['jo_list_assign_advanceorder'] = 'job-order/cmb.list.assignadvanceorder.html.twig'; + $this->template_hash['jo_assign_advanceorder_form'] = 'job-order/cmb.form.assignadvanceorder.html.twig'; } protected function checkTier($tier) @@ -3662,9 +4096,11 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $edit_route = 'jo_walkin_edit_form'; else { - // need to check if onestep or not + // need to check if onestep or assign advance order if ($jo->getStatus() == JOStatus::ASSIGNED) $edit_route = 'jo_onestep_edit_form'; + else if ($jo->getStatus() == JOStatus::RIDER_ASSIGN) + $edit_route = 'jo_assign_advance_order_form'; else $edit_route = 'jo_advance_order_edit_form'; } diff --git a/templates/job-order/cmb.form.assignadvanceorder.html.twig b/templates/job-order/cmb.form.assignadvanceorder.html.twig index 9462f31e..52d323b3 100644 --- a/templates/job-order/cmb.form.assignadvanceorder.html.twig +++ b/templates/job-order/cmb.form.assignadvanceorder.html.twig @@ -23,15 +23,9 @@ - {% if mode == "assignadvanceorder" %} -

- Assign Advance Order Job Order -

- {% else %} -

- Assign Advance Order Job Order #{{ obj.getID }} - {{ obj.getStatusText }} -

- {% endif %} +

+ Assign Advance Job Order #{{ obj.getID }} - {{ obj.getStatusText }} +

@@ -155,22 +149,23 @@
- + + {% for manufacturer in vmfgs %} {% set vmfg_id = obj.getCustomerVehicle ? obj.getCustomerVehicle.getVehicle.getManufacturer.getID : 0 %} - - {% endfor %} - + + {% endfor %} +
- {% for make in vmakes %} {% set vmake_id = obj.getCustomerVehicle ? obj.getCustomerVehicle.getVehicle.getID : 0 %} - + + {% endfor %} @@ -239,7 +234,7 @@

@@ -401,7 +396,7 @@

- {% if mode in ['view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + {% if mode in ['view-all', 'assign-advanceorder'] %} Assigned Hub {% else %} Nearest Hubs @@ -410,11 +405,6 @@

- {% if mode != 'view-all' %} - - {% endif %}
@@ -428,15 +418,6 @@ -
@@ -446,7 +427,7 @@

- {% if mode in ['view-all', 'assign-advance-order-edit'] %} + {% if mode in ['view-all', 'update-fulfillment'] %} Assigned Rider {% else %} Rider Assignment @@ -473,7 +454,7 @@ - {% if mode in ['onestep-edit', 'view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + {% if mode in ['onestep-edit', 'view-all'] %} {% set avail_riders = obj.getHub.getAvailableRiders|default([]) %} @@ -483,7 +464,7 @@ {% if obj.getHub %} {% for rider in avail_riders %} - {% if mode in ['view-all', 'assign-advance-order', 'assign-advance-order-edit'] %} + {% if mode in ['view-all', 'update-fulfillment'] %} {% else %} @@ -502,7 +483,7 @@

- {% if mode in ['assign-advance-order-edit'] %} + {% if mode in ['onestep-edit'] %}
@@ -775,7 +756,7 @@
{% if mode != 'view-all' %} - + {% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %} Cancel Job Order {% endif %} @@ -870,7 +851,96 @@ $(function() { var marker = L.marker([lat, lng], { icon: icon_customer }); - {% if mode in ['view-all', 'assign-advance-joborder', 'assign-advance-job-order-edit'] %} + {% if mode in ['onestep'] %} + // get nearest hubs ajax + var hub_table = ''; + var rider_table = ''; + $.getJSON("{{ url('hub_nearest') }}?lat=" + lat + "&long=" + lng, function(data) { + var hubs = data['hubs']; + for (i in hubs) { + var hub = hubs[i]; + var hub_marker = L.marker([hub['lat'], hub['long']], { icon: icon_hub }); + hubLayerGroup.addLayer(hub_marker); + + hub_table += ''; + hub_table += '' + hub['name'] + ''; + hub_table += '' + hub['branch'] + ''; + hub_table += '' + hub['cnum'] + ''; + hub_table += '' + hub['distance'] + ''; + hub_table += ''; + } + + $('#nearest_hubs').html(hub_table); + + }); + + // clear rider table + rider_table += ''; + rider_table += '' + ''; + rider_table += '' + ''; + rider_table += '' + ''; + rider_table += '' + ''; + rider_table += ''; + + $('#riders').html(rider_table); + + {% endif %} + + {% if mode in ['assign-advanceorder'] %} + // get nearest hubs ajax + var hub_table = ''; + var rider_table = ''; + $.getJSON("{{ url('hub_nearest') }}?lat=" + lat + "&long=" + lng, function(data) { + var hubs = data['hubs']; + for (i in hubs) { + var hub = hubs[i]; + var hub_marker = L.marker([hub['lat'], hub['long']], { icon: icon_hub }); + hubLayerGroup.addLayer(hub_marker); + + if (selected_hub == hub['id']) { + hub_table += ''; + } + else { + hub_table += ''; + } + hub_table += '' + hub['name'] + ''; + hub_table += '' + hub['branch'] + ''; + hub_table += '' + hub['cnum'] + ''; + hub_table += '' + hub['distance'] + ''; + hub_table += ''; + + } + + $('#nearest_hubs').html(hub_table); + + }); + + // get riders of hub + // get hub riders ajax + // TODO: add latitude and longitude of delivery location to ajax request + var rider_table = ''; + $.getJSON("{{ url('hub_riders') }}?id=" + selected_hub, function(data) { + var riders = data['riders']; + for (i in riders) { + var rider = riders[i]; + var rider_lat = rider['location'][0]; + var rider_lng = rider['location'][1]; + var rider_marker = L.marker([rider_lat, rider_lng], { icon: icon_rider_available }); + riderLayerGroup.addLayer(rider_marker); + + rider_table += ''; + rider_table += '' + rider['first_name'] + ''; + rider_table += '' + rider['last_name'] + ''; + rider_table += '' + rider['contact_num'] + ''; + rider_table += '' + rider['plate_num'] + ''; + rider_table += ''; + } + $('#riders').html(rider_table); + }); + + {% endif %} + + {% if mode in ['view-all', 'update-fulfillment'] %} var hub_table = ''; $.getJSON("{{ url('hub_nearest') }}?lat=" + lat + "&long=" + lng, function(data) { var hubs = data['hubs']; @@ -1036,7 +1106,7 @@ $(function() { {% endif %} }); - {% if mode in ['view-all', 'assign-advance-job-order', 'assign-advance-job-order-edit'] %} + {% if mode in ['onestep-edit', 'view-all', 'assign-advanceorder'] %} var lat = {{ obj.getCoordinates.getLatitude }}; var lng = {{ obj.getCoordinates.getLongitude }}; @@ -1065,7 +1135,41 @@ $(function() { }); {% endif %} - $("#row-form").submit(function(e) { + {% if mode in ['update-processing', 'update-reassign-hub'] %} + // display hub map + // OSM code + + var hub_lat = {{ obj.getCoordinates.getLatitude }}; + var hub_lng = {{ obj.getCoordinates.getLongitude }}; + + var osm_hmap = mapCreate('hub_map', hub_lat, hub_lng, 'road', 13); + + var destLayerGroup = L.layerGroup().addTo(osm_hmap); + var hubLayerGroup = L.layerGroup().addTo(osm_hmap); + + var dest_icon = L.icon({ + iconUrl: '/assets/images/icon-destination.png', + shadowSize: [0,0] + }); + + var hub_icon = L.icon({ + iconUrl: '/assets/images/icon-outlet.png', + shadowSize: [0,0] + }); + + var dest_marker = new L.Marker([hub_lat, hub_lng], {icon: dest_icon}).bindPopup("Destination"); + + destLayerGroup.addLayer(dest_marker); + + {% for hub in hubs %} + var hub_marker = new L.Marker([{{ hub.hub.getCoordinates.getLatitude }}, + {{ hub.hub.getCoordinates.getLongitude }}], {icon: hub_icon}).bindPopup("{{ hub.hub.getName }}"); + + hubLayerGroup.addLayer(hub_marker); + {% endfor %} + {% endif %} + + $("#row-form").submit(function(e) { e.preventDefault(); if (form_in_process) { alert("Cannot submit form twice. First submission still in progress."); @@ -1074,183 +1178,193 @@ $(function() { form_in_process = true; - var form = $(this); + var form = $(this); - // get all fields, including disabled ones - var disabled = form.find(":input:disabled").prop('disabled', false); - var fields = form.serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]; - disabled.prop('disabled', true); + // get all fields, including disabled ones + var disabled = form.find(":input:disabled").prop('disabled', false); + var fields = form.serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]; + disabled.prop('disabled', true); - // add invoice items to data - fields['invoice_items'] = invoiceItems; + // add invoice items to data + fields['invoice_items'] = invoiceItems; - // add service charges to data - fields['service_charges'] = sc_array; + // add service charges to data + fields['service_charges'] = sc_array; - e.preventDefault(); + {% if mode in ['update-processing', 'update-reassign-hub'] %} + // add selected hub to data + fields['hub'] = selectedHub; + {% endif %} - $.ajax({ - method: "POST", - url: form.prop('action'), - data: fields - }).done(function(response) { - // remove all error classes - removeErrors(); - swal({ - title: 'Done!', - text: 'Your changes have been saved!', - type: 'success', - onClose: function() { - window.location.href = "{{ return_url }}"; - } - }); - }).fail(function(response) { - if (response.status == 422) { + {% if mode in ['update-assigning', 'update-reassign-rider'] %} + // add selected rider to data + fields['rider'] = selectedRider; + {% endif %} + + e.preventDefault(); + + $.ajax({ + method: "POST", + url: form.prop('action'), + data: fields + }).done(function(response) { + // remove all error classes + removeErrors(); + swal({ + title: 'Done!', + text: 'Your changes have been saved!', + type: 'success', + onClose: function() { + window.location.href = "{{ return_url }}"; + } + }); + }).fail(function(response) { + if (response.status == 422) { form_in_process = false; - var errors = response.responseJSON.errors; - var firstfield = false; + var errors = response.responseJSON.errors; + var firstfield = false; - // remove all error classes first - removeErrors(); + // remove all error classes first + removeErrors(); - // display errors contextually - $.each(errors, function(field, msg) { - var formfield = $("[name='" + field + "'], [data-name='" + field + "']"); - var label = $("label[data-field='" + field + "']"); - var msgbox = $(".form-control-feedback[data-field='" + field + "']"); + // display errors contextually + $.each(errors, function(field, msg) { + var formfield = $("[name='" + field + "'], [data-name='" + field + "']"); + var label = $("label[data-field='" + field + "']"); + var msgbox = $(".form-control-feedback[data-field='" + field + "']"); - // add error classes to bad fields - formfield.addClass('form-control-danger'); - label.addClass('has-danger'); - msgbox.html(msg).addClass('has-danger').removeClass('hide'); + // add error classes to bad fields + formfield.addClass('form-control-danger'); + label.addClass('has-danger'); + msgbox.html(msg).addClass('has-danger').removeClass('hide'); - // check if this field comes first in DOM - var domfield = formfield.get(0); + // check if this field comes first in DOM + var domfield = formfield.get(0); - if (!firstfield || (firstfield && firstfield.compareDocumentPosition(domfield) === 2)) { - firstfield = domfield; - } - }); + if (!firstfield || (firstfield && firstfield.compareDocumentPosition(domfield) === 2)) { + firstfield = domfield; + } + }); - // focus on first bad field - firstfield.focus(); + // focus on first bad field + firstfield.focus(); - // scroll to above that field to make it visible - $('html, body').animate({ - scrollTop: $(firstfield).offset().top - 200 - }, 100); - } - }); - }); + // scroll to above that field to make it visible + $('html, body').animate({ + scrollTop: $(firstfield).offset().top - 200 + }, 100); + } + }); + }); - // remove all error classes - function removeErrors(formSelector = '') { - $(formSelector + " .form-control-danger").removeClass('form-control-danger'); - $(formSelector + " [data-field]").removeClass('has-danger'); - $(formSelector + " .form-control-feedback[data-field]").addClass('hide'); - } + // remove all error classes + function removeErrors(formSelector = '') { + $(formSelector + " .form-control-danger").removeClass('form-control-danger'); + $(formSelector + " [data-field]").removeClass('has-danger'); + $(formSelector + " .form-control-feedback[data-field]").addClass('hide'); + } - // store selected vehicle data - var vdata = false; + // store selected vehicle data + var vdata = false; - // vehicle selector + // vehicle selector {% if ftags.vehicle_dropdown %} // vehicle selector - $('#customer-vehicle').select2({ - ajax: { - url: "{{ url('customer_vehicle_search') }}", - dataType: 'json', - delay: 200, - data: function (params) { - var query = { - search: params.term, - page: params.page || 1 - } + $('#customer-vehicle').select2({ + ajax: { + url: "{{ url('customer_vehicle_search') }}", + dataType: 'json', + delay: 200, + data: function (params) { + var query = { + search: params.term, + page: params.page || 1 + } - return query; - } - }, - placeholder: "Select a vehicle" - }).on('select2:select', function(e) { - var data = e.params.data; + return query; + } + }, + placeholder: "Select a vehicle" + }).on('select2:select', function(e) { + var data = e.params.data; - // get info for this customer vehicle - $.ajax({ - method: "GET", - url: "{{ url('customer_vehicle_info') }}", - data: { id: data.id } - }).done(function(response) { - vdata = response.data; - $('#vid').val(vdata.vehicle.id); + // get info for this customer vehicle + $.ajax({ + method: "GET", + url: "{{ url('customer_vehicle_info') }}", + data: { id: data.id } + }).done(function(response) { + vdata = response.data; + $('#vid').val(vdata.vehicle.id); - $('#flag-new-customer').prop('checked', false).change(); + $('#flag-new-customer').prop('checked', false).change(); - // reset vehicle fields - resetVehicleFields(); + // reset vehicle fields + resetVehicleFields(); - // reset invoice fields - $("#btn-reset-invoice").click(); + // reset invoice fields + $("#btn-reset-invoice").click(); - // get compatible batteries - $("#invoice-bmfg").change(); + // get compatible batteries + $("#invoice-bmfg").change(); - // set form fields - $("[data-vehicle-field='1']").prop('placeholder', ''); - $("#customer-first-name").val(vdata.customer.first_name); - $("#customer-last-name").val(vdata.customer.last_name); - $("#customer-phone-mobile").val(vdata.customer.phone_mobile); - $("#customer-phone-landline").val(vdata.customer.phone_landline); - $("#customer-phone-office").val(vdata.customer.phone_office); - $("#customer-customer-notes").val(vdata.customer.customer_notes); - $("#cv-mfg").val(vdata.vehicle.mfg_id); - // get vehicles for this manufacturer - get_vehicle_makes(vdata.vehicle.mfg_id, vdata.vehicle.id); + // set form fields + $("[data-vehicle-field='1']").prop('placeholder', ''); + $("#customer-first-name").val(vdata.customer.first_name); + $("#customer-last-name").val(vdata.customer.last_name); + $("#customer-phone-mobile").val(vdata.customer.phone_mobile); + $("#customer-phone-landline").val(vdata.customer.phone_landline); + $("#customer-phone-office").val(vdata.customer.phone_office); + $("#customer-customer-notes").val(vdata.customer.customer_notes); + $("#cv-mfg").val(vdata.vehicle.mfg_id); + // get vehicles for this manufacturer + get_vehicle_makes(vdata.vehicle.mfg_id, vdata.vehicle.id); - $("#vehicle-make").val(vdata.vehicle.make); - $("#cv-year").val(vdata.vehicle.model_year); - $("#cv-color").val(vdata.vehicle.color); - $("#cv-plate").val(vdata.vehicle.plate_number); + $("#vehicle-make").val(vdata.vehicle.make); + $("#cv-year").val(vdata.vehicle.model_year); + $("#cv-color").val(vdata.vehicle.color); + $("#cv-plate").val(vdata.vehicle.plate_number); - if (typeof vdata.battery !== 'undefined') { - $("#current-battery").val(vdata.battery.mfg_name + " " + vdata.battery.model_name + " " + vdata.battery.size_name + " (" + vdata.battery.prod_code + ")"); - $("#warranty-code").val(vdata.battery.warranty_code); - $("#warranty-expiration").val(vdata.battery.warranty_expiration); - } else { - $("#current-battery, #warranty-expiration").val("No current battery").css('color', '#f4516c'); - } - $("#or_name").val(vdata.customer.first_name + ' ' + vdata.customer.last_name); - }) - }).focus(); + if (typeof vdata.battery !== 'undefined') { + $("#current-battery").val(vdata.battery.mfg_name + " " + vdata.battery.model_name + " " + vdata.battery.size_name + " (" + vdata.battery.prod_code + ")"); + $("#warranty-code").val(vdata.battery.warranty_code); + $("#warranty-expiration").val(vdata.battery.warranty_expiration); + } else { + $("#current-battery, #warranty-expiration").val("No current battery").css('color', '#f4516c'); + } + $("#or_name").val(vdata.customer.first_name + ' ' + vdata.customer.last_name); + }) + }).focus(); {% endif %} {% if ftags.vehicle_dropdown %} - // reference job order selector - $('#ref-jo').select2({ - ajax: { - url: "{{ url('jo_search') }}", - dataType: 'json', - delay: 200, - data: function (params) { - var query = { - search: params.term, - page: params.page || 1 - } + // reference job order selector + $('#ref-jo').select2({ + ajax: { + url: "{{ url('jo_search') }}", + dataType: 'json', + delay: 200, + data: function (params) { + var query = { + search: params.term, + page: params.page || 1 + } - return query; - } - }, - placeholder: "Select a job order", - allowClear: true - }); + return query; + } + }, + placeholder: "Select a job order", + allowClear: true + }); {% endif %} // reset all vehicle info form fields function resetVehicleFields() { - $("[data-vehicle-field='1']").val("").css('color', '').prop('placeholder', 'Select a vehicle first'); + $("[data-vehicle-field='1']").val("").css('color', '').prop('placeholder', 'Select a vehicle first'); } - // datepicker - $(".dp").datepicker({ + // datepicker + $(".dp").datepicker({ format: "dd M yyyy", todayHighlight: true, autoclose: true, @@ -1273,24 +1387,25 @@ $(function() { }); // toggle advance order fields - $("#flag-advance").change(function() { - var dp = $("[name='date_schedule_date']"); - var tp = $("[name='date_schedule_time']"); - var checked = $(this).prop('checked'); + $("#flag-advance").change(function() { + var dp = $("[name='date_schedule_date']"); + var tp = $("[name='date_schedule_time']"); + var checked = $(this).prop('checked'); - if (checked) { - dp.prop('disabled', false); - tp.prop('disabled', false); - } else { - // reset to default values if disabled - var dateObj = moment(dp.data('default-value'), "YYYY-MM-DD"); - dp.prop('disabled', true).parent().datepicker('setDate', dateObj.toDate()); - tp.prop('disabled', true).timepicker('setTime', tp.data('default-value')); - } - }).change(); + if (checked) { + dp.prop('disabled', false); + tp.prop('disabled', false); + } else { + // reset to default values if disabled + var dateObj = moment(dp.data('default-value'), "YYYY-MM-DD"); + dp.prop('disabled', true).parent().datepicker('setDate', dateObj.toDate()); + tp.prop('disabled', true).timepicker('setTime', tp.data('default-value')); + } + }).change(); // toggle new customer $("#flag-new-customer").change(function() { + checked = $(this).prop('checked'); if (checked) { $('.cust_field').prop('disabled', false); @@ -1307,19 +1422,19 @@ $(function() { }).change(); // vehicle manufacturer change - $("#cv-mfg").change(function() { - var id = $(this).val(); + $("#cv-mfg").change(function() { + var id = $(this).val(); field = $('#cv-make'); - // no id specified - if (!id) { - field.html('').prop('disabled', true); - return true; - } + // no id specified + if (!id) { + field.html('').prop('disabled', true); + return true; + } - // get vehicles for this manufacturer + // get vehicles for this manufacturer get_vehicle_makes(id); - }); + }); // vehicle make change (store in vid) $("#cv-make").change(function() { @@ -1327,50 +1442,50 @@ $(function() { $('#invoice-bmfg').change(); }); - // update battery list when changing manufacturer - $("#invoice-bmfg").change(function() { + // update battery list when changing manufacturer + $("#invoice-bmfg").change(function() { {% if ftags.preset_vehicle %} - $('#vid').val({{ vid }}); + $('#vid').val({{ vid }}); {% endif %} - // must have a selected vehicle + // must have a selected vehicle vid = $('#vid').val(); - if (vid == 0) - return; + if (vid == 0) + return; - var id = $(this).val(); - var field = $("#invoice-battery"); + var id = $(this).val(); + var field = $("#invoice-battery"); - // no id specified - if (!id) { - field.html('').prop('disabled', true); - return true; - } + // no id specified + if (!id) { + field.html('').prop('disabled', true); + return true; + } - // get vehicles for this manufacturer - $.ajax({ - method: "POST", - url: "{{ url('vehicle_batteries') }}", - data: { - id: id, - vehicle_id: vid - } - }).done(function(response) { - if (response.data.length > 0) { - var html = ''; + // get vehicles for this manufacturer + $.ajax({ + method: "POST", + url: "{{ url('vehicle_batteries') }}", + data: { + id: id, + vehicle_id: vid + } + }).done(function(response) { + if (response.data.length > 0) { + var html = ''; - // TODO: Battery unit price is static for now - var unitPrice = 1000; + // TODO: Battery unit price is static for now + var unitPrice = 1000; - $.each(response.data, function(index, battery) { - html += ''; - }); + $.each(response.data, function(index, battery) { + html += ''; + }); - field.html(html).prop('disabled', false); - } else { - field.html('').prop('disabled', true); - } - }); - }); + field.html(html).prop('disabled', false); + } else { + field.html('').prop('disabled', true); + } + }); + }); // populate battery dropdown for create from vehicle mode {% if ftags.preset_vehicle %} @@ -1387,7 +1502,7 @@ $(function() { var sc_array = []; // populate invoiceItems if editing so that we don't lose the battery - {% if mode in ['view-all', 'assign-advance-joborder', 'assign-advance-job-order-edit'] %} + {% if mode in ['view-all', 'open-edit', 'onestep-edit', 'walk-in-edit', 'assign-advanceorder'] %} {% if (obj.getInvoice and obj.getInvoice.getItems|length > 0) %} {% for item in obj.getInvoice.getItems %} {% if item.getBattery() %} @@ -1401,49 +1516,49 @@ $(function() { {% endif %} {% endif %} - // add to invoice - $("#btn-add-to-invoice").click(function() { - var bmfg = $("#invoice-bmfg").val(); - var battery = $("#invoice-battery").val(); - var tradeIn = $("#invoice-trade-in-type").val(); - var qty = $("#invoice-quantity").val(); + // add to invoice + $("#btn-add-to-invoice").click(function() { + var bmfg = $("#invoice-bmfg").val(); + var battery = $("#invoice-battery").val(); + var tradeIn = $("#invoice-trade-in-type").val(); + var qty = $("#invoice-quantity").val(); - if (!bmfg || !battery || !qty) { - swal({ - title: 'Whoops!', - text: 'Please fill in all the invoice fields.', - type: 'warning' - }); + if (!bmfg || !battery || !qty) { + swal({ + title: 'Whoops!', + text: 'Please fill in all the invoice fields.', + type: 'warning' + }); - return false; - } + return false; + } - if (isNaN(qty)) { - swal({ - title: 'Whoops!', - text: 'Invalid quantity specified.', - type: 'warning' - }); + if (isNaN(qty)) { + swal({ + title: 'Whoops!', + text: 'Invalid quantity specified.', + type: 'warning' + }); - return false; - } + return false; + } - // add to invoice array - invoiceItems.push({ - battery: battery, - quantity: qty, - trade_in: tradeIn, - }); + // add to invoice array + invoiceItems.push({ + battery: battery, + quantity: qty, + trade_in: tradeIn, + }); - // regenerate the invoice - generateInvoice(); - }); + // regenerate the invoice + generateInvoice(); + }); - // update invoice when promo is changed - $("#invoice-discount").change(function() { - console.log('discount ' + $("#invoice-discount").val()); - generateInvoice(); - }); + // update invoice when promo is changed + $("#invoice-discount").change(function() { + console.log('discount ' + $("#invoice-discount").val()); + generateInvoice(); + }); // trigger update when service type is changed $("#service_type").change(function() { @@ -1493,108 +1608,251 @@ $(function() { }).done(function(response) { // mark as invoice changed $("#invoice-change").val(1); - var invoice = response.invoice; -i - // populate totals - $("#invoice-discount").val(invoice.discount); - $("#invoice-price").val(invoice.price); - $("#invoice-trade-in").val(invoice.trade_in); - $("#invoice-vat").val(invoice.vat); - $("#invoice-total-amount").val(invoice.total_price); + var invoice = response.invoice; - // populate rows - var html = ''; + // populate totals + $("#invoice-discount").val(invoice.discount); + $("#invoice-price").val(invoice.price); + $("#invoice-trade-in").val(invoice.trade_in); + $("#invoice-vat").val(invoice.vat); + $("#invoice-total-amount").val(invoice.total_price); - if (invoice.items.length > 0) { - $.each(invoice.items, function(key, item) { - html += '' + - '' + item.title + '' + - '' + item.quantity + '' + - '' + item.unit_price + '' + - '' + item.amount + '' + - ''; - }); - } else { - html = '' + - '' + - 'No items to display.' + - '' + - ''; - } + // populate rows + var html = ''; - table.html(html); - }); - } - - // remove from invoice table - // TODO: figure out a way to delete rows, and should deleting trade ins be allowed since they count as items on the table? - /* - $(document).on("click", ".btn-invoice-delete", function() { - var tbody = $("#invoice-table tbody"); - var row = $(this).closest('tr'); - var qty = row.find('.col-quantity').html(); - var unitPrice = row.find('.col-unit-price').html(); - - // recreate the local invoice items object - var newItems = []; - - // subtract from totals - var subtotal = parseFloat(unitPrice) * parseInt(qty); - invoiceTotal -= subtotal; - updateInvoiceFigures(); - - // remove from table - row.remove(); - - // get total item rows and show placeholder if needed - var visibleRows = tbody.find('tr:not(.placeholder-row)').length; - - if (visibleRows === 0) { - tbody.find('.placeholder-row').removeClass('hide'); - } - }); - */ - - // cancel job order - $(".btn-cancel-job-order").click(function(e) { - var url = $(this).prop('href'); - - e.preventDefault(); - - swal({ - title: 'Cancel Job Order', - html: 'Please enter the reason for cancellation of this job order:', - input: 'textarea', - inputClass: 'form-control', - type: 'warning', - showCancelButton: true, - width: '40rem', - preConfirm: (reason) => { - if (!reason) { - swal.showValidationError( - 'Reason for cancellation is required.' - ) - } - } - }).then((reason) => { - $.ajax({ - method: "DELETE", - url: url, - data: { - 'cancel_reason': reason.value - } - }).done(function(response) { - swal({ - title: 'Done!', - text: response.success, - type: 'success', - onClose: function() { - window.location.href = "{{ return_url }}"; - } + if (invoice.items.length > 0) { + $.each(invoice.items, function(key, item) { + html += '' + + '' + item.title + '' + + '' + item.quantity + '' + + '' + item.unit_price + '' + + '' + item.amount + '' + + /* + '' + + */ + ''; }); - }); - }); - }); + } else { + html = '' + + '' + + 'No items to display.' + + '' + + ''; + } + + table.html(html); + }); + } + + // remove from invoice table + // TODO: figure out a way to delete rows, and should deleting trade ins be allowed since they count as items on the table? + /* + $(document).on("click", ".btn-invoice-delete", function() { + var tbody = $("#invoice-table tbody"); + var row = $(this).closest('tr'); + var qty = row.find('.col-quantity').html(); + var unitPrice = row.find('.col-unit-price').html(); + + // recreate the local invoice items object + var newItems = []; + + // subtract from totals + var subtotal = parseFloat(unitPrice) * parseInt(qty); + invoiceTotal -= subtotal; + updateInvoiceFigures(); + + // remove from table + row.remove(); + + // get total item rows and show placeholder if needed + var visibleRows = tbody.find('tr:not(.placeholder-row)').length; + + if (visibleRows === 0) { + tbody.find('.placeholder-row').removeClass('hide'); + } + }); + */ + + {% if mode in ['update-processing', 'update-reassign-hub'] %} + var selectedHub = '{{ obj.getHub ? obj.getHub.getID : "" }}'; + + $("#hubs-table tbody tr").click(function() { + var id = $(this).data('id'); + var lat = $(this).data('lat'); + var lng = $(this).data('lng'); + + if (id != selectedHub) { + // highlight this row, set hub value + $("#hubs-table").find('.m-table__row--primary').removeClass('m-table__row--primary'); + + $(this).addClass('m-table__row--primary'); + + // set value + selectedHub = id; + + // center the map + osm_hmap.flyTo(L.latLng(lat, lng)); + } else { + // unhighlight this row + $(this).removeClass('m-table__row--primary'); + + // remove id value + selectedHub = ''; + } + }); + {% endif %} + + {% if mode in ['update-assigning', 'update-reassign-rider'] %} + var selectedRider = '{{ obj.getRider ? obj.getRider.getID : "" }}'; + + $("#riders-table tbody tr").click(function() { + var id = $(this).data('id'); + + if (id != selectedRider) { + // highlight this row, set hub value + $("#riders-table").find('.m-table__row--primary').removeClass('m-table__row--primary'); + + $(this).addClass('m-table__row--primary'); + + // set value + selectedRider = id; + } else { + // unhighlight this row + $(this).removeClass('m-table__row--primary'); + + // remove id value + selectedRider = ''; + } + }); + {% endif %} + + {% if mode in ['update-processing', 'update-reassign-hub'] %} + // reject hub + $(".btn-reject").click(function(e) { + var hubID = $(this).data('hub-id'); + var hubName = $(this).data('hub-name'); + var hubBranch = $(this).data('hub-branch'); + + $("#hub-reject-id").val(hubID); + $("#hub-reject-name").val(hubName); + $("#hub-reject-branch").val(hubBranch); + $("#modal-rejection").modal('show'); + + return false; + }); + + // focus on reason field + $("#modal-rejection").on('shown.bs.modal', function() { + $("#hub-reject-reason").focus(); + }); + + // reset reject form on close modal + $("#modal-rejection").on('hidden.bs.modal', function() { + $("#hub-reject-contact-person, #hub-reject-remarks").val(""); + $("#hub-reject-reason").prop('selectedIndex', 0); + }); + + // submit hub rejection + $("#hub-reject-form").submit(function(e) { + var form = $(this); + var btnSubmit = form.find('[type="submit"]'); + + // disable the button + btnSubmit.prop('disabled', true).html(' Please wait'); + + e.preventDefault(); + + $.ajax({ + method: "POST", + url: form.prop('action'), + data: form.serialize() + }).done(function(response) { + // set button state + var btnReject = $("#hubs-table").find("tr[data-id='" + $("#hub-reject-id").val() + "']").find('.btn-reject'); + btnReject.removeClass('btn-reject btn-info').addClass('btn-danger btn-disabled').prop('disabled', true).html('Rejected'); + + // remove all error classes + removeErrors("#hub-reject-form"); + btnSubmit.prop('disabled', false).html('Reject'); + + // hide modal + $("#modal-rejection").modal('hide'); + }).fail(function(response) { + if (response.status == 422) { + form_in_process = false; + var errors = response.responseJSON.errors; + var firstfield = false; + + // remove all error classes first + removeErrors("#hub-reject-form"); + btnSubmit.prop('disabled', false).html('Reject'); + + // display errors contextually + $.each(errors, function(field, msg) { + var formfield = form.find("[name='" + field + "'], [data-name='" + field + "']"); + var label = form.find("label[data-field='" + field + "']"); + var msgbox = form.find(".form-control-feedback[data-field='" + field + "']"); + + // add error classes to bad fields + formfield.addClass('form-control-danger'); + label.addClass('has-danger'); + msgbox.html(msg).addClass('has-danger').removeClass('hide'); + + // check if this field comes first in DOM + var domfield = formfield.get(0); + + if (!firstfield || (firstfield && firstfield.compareDocumentPosition(domfield) === 2)) { + firstfield = domfield; + } + }); + + // focus on first bad field + firstfield.focus(); + } + }); + }); + {% endif %} + + // cancel job order + $(".btn-cancel-job-order").click(function(e) { + var url = $(this).prop('href'); + + e.preventDefault(); + + swal({ + title: 'Cancel Job Order', + html: 'Please enter the reason for cancellation of this job order:', + input: 'textarea', + inputClass: 'form-control', + type: 'warning', + showCancelButton: true, + width: '40rem', + preConfirm: (reason) => { + if (!reason) { + swal.showValidationError( + 'Reason for cancellation is required.' + ) + } + } + }).then((reason) => { + $.ajax({ + method: "DELETE", + url: url, + data: { + 'cancel_reason': reason.value + } + }).done(function(response) { + swal({ + title: 'Done!', + text: response.success, + type: 'success', + onClose: function() { + window.location.href = "{{ return_url }}"; + } + }); + }); + }); + }); // service charge add $('#btn-sc-add').click(function(e) { diff --git a/templates/job-order/cmb.list.assignadvanceorder.html.twig b/templates/job-order/cmb.list.assignadvanceorder.html.twig index 752c1d22..26baeaba 100644 --- a/templates/job-order/cmb.list.assignadvanceorder.html.twig +++ b/templates/job-order/cmb.list.assignadvanceorder.html.twig @@ -114,7 +114,7 @@ sortable: false, overflow: 'visible', template: function (row, index, datatable) { - {% if is_granted('jo_onestep.edit') or is_granted('jo_advance_order.edit') or is_granted('jo_assign_advance_order.edit') %} + {% if is_granted('jo_assign_advance_order.form') %} var actions = ''; {% endif %} -- 2.43.5 From 4e2757ac56dd20e79e11c263328bb3685a87dd44 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 30 Sep 2020 08:16:47 +0000 Subject: [PATCH 5/5] Disable the advance order checkbox. #509 --- templates/job-order/cmb.form.advanceorder.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/job-order/cmb.form.advanceorder.html.twig b/templates/job-order/cmb.form.advanceorder.html.twig index 2e44cea8..e480fa20 100644 --- a/templates/job-order/cmb.form.advanceorder.html.twig +++ b/templates/job-order/cmb.form.advanceorder.html.twig @@ -240,7 +240,7 @@ -- 2.43.5