From f030eeef2a0ecbe0107012d64d0540125bdfc87b Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 28 Apr 2020 09:08:48 +0000 Subject: [PATCH] Add newRequestJobOrder API call. #389 --- config/routes/api.yaml | 5 + src/Controller/APIController.php | 376 +++++++++++++++++++++++++++++++ src/Ramcar/AdvanceOrderSlot.php | 29 +++ 3 files changed, 410 insertions(+) create mode 100644 src/Ramcar/AdvanceOrderSlot.php diff --git a/config/routes/api.yaml b/config/routes/api.yaml index 5531407f..aa1ce722 100644 --- a/config/routes/api.yaml +++ b/config/routes/api.yaml @@ -154,3 +154,8 @@ api_nearest_hub_slots: path: /api/hub_slots controller: App\Controller\APIController::getNearestHubAndSlots methods: [GET] + +api_new_jo_request: + path: /api/new_job_order + controller: App\Controller\APIController::newRequestJobOrder + methods: [POST] diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 1d4d02d0..4c40af9f 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -23,6 +23,7 @@ use App\Ramcar\APIRiderStatus; use App\Ramcar\TransactionOrigin; use App\Ramcar\TradeInType; use App\Ramcar\JOEventType; +use App\Ramcar\AdvanceOrderSlot; use App\Service\InvoiceGeneratorInterface; use App\Service\RisingTideGateway; @@ -2305,6 +2306,342 @@ class APIController extends Controller implements LoggedController } + public function newRequestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, + MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, + RiderAssignmentHandlerInterface $rah) + { + // check required parameters and api key + $required_params = [ + 'service_type', + 'cv_id', + 'trade_in', + 'long', + 'lat', + 'warranty', + 'mode_of_payment', + ]; + $em = $this->getDoctrine()->getManager(); + $res = $this->checkParamsAndKey($req, $em, $required_params); + if ($res->isError()) + return $res->getReturnResponse(); + + // trade in type + $trade_in = $req->request->get('trade_in'); + + // address + $address = $req->request->get('delivery_address', 'Set by mobile application'); + + // instructions + $instructions = $req->request->get('delivery_instructions', ''); + + // longitude and latitude + $long = $req->request->get('long'); + $lat = $req->request->get('lat'); + + // geofence + $is_covered = $geo->isCovered($long, $lat); + if (!$is_covered) + { + // TODO: put geofence error message in config file somewhere + $res->setError(true) + ->setErrorMessage('Oops! Our service is limited to some areas in Metro Manila, Laguna, and Baguio only. We will update you as soon as we are able to cover your area'); + return $res->getReturnResponse(); + } + + $hub = null; + $hub_id = $req->request->get('hub_id'); + if (strlen($hub_id) > 0) + $hub = $em->getRepository(Hub::class)->find($hub_id); + + $schedule_date = $req->request->get('date_schedule'); + $slot_id = $req->request->get('slot_id'); + $advance_order = $req->request->get('flag_advance_order'); + $flag_advance_order = ($advance_order === 'true') ? true : false; + + $jo = new JobOrder(); + $jo->setSource(TransactionOrigin::MOBILE_APP) + ->setStatus(JOStatus::PENDING) + ->setDeliveryInstructions('') + ->setTier1Notes('') + ->setTier2Notes('') + ->setDeliveryAddress($address) + ->setTradeInType($trade_in) + ->setDeliveryInstructions($instructions) + // TODO: error check for valid mode of payment + ->setModeOfPayment($req->request->get('mode_of_payment')) + ->setAdvanceOrder($flag_advance_order); + + // customer + $cust = $this->session->getCustomer(); + if ($cust == null) + { + $res->setError(true) + ->setErrorMessage('No customer information found'); + return $res->getReturnResponse(); + } + $jo->setCustomer($cust); + + // validate service type + $stype = $req->request->get('service_type'); + if (!ServiceType::validate($stype)) + { + $res->setError(true) + ->setErrorMessage('Invalid service type'); + return $res->getReturnResponse(); + } + $jo->setServiceType($stype); + + // validate warranty + $warr = $req->request->get('warranty'); + if (!WarrantyClass::validate($warr)) + { + $res->setError(true) + ->setErrorMessage('Invalid warranty class'); + return $res->getReturnResponse(); + } + $jo->setWarrantyClass($warr); + + // set coordinates + $point = new Point($long, $lat); + $jo->setCoordinates($point); + + // make invoice criteria + $icrit = new InvoiceCriteria(); + $icrit->setServiceType($stype); + + // check promo + $promo_id = $req->request->get('promo_id'); + if (!empty($promo_id)) + { + $promo = $em->getRepository(Promo::class)->find($promo_id); + if ($promo == null) + { + $res->setError(true) + ->setErrorMessage('Invalid promo id'); + return $res->getReturnResponse(); + } + + // put in criteria + $icrit->addPromo($promo); + } + + // check customer vehicle + $cv = $em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id')); + if ($cv == null) + { + $res->setError(true) + ->setErrorMessage('Invalid customer vehicle id'); + return $res->getReturnResponse(); + } + $icrit->setCustomerVehicle($cv); + $jo->setCustomerVehicle($cv); + + // check if customer owns vehicle + if ($cust->getID() != $cv->getCustomer()->getID()) + { + $res->setError(true) + ->setErrorMessage('Customer does not own vehicle'); + return $res->getReturnResponse(); + } + + // check battery + $batt_id = $req->request->get('batt_id'); + if ($batt_id != null) + { + $batt = $em->getRepository(Battery::class)->find($batt_id); + if ($batt == null) + { + $res->setError(true) + ->setErrorMessage('Invalid battery id'); + return $res->getReturnResponse(); + } + } + else + $batt = null; + + /* + // put battery in criteria + $icrit->addBattery($batt); + */ + + // check trade-in + // only allow motolite, other, none + switch ($trade_in) + { + case TradeInType::MOTOLITE: + case TradeInType::OTHER: + break; + + default: + $trade_in = ''; + break; + } + + $icrit->addEntry($batt, $trade_in, 1); + + // send to invoice generator + $invoice = $ic->generateInvoice($icrit); + $jo->setInvoice($invoice); + + // assign hub and rider + // check if hub is null + if ($hub == null) + { + // find nearest hub + if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || + ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + { + // get nearest hub + // $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im); + $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + } + else + { + $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + } + + if (!empty($nearest_hub)) + { + //error_log('found nearest hub ' . $nearest_hub->getID()); + // assign rider + $available_riders = $nearest_hub->getAvailableRiders(); + if (count($available_riders) > 0) + { + $assigned_rider = null; + if (count($available_riders) > 1) + { + // TODO: the setting of riders into an array + // will no longer be necessary when the contents + // of randomizeRider changes + $riders = []; + foreach ($available_riders as $rider) + { + $riders[] = $rider; + } + + $assigned_rider = $this->randomizeRider($riders); + } + else + $assigned_rider = $available_riders[0]; + + //error_log('found rider ' . $assigned_rider->getID()); + $jo->setHub($nearest_hub); + $jo->setRider($assigned_rider); + $jo->setStatus(JOStatus::ASSIGNED); + + $assigned_rider->setAvailable(false); + } + } + } + else + { + $date_schedule = null; + if ((strlen($schedule_date) > 0) && (strlen($slot_id) > 0)) + { + $time_schedule = $this->getTimeFromSlot($slot_id); + if (!empty($time_schedule)) + { + $s_date = $schedule_date . ' ' . $time_schedule; + $date_schedule = DateTime::createFromFormat('Y-m-d H:i', $s_date); + //error_log($date_schedule->format('Y-m-d H:i')); + } + } + + $jo->setHub($hub); + $jo->setStatus(JOStatus::RIDER_ASSIGN); + + if ($date_schedule != null) + $jo->setDateSchedule($date_schedule); + } + + $em->persist($jo); + $em->persist($invoice); + + // add event log for JO + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::CREATE) + ->setJobOrder($jo); + $em->persist($event); + + // check JO status + if ($jo->getStatus() == JOStatus::ASSIGNED) + { + // add event logs for hub and rider assignments + $hub_assign_event = new JOEvent(); + $hub_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::HUB_ASSIGN) + ->setJobOrder($jo); + + $em->persist($hub_assign_event); + + $rider_assign_event = new JOEvent(); + $rider_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_ASSIGN) + ->setJobOrder($jo); + + $em->persist($rider_assign_event); + + // user mqtt event + $payload = [ + 'event' => 'outlet_assign' + ]; + $mclient->sendEvent($jo, $payload); + + $rah->assignJobOrder($jo, $jo->getRider()); + } + + if ($jo->getStatus() == JOStatus::RIDER_ASSIGN) + { + // add event logs for hub assignments + $hub_assign_event = new JOEvent(); + $hub_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::HUB_ASSIGN) + ->setJobOrder($jo); + + $em->persist($hub_assign_event); + + // user mqtt event + $payload = [ + 'event' => 'outlet_assign' + ]; + $mclient->sendEvent($jo, $payload); + } + + $em->flush(); + + // make invoice json data + $invoice_data = [ + 'total_price' => $invoice->getTotalPrice(), + 'vat_ex_price' => $invoice->getVATExclusivePrice(), + 'vat' => $invoice->getVAT(), + 'discount' => $invoice->getDiscount(), + 'trade_in' => $invoice->getTradeIn(), + ]; + $items = $invoice->getItems(); + $items_data = []; + foreach ($items as $item) + { + $items_data[] = [ + 'title' => $item->getTitle(), + 'qty' => $item->getQuantity() + 0, + 'price' => $item->getPrice() + 0.0, + ]; + } + $invoice_data['items'] = $items_data; + + // make job order data + $data = [ + 'jo_id' => $jo->getID(), + 'invoice' => $invoice_data + ]; + + // set data + $res->setData($data); + + return $res->getReturnResponse(); + } + protected function findCustomerByNumber($number) { $em = $this->getDoctrine()->getManager(); @@ -2979,4 +3316,43 @@ class APIController extends Controller implements LoggedController } } } + + protected function getTimeFromSlot($slot_id) + { + $time_selected = ''; + + switch($slot_id) { + case '08_09': + $time_selected = AdvanceOrderSlot::_08_09; + break; + case '09_10': + $time_selected = AdvanceOrderSlot::_09_10; + break; + case '10_11': + $time_selected = AdvanceOrderSlot::_10_11; + break; + case '11_12': + $time_selected = AdvanceOrderSlot::_11_12; + break; + case '12_13': + $time_selected = AdvanceOrderSlot::_12_13; + break; + case '13_14': + $time_selected = AdvanceOrderSlot::_13_14; + break; + case '14_15': + $time_selected = AdvanceOrderSlot::_14_15; + break; + case '15_16': + $time_selected = AdvanceOrderSlot::_15_16; + break; + case '16_17': + $time_selected = AdvanceOrderSlot::_16_17; + break; + default: + error_log('Invalid slot id ' . $slot_id); + } + + return $time_selected; + } } diff --git a/src/Ramcar/AdvanceOrderSlot.php b/src/Ramcar/AdvanceOrderSlot.php new file mode 100644 index 00000000..4967eeaf --- /dev/null +++ b/src/Ramcar/AdvanceOrderSlot.php @@ -0,0 +1,29 @@ + '08:00', + '09:00' => '09:00', + '10:00' => '10:00', + '11:00' => '11:00', + '12:00' => '12:00', + '13:00' => '13:00', + '14:00' => '14:00', + '15:00' => '15:00', + '16:00' => '16:00', + ]; +}