Merge branch '162-phase-2-changes' into 'master'

Resolve "Phase 2 changes"

Closes #162

See merge request jankstudio/resq!167
This commit is contained in:
Kendrick Chan 2018-08-10 02:21:48 +00:00
commit e5a6fa17f8
9 changed files with 255 additions and 68 deletions

View file

@ -100,6 +100,11 @@ api_jo_history:
controller: App\Controller\APIController:getJOHistory controller: App\Controller\APIController:getJOHistory
methods: [GET] methods: [GET]
api_jo_invoice:
path: /api/job_order/invoice
controller: App\Controller\APIController:getJOInvoice
methods: [GET]
api_device_id: api_device_id:
path: /api/device_id path: /api/device_id
controller: App\Controller\APIController:updateDeviceID controller: App\Controller\APIController:updateDeviceID

View file

@ -40,6 +40,11 @@ rapi_payment:
controller: App\Controller\RAPIController::payment controller: App\Controller\RAPIController::payment
methods: [POST] methods: [POST]
rapi_hub_arrive:
path: /rapi/hub_arrive
controller: App\Controller\RAPIController::hubArrive
methods: [POST]
rapi_promos: rapi_promos:
path: /rapi/promos path: /rapi/promos
controller: App\Controller\RAPIController::getPromos controller: App\Controller\RAPIController::getPromos

View file

