From 9876165af52605adb5001b354c36c7d34943a440 Mon Sep 17 00:00:00 2001 From: Ramon Gutierrez Date: Tue, 7 Feb 2023 08:25:07 +0800 Subject: [PATCH] Adjust new customer api method groupings, add routes #730 --- config/routes/api.yaml | 180 ++++---- config/routes/customer_api.yaml | 227 +++++++++ .../CustomerAppAPI/CustomerController.php | 16 - .../CustomerAppAPI/DeviceController.php | 25 + .../CustomerAppAPI/EstimateController.php | 125 +++++ .../CustomerAppAPI/JobOrderController.php | 437 +++++++++++++----- 6 files changed, 791 insertions(+), 219 deletions(-) create mode 100644 config/routes/customer_api.yaml create mode 100644 src/Controller/CustomerAppAPI/DeviceController.php create mode 100644 src/Controller/CustomerAppAPI/EstimateController.php diff --git a/config/routes/api.yaml b/config/routes/api.yaml index 19e3a468..2253f65d 100644 --- a/config/routes/api.yaml +++ b/config/routes/api.yaml @@ -1,227 +1,227 @@ # api api_register: - path: /api/register - controller: App\Controller\APIController::register + path: /apiv2/register + controller: App\Controller\CustomerAppAPI\AuthController::register methods: [POST] api_confirm: - path: /api/number_confirm - controller: App\Controller\APIController::confirmNumber + path: /apiv2/number_confirm + controller: App\Controller\CustomerAppAPI\AuthController::confirmNumber methods: [POST] api_validate: - path: /api/code_validate - controller: App\Controller\APIController::validateCode + path: /apiv2/code_validate + controller: App\Controller\CustomerAppAPI\AuthController::validateCode methods: [POST] api_info_get: - path: /api/info - controller: App\Controller\APIController::getInfo + path: /apiv2/info + controller: App\Controller\CustomerAppAPI\CustomerController::getInfo methods: [GET] api_info_update: - path: /api/info - controller: App\Controller\APIController::updateInfo + path: /apiv2/info + controller: App\Controller\CustomerAppAPI\CustomerController::updateInfo methods: [POST] api_status: - path: /api/status - controller: App\Controller\APIController::getStatus + path: /apiv2/status + controller: App\Controller\CustomerAppAPI\CustomerController::getStatus methods: [GET] api_vehicle_mfg_list: - path: /api/vehicle/mfgs - controller: App\Controller\APIController::listVehicleManufacturers + path: /apiv2/vehicle/mfgs + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicleManufacturers methods: [GET] api_vehicle_make_list: - path: /api/vehicle/mfgs/{mfg_id}/makes - controller: App\Controller\APIController::listVehicleMakes + path: /apiv2/vehicle/mfgs/{mfg_id}/makes + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicleMakes methods: [GET] api_cust_vehicle_add: - path: /api/vehicles - controller: App\Controller\APIController::addVehicle + path: /apiv2/vehicles + controller: App\Controller\CustomerAppAPI\VehicleController::addVehicle methods: [POST] api_cust_vehicle_update: - path: /api/vehicles/{id} - controller: App\Controller\APIController::updateVehicle + path: /apiv2/vehicles/{id} + controller: App\Controller\CustomerAppAPI\VehicleController::updateVehicle methods: [POST] api_cust_vehicle_list: - path: /api/vehicles - controller: App\Controller\APIController::listVehicles + path: /apiv2/vehicles + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicles methods: [GET] api_promo_list: - path: /api/promos - controller: App\Controller\APIController::listPromos + path: /apiv2/promos + controller: App\Controller\CustomerAppAPI\PromoController::listPromos methods: [GET] api_battery_list: - path: /api/vehicles/{vid}/compatible_batteries - controller: App\Controller\APIController::getCompatibleBatteries + path: /apiv2/vehicles/{vid}/compatible_batteries + controller: App\Controller\CustomerAppAPI\VehicleController::getCompatibleBatteries methods: [GET] api_jo_request: - path: /api/job_order - controller: App\Controller\APIController::requestJobOrder + path: /apiv2/job_order + controller: App\Controller\CustomerAppAPI\JobOrderController::requestJobOrder methods: [POST] api_estimate: - path: /api/estimate - controller: App\Controller\APIController::getEstimate + path: /apiv2/estimate + controller: App\Controller\CustomerAppAPI\EstimateController::getEstimate methods: [POST] api_ongoing: - path: /api/job_order/ongoing - controller: App\Controller\APIController::getOngoing + path: /apiv2/job_order/ongoing + controller: App\Controller\CustomerAppAPI\JobOrderController::getOngoing methods: [GET] api_rider_status: - path: /api/rider - controller: App\Controller\APIController::getRiderStatus + path: /apiv2/rider + controller: App\Controller\CustomerAppAPI\RiderController::getRiderStatus methods: [GET] api_rider_rating_add: - path: /api/rider_rating - controller: App\Controller\APIController::addRiderRating + path: /apiv2/rider_rating + controller: App\Controller\CustomerAppAPI\RiderController::addRiderRating methods: [POST] api_jo_cancel: - path: /api/job_order/cancel - controller: App\Controller\APIController:cancelJobOrder + path: /apiv2/job_order/cancel + controller: App\Controller\CustomerAppAPI\JobOrderController:cancelJobOrder methods: [POST] api_jo_history: - path: /api/job_order/history - controller: App\Controller\APIController:getJOHistory + path: /apiv2/job_order/history + controller: App\Controller\CustomerAppAPI\JobOrderController:getJOHistory methods: [GET] api_jo_invoice: - path: /api/job_order/invoice - controller: App\Controller\APIController:getJOInvoice + path: /apiv2/job_order/invoice + controller: App\Controller\CustomerAppAPI\JobOrderController:getJOInvoice methods: [GET] api_device_id: - path: /api/device_id - controller: App\Controller\APIController:updateDeviceID + path: /apiv2/device_id + controller: App\Controller\CustomerAppAPI\DeviceController:updateDeviceID methods: [POST] api_privacy: - path: /api/privacy - controller: App\Controller\APIController:privacySettings + path: /apiv2/privacy + controller: App\Controller\CustomerAppAPI\PrivacyController:privacySettings methods: [POST] api_resend_code: - path: /api/resend_code - controller: App\Controller\APIController:resendCode + path: /apiv2/resend_code + controller: App\Controller\CustomerAppAPI\AuthController:resendCode methods: [POST] api_location_support: - path: /api/location_support - controller: App\Controller\APIController:locationSupport + path: /apiv2/location_support + controller: App\Controller\CustomerAppAPI\LocationController:locationSupport methods: [GET] api_activate_warranty: - path: /api/activate_warranty - controller: App\Controller\APIController:activateWarranty + path: /apiv2/activate_warranty + controller: App\Controller\CustomerAppAPI\WarrantyController:activateWarranty methods: [POST] api_service_list: - path: /api/services - controller: App\Controller\APIController:listServices + path: /apiv2/services + controller: App\Controller\CustomerAppAPI\ServiceController:listServices methods: [GET] api_partner_info: - path: /api/partners/{pid} - controller: App\Controller\APIController:getPartnerInformation + path: /apiv2/partners/{pid} + controller: App\Controller\CustomerAppAPI\PartnerController:getPartnerInformation methods: [GET] api_partner: - path: /api/partners - controller: App\Controller\APIController:getClosestPartners + path: /apiv2/partners + controller: App\Controller\CustomerAppAPI\PartnerController:getClosestPartners methods: [GET] api_partner_review: - path: /api/partners/{pid}/review - controller: App\Controller\APIController:reviewPartner + path: /apiv2/partners/{pid}/review + controller: App\Controller\CustomerAppAPI\PartnerController:reviewPartner methods: [POST] api_nearest_hub_slots: - path: /api/hub_slots - controller: App\Controller\APIController::getNearestHubAndSlots + path: /apiv2/hub_slots + controller: App\Controller\CustomerAppAPI\LocationController::getNearestHubAndSlots methods: [GET] api_new_jo_request: - path: /api/new_job_order - controller: App\Controller\APIController::newRequestJobOrder + path: /apiv2/new_job_order + controller: App\Controller\CustomerAppAPI\JobOrderController::newRequestJobOrder methods: [POST] api_version_check: - path: /api/version_check - controller: App\Controller\APIController::versionCheck + path: /apiv2/version_check + controller: App\Controller\CustomerAppAPI\AppController::versionCheck methods: [GET] api_schedule_option_status: - path: /api/schedule_option_status - controller: App\Controller\APIController::scheduleOptionStatus + path: /apiv2/schedule_option_status + controller: App\Controller\CustomerAppAPI\ScheduleController::scheduleOptionStatus methods: [GET] # paperless warranty / qr code api_warr_serial_check: - path: /api/warranty/{serial} - controller: App\Controller\APIController::warrantyCheck + path: /apiv2/warranty/{serial} + controller: App\Controller\CustomerAppAPI\WarrantyController::warrantyCheck methods: [GET] api_warr_serial_register: - path: /api/warranty/{serial} - controller: App\Controller\APIController::warrantyRegister + path: /apiv2/warranty/{serial} + controller: App\Controller\CustomerAppAPI\WarrantyController::warrantyRegister methods: [POST] api_jo_info: - path: /api/job_order/{id}/info - controller: App\Controller\APIController::getJobOrderInfo + path: /apiv2/job_order/{id}/info + controller: App\Controller\CustomerAppAPI\JobOrderController::getJobOrderInfo methods: [GET] api_ongoing_job_orders: - path: /api/job_orders/ongoing - controller: App\Controller\APIController::getAllOngoingJobOrders + path: /apiv2/job_orders/ongoing + controller: App\Controller\CustomerAppAPI\JobOrderController::getAllOngoingJobOrders methods: [GET] api_ongoing_jo_count: - path: /api/job_orders/ongoing/count - controller: App\Controller\APIController::getOngoingJobOrderCount + path: /apiv2/job_orders/ongoing/count + controller: App\Controller\CustomerAppAPI\JobOrderController::getOngoingJobOrderCount methods: [GET] api_new_location: - path: /api/new_location - controller: App\Controller\APIController::addLocation + path: /apiv2/new_location + controller: App\Controller\CustomerAppAPI\LocationController::addLocation methods: [POST] api_locations: - path: /api/locations - controller: App\Controller\APIController::getLocations + path: /apiv2/locations + controller: App\Controller\CustomerAppAPI\LocationController::getLocations methods: [GET] api_cust_vehicle_remove: - path: /api/vehicles/{id}/remove - controller: App\Controller\APIController::removeVehicle + path: /apiv2/vehicles/{id}/remove + controller: App\Controller\CustomerAppAPI\VehicleController::removeVehicle methods: [POST] api_latest_job_order: - path: /api/job_order/latest - controller: App\Controller\APIController::getLatestJobOrder + path: /apiv2/job_order/latest + controller: App\Controller\CustomerAppAPI\JobOrderController::getLatestJobOrder methods: [GET] api_customer_hash_get: - path: /api/customer_hash - controller: App\Controller\APIController::getCustomerHash + path: /apiv2/customer_hash + controller: App\Controller\CustomerAppAPI\CustomerController::getCustomerHash methods: [GET] #api_completed_job_orders: -# path: /api/job_orders/completed -# controller: App\Controller\APIController::getCompletedJobOrders +# path: /apiv2/job_orders/completed +# controller: App\Controller\CustomerAppAPI\JobOrderController::getCompletedJobOrders # methods: [GET] diff --git a/config/routes/customer_api.yaml b/config/routes/customer_api.yaml new file mode 100644 index 00000000..86aae804 --- /dev/null +++ b/config/routes/customer_api.yaml @@ -0,0 +1,227 @@ +# api + +cust_api_register: + path: /apiv2/register + controller: App\Controller\CustomerAppAPI\AuthController::register + methods: [POST] + +cust_api_confirm: + path: /apiv2/number_confirm + controller: App\Controller\CustomerAppAPI\AuthController::confirmNumber + methods: [POST] + +cust_api_validate: + path: /apiv2/code_validate + controller: App\Controller\CustomerAppAPI\AuthController::validateCode + methods: [POST] + +cust_api_info_get: + path: /apiv2/info + controller: App\Controller\CustomerAppAPI\CustomerController::getInfo + methods: [GET] + +cust_api_info_update: + path: /apiv2/info + controller: App\Controller\CustomerAppAPI\CustomerController::updateInfo + methods: [POST] + +cust_api_status: + path: /apiv2/status + controller: App\Controller\CustomerAppAPI\CustomerController::getStatus + methods: [GET] + +cust_api_vehicle_mfg_list: + path: /apiv2/vehicle/mfgs + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicleManufacturers + methods: [GET] + +cust_api_vehicle_make_list: + path: /apiv2/vehicle/mfgs/{mfg_id}/makes + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicleMakes + methods: [GET] + +cust_api_cust_vehicle_add: + path: /apiv2/vehicles + controller: App\Controller\CustomerAppAPI\VehicleController::addVehicle + methods: [POST] + +cust_api_cust_vehicle_update: + path: /apiv2/vehicles/{id} + controller: App\Controller\CustomerAppAPI\VehicleController::updateVehicle + methods: [POST] + +cust_api_cust_vehicle_list: + path: /apiv2/vehicles + controller: App\Controller\CustomerAppAPI\VehicleController::listVehicles + methods: [GET] + +cust_api_promo_list: + path: /apiv2/promos + controller: App\Controller\CustomerAppAPI\PromoController::listPromos + methods: [GET] + +cust_api_battery_list: + path: /apiv2/vehicles/{vid}/compatible_batteries + controller: App\Controller\CustomerAppAPI\VehicleController::getCompatibleBatteries + methods: [GET] + +cust_api_jo_request: + path: /apiv2/job_order + controller: App\Controller\CustomerAppAPI\JobOrderController::requestJobOrder + methods: [POST] + +cust_api_estimate: + path: /apiv2/estimate + controller: App\Controller\CustomerAppAPI\EstimateController::getEstimate + methods: [POST] + +cust_api_ongoing: + path: /apiv2/job_order/ongoing + controller: App\Controller\CustomerAppAPI\JobOrderController::getOngoing + methods: [GET] + +cust_api_rider_status: + path: /apiv2/rider + controller: App\Controller\CustomerAppAPI\RiderController::getRiderStatus + methods: [GET] + +cust_api_rider_rating_add: + path: /apiv2/rider_rating + controller: App\Controller\CustomerAppAPI\RiderController::addRiderRating + methods: [POST] + +cust_api_jo_cancel: + path: /apiv2/job_order/cancel + controller: App\Controller\CustomerAppAPI\JobOrderController:cancelJobOrder + methods: [POST] + +cust_api_jo_history: + path: /apiv2/job_order/history + controller: App\Controller\CustomerAppAPI\JobOrderController:getJOHistory + methods: [GET] + +cust_api_jo_invoice: + path: /apiv2/job_order/invoice + controller: App\Controller\CustomerAppAPI\JobOrderController:getJOInvoice + methods: [GET] + +cust_api_device_id: + path: /apiv2/device_id + controller: App\Controller\CustomerAppAPI\DeviceController:updateDeviceID + methods: [POST] + +cust_api_privacy: + path: /apiv2/privacy + controller: App\Controller\CustomerAppAPI\PrivacyController:privacySettings + methods: [POST] + +cust_api_resend_code: + path: /apiv2/resend_code + controller: App\Controller\CustomerAppAPI\AuthController:resendCode + methods: [POST] + +cust_api_location_support: + path: /apiv2/location_support + controller: App\Controller\CustomerAppAPI\LocationController:locationSupport + methods: [GET] + +cust_api_activate_warranty: + path: /apiv2/activate_warranty + controller: App\Controller\CustomerAppAPI\WarrantyController:activateWarranty + methods: [POST] + +cust_api_service_list: + path: /apiv2/services + controller: App\Controller\CustomerAppAPI\ServiceController:listServices + methods: [GET] + +cust_api_partner_info: + path: /apiv2/partners/{pid} + controller: App\Controller\CustomerAppAPI\PartnerController:getPartnerInformation + methods: [GET] + +cust_api_partner: + path: /apiv2/partners + controller: App\Controller\CustomerAppAPI\PartnerController:getClosestPartners + methods: [GET] + +cust_api_partner_review: + path: /apiv2/partners/{pid}/review + controller: App\Controller\CustomerAppAPI\PartnerController:reviewPartner + methods: [POST] + +cust_api_nearest_hub_slots: + path: /apiv2/hub_slots + controller: App\Controller\CustomerAppAPI\LocationController::getNearestHubAndSlots + methods: [GET] + +cust_api_new_jo_request: + path: /apiv2/new_job_order + controller: App\Controller\CustomerAppAPI\JobOrderController::newRequestJobOrder + methods: [POST] + +cust_api_version_check: + path: /apiv2/version_check + controller: App\Controller\CustomerAppAPI\AppController::versionCheck + methods: [GET] + +cust_api_schedule_option_status: + path: /apiv2/schedule_option_status + controller: App\Controller\CustomerAppAPI\ScheduleController::scheduleOptionStatus + methods: [GET] + +# paperless warranty / qr code +cust_api_warr_serial_check: + path: /apiv2/warranty/{serial} + controller: App\Controller\CustomerAppAPI\WarrantyController::warrantyCheck + methods: [GET] + +cust_api_warr_serial_register: + path: /apiv2/warranty/{serial} + controller: App\Controller\CustomerAppAPI\WarrantyController::warrantyRegister + methods: [POST] + +cust_api_jo_info: + path: /apiv2/job_order/{id}/info + controller: App\Controller\CustomerAppAPI\JobOrderController::getJobOrderInfo + methods: [GET] + +cust_api_ongoing_job_orders: + path: /apiv2/job_orders/ongoing + controller: App\Controller\CustomerAppAPI\JobOrderController::getAllOngoingJobOrders + methods: [GET] + +cust_api_ongoing_jo_count: + path: /apiv2/job_orders/ongoing/count + controller: App\Controller\CustomerAppAPI\JobOrderController::getOngoingJobOrderCount + methods: [GET] + +cust_api_new_location: + path: /apiv2/new_location + controller: App\Controller\CustomerAppAPI\LocationController::addLocation + methods: [POST] + +cust_api_locations: + path: /apiv2/locations + controller: App\Controller\CustomerAppAPI\LocationController::getLocations + methods: [GET] + +cust_api_cust_vehicle_remove: + path: /apiv2/vehicles/{id}/remove + controller: App\Controller\CustomerAppAPI\VehicleController::removeVehicle + methods: [POST] + +cust_api_latest_job_order: + path: /apiv2/job_order/latest + controller: App\Controller\CustomerAppAPI\JobOrderController::getLatestJobOrder + methods: [GET] + +cust_api_customer_hash_get: + path: /apiv2/customer_hash + controller: App\Controller\CustomerAppAPI\CustomerController::getCustomerHash + methods: [GET] + +#cust_api_completed_job_orders: +# path: /apiv2/job_orders/completed +# controller: App\Controller\CustomerAppAPI\JobOrderController::getCompletedJobOrders +# methods: [GET] diff --git a/src/Controller/CustomerAppAPI/CustomerController.php b/src/Controller/CustomerAppAPI/CustomerController.php index cfaf4833..e0b5ab5d 100644 --- a/src/Controller/CustomerAppAPI/CustomerController.php +++ b/src/Controller/CustomerAppAPI/CustomerController.php @@ -77,22 +77,6 @@ class CustomerController extends ApiController return new ApiResponse(true, '', $data); } - public function updateDeviceID(Request $req) - { - // validate params - $this->validateRequest($req, [ - 'device_id', - ]); - - $device_id = $req->request->get('device_id'); - $this->session->setDevicePushID($device_id); - - $this->em->flush(); - - // response - return new ApiResponse(); - } - protected function updateCustomerInfo(Request $req) { // create new customer if it's not there diff --git a/src/Controller/CustomerAppAPI/DeviceController.php b/src/Controller/CustomerAppAPI/DeviceController.php new file mode 100644 index 00000000..526c2541 --- /dev/null +++ b/src/Controller/CustomerAppAPI/DeviceController.php @@ -0,0 +1,25 @@ +validateRequest($req, [ + 'device_id', + ]); + + $device_id = $req->request->get('device_id'); + $this->session->setDevicePushID($device_id); + + $this->em->flush(); + + // response + return new ApiResponse(); + } +} diff --git a/src/Controller/CustomerAppAPI/EstimateController.php b/src/Controller/CustomerAppAPI/EstimateController.php new file mode 100644 index 00000000..95fdc770 --- /dev/null +++ b/src/Controller/CustomerAppAPI/EstimateController.php @@ -0,0 +1,125 @@ +debugRequest($req); + + // validate params + $this->validateRequest($req, [ + 'service_type', + 'cv_id', + // 'batt_id', + 'trade_in', + ]); + + // customer + $cust = $this->session->getCustomer(); + if ($cust == null) { + return new ApiResponse(false, 'No customer information found.'); + } + + // make invoice criteria + $icrit = new InvoiceCriteria(); + $icrit->setServiceType($req->request->get('service_type')); + + // check promo + $promo_id = $req->request->get('promo_id'); + if (!empty($promo_id)) { + $promo = $this->em->getRepository(Promo::class)->find($promo_id); + if ($promo == null) { + return new ApiResponse(false, 'Invalid promo id.'); + } + + // put in criteria + $icrit->addPromo($promo); + } + + // check customer vehicle + $cv = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id')); + if ($cv == null) { + return new ApiResponse(false, 'Invalid customer vehicle id.'); + } + $icrit->setCustomerVehicle($cv); + + // check if customer owns vehicle + if ($cust->getID() != $cv->getCustomer()->getID()) { + return new ApiResponse(false, 'Customer does not own vehicle.'); + } + + // check battery + $batt_id = $req->request->get('batt_id'); + if ($batt_id != null) { + $batt = $this->em->getRepository(Battery::class)->find($batt_id); + if ($batt == null) { + return new ApiResponse(false, 'Invalid battery id.'); + } + } else + $batt = null; + + /* + // put battery in criteria + $icrit->addBattery($batt); + */ + + // check trade-in + // only allow motolite, other, none + $trade_in = $req->request->get('trade_in'); + 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); + + // make invoice json data + $data = [ + 'total_price' => (float) $invoice->getTotalPrice(), + 'vat_ex_price' => (float) $invoice->getVATExclusivePrice(), + 'vat' => (float) $invoice->getVAT(), + 'discount' => (float) $invoice->getDiscount(), + 'trade_in' => (float) $invoice->getTradeIn(), + ]; + $items = $invoice->getItems(); + $items_data = []; + foreach ($items as $item) { + $my_data = [ + 'title' => $item->getTitle(), + 'qty' => (int) $item->getQuantity() + 0, + 'price' => (float) $item->getPrice() + 0.0, + ]; + + $item_batt = $item->getBattery(); + if ($item_batt != null) { + $my_data['image_url'] = $this->getBatteryImageURL($req, $item_batt); + } + + $items_data[] = $my_data; + } + + $data['items'] = $items_data; + + // error_log(print_r($data, true)); + + // response + return new ApiResponse(true, '', $data); + } +} diff --git a/src/Controller/CustomerAppAPI/JobOrderController.php b/src/Controller/CustomerAppAPI/JobOrderController.php index 28c71a89..94f456ac 100644 --- a/src/Controller/CustomerAppAPI/JobOrderController.php +++ b/src/Controller/CustomerAppAPI/JobOrderController.php @@ -38,118 +38,6 @@ use DateTime; class JobOrderController extends ApiController { - public function getEstimate(Request $req, InvoiceGeneratorInterface $ic) - { - // $this->debugRequest($req); - - // validate params - $this->validateRequest($req, [ - 'service_type', - 'cv_id', - // 'batt_id', - 'trade_in', - ]); - - // customer - $cust = $this->session->getCustomer(); - if ($cust == null) { - return new ApiResponse(false, 'No customer information found.'); - } - - // make invoice criteria - $icrit = new InvoiceCriteria(); - $icrit->setServiceType($req->request->get('service_type')); - - // check promo - $promo_id = $req->request->get('promo_id'); - if (!empty($promo_id)) { - $promo = $this->em->getRepository(Promo::class)->find($promo_id); - if ($promo == null) { - return new ApiResponse(false, 'Invalid promo id.'); - } - - // put in criteria - $icrit->addPromo($promo); - } - - // check customer vehicle - $cv = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id')); - if ($cv == null) { - return new ApiResponse(false, 'Invalid customer vehicle id.'); - } - $icrit->setCustomerVehicle($cv); - - // check if customer owns vehicle - if ($cust->getID() != $cv->getCustomer()->getID()) { - return new ApiResponse(false, 'Customer does not own vehicle.'); - } - - // check battery - $batt_id = $req->request->get('batt_id'); - if ($batt_id != null) { - $batt = $this->em->getRepository(Battery::class)->find($batt_id); - if ($batt == null) { - return new ApiResponse(false, 'Invalid battery id.'); - } - } else - $batt = null; - - /* - // put battery in criteria - $icrit->addBattery($batt); - */ - - // check trade-in - // only allow motolite, other, none - $trade_in = $req->request->get('trade_in'); - 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); - - // make invoice json data - $data = [ - 'total_price' => (float) $invoice->getTotalPrice(), - 'vat_ex_price' => (float) $invoice->getVATExclusivePrice(), - 'vat' => (float) $invoice->getVAT(), - 'discount' => (float) $invoice->getDiscount(), - 'trade_in' => (float) $invoice->getTradeIn(), - ]; - $items = $invoice->getItems(); - $items_data = []; - foreach ($items as $item) { - $my_data = [ - 'title' => $item->getTitle(), - 'qty' => (int) $item->getQuantity() + 0, - 'price' => (float) $item->getPrice() + 0.0, - ]; - - $item_batt = $item->getBattery(); - if ($item_batt != null) { - $my_data['image_url'] = $this->getBatteryImageURL($req, $item_batt); - } - - $items_data[] = $my_data; - } - - $data['items'] = $items_data; - - // error_log(print_r($data, true)); - - // response - return new ApiResponse(true, '', $data); - } - public function getOngoing(Request $req) { // validate params @@ -163,7 +51,7 @@ class JobOrderController extends ApiController /* // check if we have an ongoing job order - $ongoing_jos = $em->getRepository(JobOrder::class)->findBy([ + $ongoing_jos = $this->em->getRepository(JobOrder::class)->findBy([ 'customer' => $cust, 'status' => [JOStatus::PENDING, JOStatus::RIDER_ASSIGN, JOStatus::IN_TRANSIT, JOStatus::ASSIGNED, JOStatus::IN_PROGRESS], ]); @@ -993,6 +881,329 @@ class JobOrderController extends ApiController ]); } + // TODO: remove later + // mobile app no longer calls this + public function requestJobOrder( + Request $req, + InvoiceGeneratorInterface $ic, + GeofenceTracker $geo, + MapTools $map_tools, + InventoryManager $im, + MQTTClient $mclient, + RiderAssignmentHandlerInterface $rah, + PromoLogger $promo_logger, + HubSelector $hub_select, + HubDistributor $hub_dist, + HubFilterLogger $hub_filter_logger, + HubFilteringGeoChecker $hub_geofence + ) { + // validate params + $this->validateRequest($req, [ + 'service_type', + 'cv_id', + // 'batt_id', + 'trade_in', + 'long', + 'lat', + 'warranty', + 'mode_of_payment', + ]); + + // 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 + return new ApiResponse(false, $this->getGeoErrorMessage()); + } + + $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')); + + // customer + $cust = $this->session->getCustomer(); + if ($cust == null) { + return new ApiResponse(false, 'No customer information found.'); + } + $jo->setCustomer($cust); + + // validate service type + $stype = $req->request->get('service_type'); + if (!ServiceType::validate($stype)) { + return new ApiResponse(false, 'Invalid service type.'); + } + $jo->setServiceType($stype); + + // validate warranty + $warr = $req->request->get('warranty'); + if (!WarrantyClass::validate($warr)) { + return new ApiResponse(false, 'Invalid warranty class.'); + } + $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 = $this->em->getRepository(Promo::class)->find($promo_id); + if ($promo == null) { + return new ApiResponse(false, 'Invalid promo id.'); + } + + // put in criteria + $icrit->addPromo($promo); + } + + // check customer vehicle + $cv = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id')); + if ($cv == null) { + return new ApiResponse(false, 'Invalid customer vehicle id.'); + } + $icrit->setCustomerVehicle($cv); + $jo->setCustomerVehicle($cv); + + // check if customer owns vehicle + if ($cust->getID() != $cv->getCustomer()->getID()) { + return new ApiResponse(false, 'Customer does not own vehicle.'); + } + + // check battery + $batt_id = $req->request->get('batt_id'); + if ($batt_id != null) { + $batt = $this->em->getRepository(Battery::class)->find($batt_id); + if ($batt == null) { + return new ApiResponse(false, 'Invalid battery id.'); + } + } 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); + + // set more hub criteria fields + $hub_criteria = new HubCriteria(); + $hub_criteria->setPoint($jo->getCoordinates()); + + // get distance limit for mobile from env + $limit_distance = $_ENV['CUST_DISTANCE_LIMIT']; + + // set distance limit + $hub_criteria->setLimitDistance($limit_distance); + + if ($hub_geofence->isCovered($long, $lat)) { + // TODO: set this properly, since the other flags + // are on default values. + // if true, set other values for HubCriteria + // error_log('Area is covered by hub filtering'); + $hub_criteria->setJoType($jo->getServiceType()) + ->setPaymentMethod($jo->getModeOfPayment()) + ->setRoundRobin(true); + } + + // add battery to items + $sku = $batt->getSAPCode(); + if (!empty($sku)) + $hub_criteria->addItem($batt->getSAPCode(), 1); + + // get customer id. No JO id at this point + $customer_id = $cust->getID(); + + $hub_criteria->setCustomerId($customer_id); + + // find nearest hubs + $nearest_hubs = $hub_select->find($hub_criteria); + + $assigned_rider = null; + if (!empty($nearest_hubs)) { + // go through the hub list, find the nearest hub + // with an available rider + //error_log('found nearest hub ' . $nearest_hub->getID()); + foreach ($nearest_hubs as $nearest_hub) { + $available_riders = $nearest_hub['hub']->getAvailableRiders(); + if (count($available_riders) >= 1) { + if (count($available_riders) == 1) { + $assigned_rider = $available_riders[0]; + } else { + // 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); + } + + $jo->setHub($nearest_hub['hub']); + $jo->setRider($assigned_rider); + $jo->setStatus(JOStatus::ASSIGNED); + $jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED); + + $assigned_rider->setAvailable(false); + + // set rider's current job order + $assigned_rider->setCurrentJobOrder($jo); + + // update redis hub_jo_count for hub + $hub_dist->incrementJoCountForHub($nearest_hub['hub']); + + // break out of loop + break; + } else { + // log hub into hub_filter_log + $hub_filter_logger->logFilteredHub($nearest_hub['hub'], 'no_available_rider', null, $cust->getID()); + // continue to go through list to find hub with an available rider + } + } + } + + $this->em->persist($jo); + $this->em->persist($invoice); + + // add event log for JO + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::CREATE) + ->setJobOrder($jo); + $this->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); + + $this->em->persist($hub_assign_event); + + $rider_assign_event = new JOEvent(); + $rider_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_ASSIGN) + ->setJobOrder($jo); + + $this->em->persist($rider_assign_event); + + // user mqtt event + $payload = [ + 'event' => 'outlet_assign' + ]; + $mclient->sendEvent($jo, $payload); + + $rah->assignJobOrder($jo, $jo->getRider()); + } + + $this->em->flush(); + + // make invoice json data + $invoice_data = [ + 'total_price' => $invoice->getTotalPrice(), + 'vat_ex_price' => (float) $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; + + // check service type + if ($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) { + $customer = $cv->getCustomer(); + $customer_tags = $customer->getCustomerTagObjects(); + if (!empty($customer_tags)) { + foreach ($customer_tags as $customer_tag) { + // TODO: not too comfy with this being hardcoded + if ($customer_tag->getID() == $invoice->getUsedCustomerTagId()) { + // remove associated entity + $customer->removeCustomerTag($customer_tag); + + // log the availment of promo from customer + $created_by = $req->query->get('api_key');; + $cust_id = $jo->getCustomer()->getID(); + $cust_fname = $jo->getCustomer()->getFirstName(); + $cust_lname = $jo->getCustomer()->getLastName(); + $jo_id = $jo->getID(); + $invoice_id = $jo->getInvoice()->getID(); + // TODO: check if we store total price of invoice or just the discounted amount + $amount = $jo->getInvoice()->getTotalPrice(); + $promo_logger->logPromoInfo( + $created_by, + $cust_id, + $cust_fname, + $cust_lname, + $jo_id, + $invoice_id, + $amount + ); + } + } + } + } + + // response + return new ApiResponse(true, '', [ + 'jo_id' => $jo->getID(), + 'invoice' => $invoice_data, + ]); + } + // commenting it out. Modify the getJOHistory instead to just get the fulfilled // and cancelled job orders, since ongoing is not yet part of history /*