diff --git a/config/routes/api.yaml b/config/routes/api.yaml index a47df74b..50e50957 100644 --- a/config/routes/api.yaml +++ b/config/routes/api.yaml @@ -100,6 +100,11 @@ api_jo_history: controller: App\Controller\APIController:getJOHistory methods: [GET] +api_jo_invoice: + path: /api/job_order/invoice + controller: App\Controller\APIController:getJOInvoice + methods: [GET] + api_device_id: path: /api/device_id controller: App\Controller\APIController:updateDeviceID diff --git a/config/routes/rider_api.yaml b/config/routes/rider_api.yaml index 2f61be21..bd38c492 100644 --- a/config/routes/rider_api.yaml +++ b/config/routes/rider_api.yaml @@ -40,6 +40,11 @@ rapi_payment: controller: App\Controller\RAPIController::payment methods: [POST] +rapi_hub_arrive: + path: /rapi/hub_arrive + controller: App\Controller\RAPIController::hubArrive + methods: [POST] + rapi_promos: path: /rapi/promos controller: App\Controller\RAPIController::getPromos diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 7c05464d..a61ea970 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -20,6 +20,7 @@ use App\Ramcar\WarrantyClass; use App\Ramcar\APIRiderStatus; use App\Ramcar\TransactionOrigin; use App\Ramcar\TradeInType; +use App\Ramcar\JOEventType; use App\Service\InvoiceCreator; use App\Service\RisingTideGateway; @@ -34,6 +35,7 @@ use App\Entity\JobOrder; use App\Entity\Promo; use App\Entity\Battery; use App\Entity\RiderRating; +use App\Entity\JOEvent; use DateTime; @@ -193,6 +195,11 @@ class APIController extends Controller return $res->getReturnResponse(); } + protected function generateConfirmCode() + { + return sprintf("%06d", mt_rand(100000, 999999)); + } + public function confirmNumber(RisingTideGateway $rt, Request $req) { // check parameters @@ -213,9 +220,9 @@ class APIController extends Controller // TODO: validate phone number - // TODO: generate code and save - // use '123456' for now - $code = '123456'; + // generate code and save + // $code = '123456'; + $code = $this->generateConfirmCode(); $this->session->setConfirmCode($code) ->setPhoneNumber($phone_number); $em->flush(); @@ -314,6 +321,8 @@ class APIController extends Controller $data = [ 'first_name' => $cust->getFirstName(), 'last_name' => $cust->getLastName(), + 'priv_third_party' => $cust->getPrivacyThirdParty(), + 'priv_promo' => $cust->getPrivacyPromo(), ]; $res->setData($data); @@ -883,6 +892,14 @@ class APIController extends Controller $em->persist($jo); $em->persist($invoice); + + // add event log + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::CREATE) + ->setJobOrder($jo); + $em->persist($event); + $em->flush(); // make invoice json data @@ -1088,29 +1105,26 @@ class APIController extends Controller $jo = $ongoing_jos[0]; $dest = $jo->getCoordinates(); + $data = [ + 'jo_id' => $jo->getID(), + 'service_type' => $jo->getServiceType(), + 'destination' => [ + 'long' => $dest->getLongitude(), + 'lat' => $dest->getLatitude(), + ], + 'delivery_address' => $jo->getDeliveryAddress(), + 'delivery_instructions' => $jo->getDeliveryInstructions(), + ]; + switch ($jo->getStatus()) { case JOStatus::PENDING: - $res->setData([ - 'status' => APIRiderStatus::OUTLET_ASSIGN, - 'jo_id' => $jo->getID(), - 'service_type' => $jo->getServiceType(), - 'destination' => [ - 'long' => $dest->getLongitude(), - 'lat' => $dest->getLatitude(), - ], - ]); + $data['status'] = APIRiderStatus::OUTLET_ASSIGN; + $res->setData($data); return $res->getReturnResponse(); case JOStatus::RIDER_ASSIGN: - $res->setData([ - 'status' => APIRiderStatus::RIDER_ASSIGN, - 'jo_id' => $jo->getID(), - 'service_type' => $jo->getServiceType(), - 'destination' => [ - 'long' => $dest->getLongitude(), - 'lat' => $dest->getLatitude(), - ], - ]); + $data['status'] = APIRiderStatus::RIDER_ASSIGN; + $res->setData($data); return $res->getReturnResponse(); case JOStatus::ASSIGNED: case JOStatus::IN_TRANSIT: @@ -1123,27 +1137,20 @@ class APIController extends Controller $image_url = $url_prefix . '/assets/images/user.gif'; if ($rider->getImageFile() != null) $image_url = $url_prefix . '/uploads/' . $rider->getImageFile(); - $res->setData([ - 'status' => APIRiderStatus::RIDER_PICK_UP, - 'jo_id' => $jo->getID(), - 'service_type' => $jo->getServiceType(), - 'destination' => [ - 'long' => $dest->getLongitude(), - 'lat' => $dest->getLatitude(), - ], - // TODO: fix this to actual location of rider - 'rider' => [ - 'id' => $rider->getID(), - 'name' => $rider->getFullName(), - 'plate_num' => $rider->getPlateNumber(), - 'contact_num' => $rider->getContactNumber(), - 'image_url' => $image_url, - 'location' => [ - 'long' => $coord->getLongitude(), - 'lat' => $coord->getLatitude() - ] + + $data['status'] = APIRiderStatus::RIDER_PICK_UP; + // TODO: fix this to actual location of rider + $data['rider'] = [ + 'id' => $rider->getID(), + 'name' => $rider->getFullName(), + 'plate_num' => $rider->getPlateNumber(), + 'contact_num' => $rider->getContactNumber(), + 'image_url' => $image_url, + 'location' => [ + 'long' => $coord->getLongitude(), + 'lat' => $coord->getLatitude() ] - ]); + ]; return $res->getReturnResponse(); } @@ -1273,6 +1280,81 @@ class APIController extends Controller return $res->getReturnResponse(); } + public function getJOInvoice(Request $req) + { + $required_params = [ + 'jo_id', + ]; + $em = $this->getDoctrine()->getManager(); + $res = $this->checkParamsAndKey($req, $em, $required_params); + if ($res->isError()) + return $res->getReturnResponse(); + + // get job order + $jo_id = $req->query->get('jo_id'); + $jo = $em->getRepository(JobOrder::class)->find($jo_id); + if ($jo == null) + { + $res->setError(true) + ->setErrorMessage('No job order found'); + return $res->getReturnResponse(); + } + + // get customer + $cust = $this->session->getCustomer(); + if ($cust == null) + { + $res->setError(true) + ->setErrorMessage('No customer information found'); + return $res->getReturnResponse(); + } + + // check that the customer owns the job order + $jo_cust = $jo->getCustomer(); + if ($jo_cust->getID() != $cust->getID()) + { + $res->setError(true) + ->setErrorMessage('Job order was not initiated by customer'); + return $res->getReturnResponse(); + } + + $inv = $jo->getInvoice(); + + // invoice items + $inv_items = []; + foreach ($inv->getItems() as $item) + { + $item_batt = $item->getBattery(); + if ($item_batt == null) + $batt_id = null; + else + $batt_id = $item_batt->getID(); + + $inv_items[] = [ + 'id' => $item->getID(), + 'title' => $item->getTitle(), + 'qty' => $item->getQuantity(), + 'price' => $item->getPrice(), + 'batt_id' => $batt_id, + ]; + } + + $data = [ + 'invoice' => [ + 'discount' => $inv->getDiscount(), + 'trade_in' => $inv->getTradeIn(), + 'total_price' => $inv->getTotalPrice(), + 'vat' => $inv->getVat(), + 'items' => $inv_items, + ], + ]; + + + $res->setData($data); + + return $res->getReturnResponse(); + } + public function cancelJobOrder(Request $req, MQTTClient $mclient) { $required_params = [ @@ -1316,11 +1398,13 @@ class APIController extends Controller $cancel_reason = $req->request->get('reason'); $jo->cancel($cancel_reason); - /* - $jo->setStatus(JOStatus::CANCELLED) - ->setDateCancel(new DateTime()) - ->setCancelReason($cancel_reason); - */ + + // add event log + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::CANCEL) + ->setJobOrder($jo); + $em->persist($event); $em->flush(); diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 401a7612..7068d730 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -597,7 +597,8 @@ class JobOrderController extends BaseController JOStatus::PENDING, JOStatus::RIDER_ASSIGN, JOStatus::ASSIGNED, - JOStatus::IN_PROGRESS + JOStatus::IN_PROGRESS, + JOStatus::IN_TRANSIT, ]; break; case 'all': diff --git a/src/Controller/RAPIController.php b/src/Controller/RAPIController.php index 0fa9f31d..37ccdcc2 100644 --- a/src/Controller/RAPIController.php +++ b/src/Controller/RAPIController.php @@ -23,6 +23,7 @@ use App\Ramcar\TransactionOrigin; use App\Ramcar\TradeInType; use App\Ramcar\InvoiceStatus; use App\Ramcar\ModeOfPayment; +use App\Ramcar\JOEventType; use App\Service\InvoiceCreator; use App\Service\MQTTClient; @@ -40,6 +41,7 @@ use App\Entity\BatterySize; use App\Entity\RiderRating; use App\Entity\Rider; use App\Entity\User; +use App\Entity\JOEvent; use DateTime; @@ -464,11 +466,19 @@ class RAPIController extends Controller // set jo status to in transit $jo->setStatus(JOStatus::IN_TRANSIT); - $em->flush(); // TODO: send mqtt event (?) - // TODO: add event + // add event log + $rider = $this->session->getRider(); + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_ACCEPT) + ->setJobOrder($jo) + ->setRider($rider); + $em->persist($event); + + $em->flush(); return $res->getReturnResponse(); } @@ -481,17 +491,18 @@ class RAPIController extends Controller if ($res->isError()) return $res->getReturnResponse(); - /* - // set jo status to cancelled - // TODO: set reason - $jo->setStatus(JOStatus::CANCELLED) - ->setDateCancel(new DateTime()); + // $jo->cancel("rider cancelled"); + // requeue it, instead of cancelling it + $jo->requeue(); - // make rider available - $this->session->getRider()->setAvailable(true); - */ - - $jo->cancel("rider cancelled"); + // add event log + $rider = $this->session->getRider(); + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::REQUEUE) + ->setJobOrder($jo) + ->setRider($rider); + $em->persist($event); $em->flush(); @@ -504,7 +515,6 @@ class RAPIController extends Controller $mclient->sendEvent($jo, $payload); - // TODO: add event return $res->getReturnResponse(); } @@ -521,6 +531,16 @@ class RAPIController extends Controller // set jo status to in progress $jo->setStatus(JOStatus::IN_PROGRESS); + + // add event log + $rider = $this->session->getRider(); + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_ARRIVE) + ->setJobOrder($jo) + ->setRider($rider); + $em->persist($event); + $em->flush(); // send mqtt event @@ -538,7 +558,30 @@ class RAPIController extends Controller ]; $mclient->sendEvent($jo, $payload); - // TODO: add event + + return $res->getReturnResponse(); + } + + public function hubArrive(Request $req) + { + $required_params = []; + $em = $this->getDoctrine()->getManager(); + $res = $this->checkParamsAndKey($req, $em, $required_params); + if ($res->isError()) + return $res->getReturnResponse(); + + // are we logged in? + if (!$this->session->hasRider()) + { + $res->setError(true) + ->setErrorMessage('No logged in rider.'); + return $res->getReturnResponse(); + } + + // TODO: tag rider as available + + $em->flush(); + return $res->getReturnResponse(); } @@ -560,6 +603,17 @@ class RAPIController extends Controller */ $jo->fulfill(); + // add event log + $rider = $this->session->getRider(); + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::FULFILL) + ->setJobOrder($jo) + ->setRider($rider); + $em->persist($event); + + // TODO: tag rider as unavailable + $em->flush(); // send mqtt event (fulfilled) @@ -576,9 +630,6 @@ class RAPIController extends Controller ]; $mclient->sendEvent($jo, $payload); - - // TODO: add event - return $res->getReturnResponse(); } @@ -772,10 +823,17 @@ class RAPIController extends Controller // save invoice $jo->setInvoice($invoice); $em->persist($invoice); + + // add event log + $rider = $this->session->getRider(); + $event = new JOEvent(); + $event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_EDIT) + ->setJobOrder($jo) + ->setRider($rider); + $em->persist($event); + $em->flush(); - - // TODO: add event - // TODO: send mqtt event (?) return $res->getReturnResponse(); diff --git a/src/Entity/JOEvent.php b/src/Entity/JOEvent.php index 7d0d5d31..ee051712 100644 --- a/src/Entity/JOEvent.php +++ b/src/Entity/JOEvent.php @@ -52,6 +52,13 @@ class JOEvent */ protected $job_order; + // rider related to the event + /** + * @ORM\ManyToOne(targetEntity="Rider", inversedBy="events") + * @ORM\JoinColumn(name="rider_id", referencedColumnName="id", nullable=true) + */ + protected $rider; + public function __construct() { $this->date_create = new DateTime(); @@ -115,4 +122,15 @@ class JOEvent { return $this->job_order; } + + public function setRider(Rider $rider) + { + $this->rider = $rider; + return $this; + } + + public function getRider() + { + return $this->rider; + } } diff --git a/src/Entity/JobOrder.php b/src/Entity/JobOrder.php index 122df4df..e3e69688 100644 --- a/src/Entity/JobOrder.php +++ b/src/Entity/JobOrder.php @@ -661,6 +661,14 @@ class JobOrder $rider->setAvailable(); } + public function requeue() + { + // set status back to 'for rider assignment' + $this->setStatus(JOStatus::RIDER_ASSIGN); + + $this->makeRiderAvailable(); + } + public function cancel($reason) { // set status to cancelled diff --git a/src/Ramcar/JOEventType.php b/src/Ramcar/JOEventType.php index defa6d3b..3929c24e 100644 --- a/src/Ramcar/JOEventType.php +++ b/src/Ramcar/JOEventType.php @@ -10,6 +10,10 @@ class JOEventType extends NameValue const CANCEL = 'cancel'; const FULFILL = 'fulfill'; const OPEN_EDIT = 'open_edit'; + const REQUEUE = 'requeue'; + const RIDER_ACCEPT = 'accept'; + const RIDER_ARRIVE = 'arrive'; + const RIDER_EDIT = 'rider_edit'; const COLLECTION = [ 'create' => 'Created', @@ -18,5 +22,9 @@ class JOEventType extends NameValue 'cancel' => 'Cancelled', 'fulfill' => 'Fulfilled', 'open_edit' => 'Open Edit', + 'requeue' => 'Requeue', + 'accept' => 'Rider Accept', + 'arrive' => 'Rider Arrive', + 'rider_edit' => 'Rider Edit', ]; } diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 349c2d68..f566ab00 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -739,7 +739,7 @@