@ -20,6 +20,7 @@ use App\Ramcar\WarrantyClass;
use App\Ramcar\APIRiderStatus; use App\Ramcar\APIRiderStatus;
use App\Ramcar\TransactionOrigin; use App\Ramcar\TransactionOrigin;
use App\Ramcar\TradeInType; use App\Ramcar\TradeInType;
use App\Ramcar\JOEventType;
use App\Service\InvoiceCreator; use App\Service\InvoiceCreator;
use App\Service\RisingTideGateway; use App\Service\RisingTideGateway;
@ -34,6 +35,7 @@ use App\Entity\JobOrder;
use App\Entity\Promo; use App\Entity\Promo;
use App\Entity\Battery; use App\Entity\Battery;
use App\Entity\RiderRating; use App\Entity\RiderRating;
use App\Entity\JOEvent;
use DateTime; use DateTime;
@ -193,6 +195,11 @@ class APIController extends Controller
return $res->getReturnResponse(); return $res->getReturnResponse();
} }
protected function generateConfirmCode()
{
return sprintf("%06d", mt_rand(100000, 999999));
}
public function confirmNumber(RisingTideGateway $rt, Request $req) public function confirmNumber(RisingTideGateway $rt, Request $req)
{ {
// check parameters // check parameters
@ -213,9 +220,9 @@ class APIController extends Controller
// TODO: validate phone number // TODO: validate phone number
// TODO: generate code and save // generate code and save
// use '123456' for now // $code = '123456';
$code = '123456'; $code = $this->generateConfirmCode();
$this->session->setConfirmCode($code) $this->session->setConfirmCode($code)
->setPhoneNumber($phone_number); ->setPhoneNumber($phone_number);
$em->flush(); $em->flush();
@ -314,6 +321,8 @@ class APIController extends Controller
$data = [ $data = [
'first_name' => $cust->getFirstName(), 'first_name' => $cust->getFirstName(),
'last_name' => $cust->getLastName(), 'last_name' => $cust->getLastName(),
'priv_third_party' => $cust->getPrivacyThirdParty(),
'priv_promo' => $cust->getPrivacyPromo(),
]; ];
$res->setData($data); $res->setData($data);
@ -883,6 +892,14 @@ class APIController extends Controller
$em->persist($jo); $em->persist($jo);
$em->persist($invoice); $em->persist($invoice);
// add event log
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CREATE)
->setJobOrder($jo);
$em->persist($event);
$em->flush(); $em->flush();
// make invoice json data // make invoice json data
@ -1088,29 +1105,26 @@ class APIController extends Controller
$jo = $ongoing_jos[0]; $jo = $ongoing_jos[0];
$dest = $jo->getCoordinates(); $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()) switch ($jo->getStatus())
{ {
case JOStatus::PENDING: case JOStatus::PENDING:
$res->setData([ $data['status'] = APIRiderStatus::OUTLET_ASSIGN;
'status' => APIRiderStatus::OUTLET_ASSIGN, $res->setData($data);
'jo_id' => $jo->getID(),
'service_type' => $jo->getServiceType(),
'destination' => [
'long' => $dest->getLongitude(),
'lat' => $dest->getLatitude(),
],
]);
return $res->getReturnResponse(); return $res->getReturnResponse();
case JOStatus::RIDER_ASSIGN: case JOStatus::RIDER_ASSIGN:
$res->setData([ $data['status'] = APIRiderStatus::RIDER_ASSIGN;
'status' => APIRiderStatus::RIDER_ASSIGN, $res->setData($data);
'jo_id' => $jo->getID(),
'service_type' => $jo->getServiceType(),
'destination' => [
'long' => $dest->getLongitude(),
'lat' => $dest->getLatitude(),
],
]);
return $res->getReturnResponse(); return $res->getReturnResponse();
case JOStatus::ASSIGNED: case JOStatus::ASSIGNED:
case JOStatus::IN_TRANSIT: case JOStatus::IN_TRANSIT:
@ -1123,27 +1137,20 @@ class APIController extends Controller
$image_url = $url_prefix . '/assets/images/user.gif'; $image_url = $url_prefix . '/assets/images/user.gif';
if ($rider->getImageFile() != null) if ($rider->getImageFile() != null)
$image_url = $url_prefix . '/uploads/' . $rider->getImageFile(); $image_url = $url_prefix . '/uploads/' . $rider->getImageFile();
$res->setData([
'status' => APIRiderStatus::RIDER_PICK_UP, $data['status'] = APIRiderStatus::RIDER_PICK_UP;
'jo_id' => $jo->getID(), // TODO: fix this to actual location of rider
'service_type' => $jo->getServiceType(), $data['rider'] = [
'destination' => [ 'id' => $rider->getID(),
'long' => $dest->getLongitude(), 'name' => $rider->getFullName(),
'lat' => $dest->getLatitude(), 'plate_num' => $rider->getPlateNumber(),
], 'contact_num' => $rider->getContactNumber(),
// TODO: fix this to actual location of rider 'image_url' => $image_url,
'rider' => [ 'location' => [
'id' => $rider->getID(), 'long' => $coord->getLongitude(),
'name' => $rider->getFullName(), 'lat' => $coord->getLatitude()
'plate_num' => $rider->getPlateNumber(),
'contact_num' => $rider->getContactNumber(),
'image_url' => $image_url,
'location' => [
'long' => $coord->getLongitude(),
'lat' => $coord->getLatitude()
]
] ]
]); ];
return $res->getReturnResponse(); return $res->getReturnResponse();
} }
@ -1273,6 +1280,81 @@ class APIController extends Controller
return $res->getReturnResponse(); 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) public function cancelJobOrder(Request $req, MQTTClient $mclient)
{ {
$required_params = [ $required_params = [
@ -1316,11 +1398,13 @@ class APIController extends Controller
$cancel_reason = $req->request->get('reason'); $cancel_reason = $req->request->get('reason');
$jo->cancel($cancel_reason); $jo->cancel($cancel_reason);
/*
$jo->setStatus(JOStatus::CANCELLED) // add event log
->setDateCancel(new DateTime()) $event = new JOEvent();
->setCancelReason($cancel_reason); $event->setDateHappen(new DateTime())
*/ ->setTypeID(JOEventType::CANCEL)
->setJobOrder($jo);
$em->persist($event);
$em->flush(); $em->flush();

View file

@ -597,7 +597,8 @@ class JobOrderController extends BaseController
JOStatus::PENDING, JOStatus::PENDING,
JOStatus::RIDER_ASSIGN, JOStatus::RIDER_ASSIGN,
JOStatus::ASSIGNED, JOStatus::ASSIGNED,
JOStatus::IN_PROGRESS JOStatus::IN_PROGRESS,
JOStatus::IN_TRANSIT,
]; ];
break; break;
case 'all': case 'all':

View file

@ -23,6 +23,7 @@ use App\Ramcar\TransactionOrigin;
use App\Ramcar\TradeInType; use App\Ramcar\TradeInType;
use App\Ramcar\InvoiceStatus; use App\Ramcar\InvoiceStatus;
use App\Ramcar\ModeOfPayment; use App\Ramcar\ModeOfPayment;
use App\Ramcar\JOEventType;
use App\Service\InvoiceCreator; use App\Service\InvoiceCreator;
use App\Service\MQTTClient; use App\Service\MQTTClient;
@ -40,6 +41,7 @@ use App\Entity\BatterySize;
use App\Entity\RiderRating; use App\Entity\RiderRating;
use App\Entity\Rider; use App\Entity\Rider;
use App\Entity\User; use App\Entity\User;
use App\Entity\JOEvent;
use DateTime; use DateTime;
@ -464,11 +466,19 @@ class RAPIController extends Controller
// set jo status to in transit // set jo status to in transit
$jo->setStatus(JOStatus::IN_TRANSIT); $jo->setStatus(JOStatus::IN_TRANSIT);
$em->flush();
// TODO: send mqtt event (?) // 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(); return $res->getReturnResponse();
} }
@ -481,17 +491,18 @@ class RAPIController extends Controller
if ($res->isError()) if ($res->isError())
return $res->getReturnResponse(); return $res->getReturnResponse();
/* // $jo->cancel("rider cancelled");
// set jo status to cancelled // requeue it, instead of cancelling it
// TODO: set reason $jo->requeue();
$jo->setStatus(JOStatus::CANCELLED)
->setDateCancel(new DateTime());
// make rider available // add event log
$this->session->getRider()->setAvailable(true); $rider = $this->session->getRider();
*/ $event = new JOEvent();
$event->setDateHappen(new DateTime())
$jo->cancel("rider cancelled"); ->setTypeID(JOEventType::REQUEUE)
->setJobOrder($jo)
->setRider($rider);
$em->persist($event);
$em->flush(); $em->flush();
@ -504,7 +515,6 @@ class RAPIController extends Controller
$mclient->sendEvent($jo, $payload); $mclient->sendEvent($jo, $payload);
// TODO: add event
return $res->getReturnResponse(); return $res->getReturnResponse();
} }
@ -521,6 +531,16 @@ class RAPIController extends Controller
// set jo status to in progress // set jo status to in progress
$jo->setStatus(JOStatus::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(); $em->flush();
// send mqtt event // send mqtt event
@ -538,7 +558,30 @@ class RAPIController extends Controller
]; ];
$mclient->sendEvent($jo, $payload); $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(); return $res->getReturnResponse();
} }
@ -560,6 +603,17 @@ class RAPIController extends Controller
*/ */
$jo->fulfill(); $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(); $em->flush();
// send mqtt event (fulfilled) // send mqtt event (fulfilled)
@ -576,9 +630,6 @@ class RAPIController extends Controller
]; ];
$mclient->sendEvent($jo, $payload); $mclient->sendEvent($jo, $payload);
// TODO: add event
return $res->getReturnResponse(); return $res->getReturnResponse();
} }
@ -772,10 +823,17 @@ class RAPIController extends Controller
// save invoice // save invoice
$jo->setInvoice($invoice); $jo->setInvoice($invoice);
$em->persist($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(); $em->flush();
// TODO: add event
// TODO: send mqtt event (?) // TODO: send mqtt event (?)
return $res->getReturnResponse(); return $res->getReturnResponse();

View file

@ -52,6 +52,13 @@ class JOEvent
*/ */
protected $job_order; 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() public function __construct()
{ {
$this->date_create = new DateTime(); $this->date_create = new DateTime();
@ -115,4 +122,15 @@ class JOEvent
{ {
return $this->job_order; return $this->job_order;
} }
public function setRider(Rider $rider)
{
$this->rider = $rider;
return $this;
}
public function getRider()
{
return $this->rider;
}
} }

View file

@ -661,6 +661,14 @@ class JobOrder
$rider->setAvailable(); $rider->setAvailable();
} }
public function requeue()
{
// set status back to 'for rider assignment'
$this->setStatus(JOStatus::RIDER_ASSIGN);
$this->makeRiderAvailable();
}
public function cancel($reason) public function cancel($reason)
{ {
// set status to cancelled // set status to cancelled

View file

@ -10,6 +10,10 @@ class JOEventType extends NameValue
const CANCEL = 'cancel'; const CANCEL = 'cancel';
const FULFILL = 'fulfill'; const FULFILL = 'fulfill';
const OPEN_EDIT = 'open_edit'; const OPEN_EDIT = 'open_edit';
const REQUEUE = 'requeue';
const RIDER_ACCEPT = 'accept';
const RIDER_ARRIVE = 'arrive';
const RIDER_EDIT = 'rider_edit';
const COLLECTION = [ const COLLECTION = [
'create' => 'Created', 'create' => 'Created',
@ -18,5 +22,9 @@ class JOEventType extends NameValue
'cancel' => 'Cancelled', 'cancel' => 'Cancelled',
'fulfill' => 'Fulfilled', 'fulfill' => 'Fulfilled',
'open_edit' => 'Open Edit', 'open_edit' => 'Open Edit',
'requeue' => 'Requeue',
'accept' => 'Rider Accept',
'arrive' => 'Rider Arrive',
'rider_edit' => 'Rider Edit',
]; ];
} }

View file

@ -739,7 +739,7 @@
<i class="fa fa-genderless" style="color: #f4516c;"></i> <i class="fa fa-genderless" style="color: #f4516c;"></i>
</div> </div>
<div class="m-timeline-2__item-text m--padding-top-5"> <div class="m-timeline-2__item-text m--padding-top-5">
{{ event.getTypeName }} by {{ event.getUser.getFullName|default('Application') }} {{ event.getTypeName }} by {{ event.getUser.getFullName|default('Application') }} {% if event.getRider %} - Rider - {{ event.getRider.getFullName }}{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}