1734 lines
59 KiB
PHP
1734 lines
59 KiB
PHP
<?php
|
|
|
|
namespace App\Controller\CustomerAppAPI;
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Catalyst\ApiBundle\Component\Response as ApiResponse;
|
|
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
|
|
|
use App\Service\InvoiceGeneratorInterface;
|
|
use App\Service\MQTTClient;
|
|
use App\Service\MQTTClientApiv2;
|
|
use App\Service\FCMSender;
|
|
use App\Service\RiderTracker;
|
|
use App\Service\GeofenceTracker;
|
|
use App\Service\MapTools;
|
|
use App\Service\InventoryManager;
|
|
use App\Service\RiderAssignmentHandlerInterface;
|
|
use App\Service\PromoLogger;
|
|
use App\Service\HubSelector;
|
|
use App\Service\HubDistributor;
|
|
use App\Service\HubFilterLogger;
|
|
use App\Service\HubFilteringGeoChecker;
|
|
use App\Service\JobOrderManager;
|
|
use App\Service\PriceTierManager;
|
|
use App\Ramcar\ServiceType;
|
|
use App\Ramcar\APIRiderStatus;
|
|
use App\Ramcar\InvoiceCriteria;
|
|
use App\Ramcar\TradeInType;
|
|
use App\Ramcar\JOEventType;
|
|
use App\Ramcar\JOStatus;
|
|
use App\Ramcar\AdvanceOrderSlot;
|
|
use App\Ramcar\TransactionOrigin;
|
|
use App\Ramcar\AutoAssignStatus;
|
|
use App\Ramcar\WarrantyClass;
|
|
use App\Ramcar\HubCriteria;
|
|
use App\Ramcar\DeliveryStatus;
|
|
use App\Entity\Battery;
|
|
use App\Entity\Hub;
|
|
use App\Entity\Promo;
|
|
use App\Entity\JOEvent;
|
|
use App\Entity\Warranty;
|
|
use App\Entity\JobOrder;
|
|
use App\Entity\CustomerVehicle;
|
|
|
|
use DateTime;
|
|
|
|
class JobOrderController extends ApiController
|
|
{
|
|
public function getOngoing(Request $req)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
/*
|
|
// check if we have an ongoing job order
|
|
$ongoing_jos = $this->em->getRepository(JobOrder::class)->findBy([
|
|
'customer' => $cust,
|
|
'status' => [JOStatus::PENDING, JOStatus::RIDER_ASSIGN, JOStatus::IN_TRANSIT, JOStatus::ASSIGNED, JOStatus::IN_PROGRESS],
|
|
]);
|
|
*/
|
|
$ongoing_jos = $this->getOngoingJobOrders($cust);
|
|
|
|
// initialize data
|
|
$data = [];
|
|
|
|
// no ongoing
|
|
if (count($ongoing_jos) <= 0) {
|
|
$data = [
|
|
'has_ongoing' => false,
|
|
];
|
|
} else {
|
|
$data = [
|
|
'has_ongoing' => true,
|
|
];
|
|
}
|
|
|
|
// response
|
|
return new ApiResponse(true, '', $data);
|
|
}
|
|
|
|
public function getJOInvoice(Request $req)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req, [
|
|
'jo_id',
|
|
]);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get job order
|
|
$jo_id = $req->query->get('jo_id');
|
|
$jo = $this->em->getRepository(JobOrder::class)->find($jo_id);
|
|
if ($jo == null) {
|
|
return new ApiResponse(false, 'No job order found.');
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
// check that the customer owns the job order
|
|
$jo_cust = $jo->getCustomer();
|
|
if ($jo_cust->getID() != $cust->getID()) {
|
|
return new ApiResponse(false, 'Job order was not initiated by customer.');
|
|
}
|
|
|
|
$invoice = $jo->getInvoice();
|
|
|
|
// 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;
|
|
|
|
/*
|
|
// 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,
|
|
],
|
|
];
|
|
|
|
*/
|
|
|
|
// response
|
|
return new ApiResponse(true, '', $data);
|
|
}
|
|
|
|
public function cancelJobOrder(Request $req, MQTTClient $mclient)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req, [
|
|
'jo_id',
|
|
'reason',
|
|
]);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get job order
|
|
$jo_id = $req->request->get('jo_id');
|
|
$jo = $this->em->getRepository(JobOrder::class)->find($jo_id);
|
|
if ($jo == null) {
|
|
return new ApiResponse(false, 'No job order found.');
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
// check that the customer owns the job order
|
|
$jo_cust = $jo->getCustomer();
|
|
if ($jo_cust->getID() != $cust->getID()) {
|
|
return new ApiResponse(false, 'Job order was not initiated by customer.');
|
|
}
|
|
|
|
// TODO: check job order status, if it's cancellable
|
|
$cancel_reason = $req->request->get('reason');
|
|
|
|
$jo->cancel($cancel_reason);
|
|
|
|
// add event log
|
|
$event = new JOEvent();
|
|
$event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::CANCEL)
|
|
->setJobOrder($jo);
|
|
$this->em->persist($event);
|
|
|
|
$this->em->flush();
|
|
|
|
// send mobile app event
|
|
$payload = [
|
|
'event' => 'cancelled',
|
|
'reason' => $cancel_reason,
|
|
'jo_id' => $jo->getID(),
|
|
];
|
|
// $mclient->sendEvent($jo, $payload);
|
|
$mclient->sendRiderEvent($jo, $payload);
|
|
|
|
// response
|
|
return new ApiResponse();
|
|
}
|
|
|
|
// we can't use param converter for now because we want to output the proper 404
|
|
public function getJobOrderInfo($id, Request $req, RiderTracker $rt)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
// get job order data
|
|
$jo = $this->em->getRepository(JobOrder::class)->find($id);
|
|
if ($jo == null) {
|
|
return new ApiResponse(false, 'No job order information found.');
|
|
}
|
|
|
|
// check if job order belongs to customer / user
|
|
if ($cust->getID() != $jo->getCustomer()->getID()) {
|
|
return new ApiResponse(false, 'No job order information found.');
|
|
}
|
|
|
|
// put into job order data array
|
|
$jo_data = $this->generateJobOrderData($req, $jo, $rt);
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'job_order' => $jo_data,
|
|
]);
|
|
}
|
|
|
|
public function getJOHistory(Request $req)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
// get job orders
|
|
$all_jo_data = [];
|
|
// $jos = $cust->getJobOrders();
|
|
// get the fulfilled and cancelled job orders, since ongoing jos are not yet part of history
|
|
$jos = $this->em->getRepository(JobOrder::class)->findBy([
|
|
'customer' => $cust,
|
|
'status' => [JOStatus::CANCELLED, JOStatus::FULFILLED]
|
|
], ['date_schedule' => 'DESC']);
|
|
foreach ($jos as $jo) {
|
|
// NOTE: use generateJobOrderData method, maybe?
|
|
$status = $jo->getStatus();
|
|
|
|
$jo_data = [
|
|
'id' => $jo->getID(),
|
|
'date_create' => $jo->getDateCreate()->format('M d, Y'),
|
|
'service_type' => $jo->getServiceType(),
|
|
'status' => $status,
|
|
];
|
|
|
|
// customer vehicle and warranty
|
|
$cv = $jo->getCustomerVehicle();
|
|
|
|
// get latest warranty using plate number
|
|
$warranty = $this->findWarranty($cv->getPlateNumber());
|
|
|
|
$jo_data['customer_vehicle'] = [
|
|
'id' => $cv->getID(),
|
|
'plate_number' => $cv->getPlateNumber(),
|
|
'warranty' => $warranty,
|
|
];
|
|
|
|
// rider
|
|
$rider = $jo->getRider();
|
|
|
|
// check if jo has rider rating set to true
|
|
$has_rider_rating = $jo->hasRiderRating();
|
|
$rating = 0;
|
|
$comment = '';
|
|
if ($rider != null) {
|
|
$jo_data['rider'] = $rider->getFullName();
|
|
|
|
// find the rider rating if any
|
|
if ($has_rider_rating) {
|
|
$jo_rating = $jo->getRating();
|
|
if ($jo_rating != null) {
|
|
$rating = $jo_rating->getRating();
|
|
|
|
// get comment
|
|
$comment = $jo_rating->getComment();
|
|
}
|
|
}
|
|
}
|
|
|
|
// rider rating for jo
|
|
$jo_data['has_rider_rating'] = $has_rider_rating;
|
|
$jo_data['rider_rating'] = $rating;
|
|
$jo_data['comment'] = $comment;
|
|
|
|
// invoice items
|
|
$items = [];
|
|
$jo_items = $jo->getInvoice()->getItems();
|
|
foreach ($jo_items as $item) {
|
|
$items[] = [
|
|
'id' => $item->getID(),
|
|
'title' => $item->getTitle(),
|
|
'qty' => $item->getQuantity(),
|
|
'price' => $item->getPrice(),
|
|
];
|
|
}
|
|
|
|
$jo_data['items'] = $items;
|
|
|
|
// dates depending on status
|
|
switch ($status) {
|
|
case JOStatus::FULFILLED:
|
|
if ($jo->getDateFulfill() == null)
|
|
$jo_data['date_fulfilled'] = '';
|
|
else
|
|
$jo_data['date_fulfilled'] = $jo->getDateFulfill()->format('M d, Y');
|
|
break;
|
|
case JOStatus::CANCELLED:
|
|
$date_cancel = $jo->getDateCancel();
|
|
if ($date_cancel == null)
|
|
$date_cancel = new DateTime();
|
|
$jo_data['date_cancelled'] = $date_cancel->format('M d, Y');
|
|
break;
|
|
}
|
|
|
|
$all_jo_data[] = $jo_data;
|
|
}
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'job_orders' => $all_jo_data,
|
|
]);
|
|
}
|
|
|
|
public function getLatestJobOrder(Request $req, RiderTracker $rt)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
// get the latest job order for customer
|
|
$latest_jo = $this->em->getRepository(JobOrder::class)->findOneBy(['customer' => $cust], ['id' => 'DESC']);
|
|
|
|
$jo_data = null;
|
|
if ($latest_jo != null) {
|
|
// TODO: clean the response up to just return what is needed
|
|
$jo_data = $this->generateLatestJobOrderData($req, $latest_jo, $rt);
|
|
}
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'latest_job_order' => $jo_data,
|
|
]);
|
|
}
|
|
|
|
public function getAllOngoingJobOrders(Request $req, RiderTracker $rt)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
$ongoing_jos = $this->getOngoingJobOrders($cust);
|
|
|
|
// initialize data
|
|
$jo_data = [];
|
|
foreach ($ongoing_jos as $jo) {
|
|
$jo_data[] = $this->generateJobOrderData($req, $jo, $rt);
|
|
}
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'ongoing_job_orders' => $jo_data,
|
|
]);
|
|
}
|
|
|
|
public function getOngoingJobOrderCount(Request $req)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
$ongoing_jos = $this->getOngoingJobOrders($cust);
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'ongoing_job_order_count' => count($ongoing_jos),
|
|
]);
|
|
}
|
|
|
|
public function newRequestJobOrder(
|
|
Request $req,
|
|
InvoiceGeneratorInterface $ic,
|
|
GeofenceTracker $geo,
|
|
MapTools $map_tools,
|
|
InventoryManager $im,
|
|
MQTTClientApiv2 $mclientv2,
|
|
FCMSender $fcmclient,
|
|
RiderAssignmentHandlerInterface $rah,
|
|
PromoLogger $promo_logger,
|
|
HubSelector $hub_select,
|
|
HubDistributor $hub_dist,
|
|
HubFilterLogger $hub_filter_logger,
|
|
HubFilteringGeoChecker $hub_geofence,
|
|
JobOrderManager $jo_manager,
|
|
PriceTierManager $pt_manager
|
|
) {
|
|
// validate params
|
|
$validity = $this->validateRequest($req, [
|
|
'service_type',
|
|
'cv_id',
|
|
'long',
|
|
'lat',
|
|
'warranty',
|
|
'mode_of_payment',
|
|
]);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// trade in type
|
|
$trade_in_batt = $req->request->get('trade_in_batt');
|
|
$trade_in_type = $req->request->get('trade_in_type', '');
|
|
|
|
// address
|
|
$address = $req->request->get('delivery_address', 'Set by mobile application');
|
|
|
|
// instructions
|
|
$instructions = $req->request->get('delivery_instructions', '');
|
|
|
|
// landmark
|
|
$landmark = $req->request->get('landmark', '');
|
|
|
|
// longitude and latitude
|
|
$long = $req->request->get('long');
|
|
$lat = $req->request->get('lat');
|
|
|
|
// NOTE: had to move this up so we can check for promo before geofence
|
|
// customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null) {
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
$is_covered = false;
|
|
// check if customer still has promo
|
|
if (($cust->getCustomerTag('TAG_CAR_CLUB_OFFICER_PROMO')) ||
|
|
($cust->getCustomerTag('TAG_CAR_CLUB_MEMBER_PROMO'))
|
|
) {
|
|
// if has customer tag, customer has not availed of promo
|
|
$is_covered = true;
|
|
} else {
|
|
// 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());
|
|
}
|
|
|
|
$hub = null;
|
|
$hub_id = $req->request->get('hub_id');
|
|
// check if hub_id is -1 which means user clicked Book Now before 5 PM
|
|
// but confirmed the order after 5 PM
|
|
if ($hub_id == -1) {
|
|
return new ApiResponse(false, 'Book Now no longer available.');
|
|
}
|
|
if (strlen($hub_id) > 0)
|
|
$hub = $this->em->getRepository(Hub::class)->find($hub_id);
|
|
|
|
$schedule_date = $req->request->get('date_schedule');
|
|
$slot_id = $req->request->get('slot_id');
|
|
|
|
// process the jo date schedule
|
|
$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'));
|
|
}
|
|
}
|
|
|
|
$advance_order = $req->request->get('flag_advance_order');
|
|
// check for 'false' text
|
|
if ($advance_order === false || $advance_order === 0 || $advance_order === '0' || $advance_order == 'false')
|
|
$flag_advance_order = false;
|
|
else
|
|
$flag_advance_order = true;
|
|
// $flag_advance_order = $advance_order ? true : false;
|
|
|
|
$jo = new JobOrder();
|
|
$jo->setSource(TransactionOrigin::MOBILE_APP)
|
|
->setStatus(JOStatus::PENDING)
|
|
->setDeliveryInstructions('')
|
|
->setTier1Notes('')
|
|
->setTier2Notes('')
|
|
->setDeliveryAddress($address)
|
|
->setTradeInType($trade_in_type)
|
|
->setDeliveryInstructions($instructions)
|
|
// TODO: error check for valid mode of payment
|
|
->setModeOfPayment($req->request->get('mode_of_payment'))
|
|
->setAdvanceOrder($flag_advance_order)
|
|
->setStatusAutoAssign(AutoAssignStatus::NOT_ASSIGNED)
|
|
->setLandmark($landmark);
|
|
|
|
// customer
|
|
// $cust = $this->session->getCustomer();
|
|
// if ($cust == null)
|
|
// {
|
|
// $res->setError(true)
|
|
// ->setErrorMessage('No customer information found');
|
|
// return $res->getReturnResponse();
|
|
// }
|
|
|
|
// check if customer has more than one job order already
|
|
$flag_cust_new = false;
|
|
|
|
$cust_jo_count = $jo_manager->getCustomerJobOrderCount($cust->getID());
|
|
if ($cust_jo_count <= 1)
|
|
$flag_cust_new = true;
|
|
|
|
$jo->setCustomer($cust);
|
|
$jo->setCustNew($flag_cust_new);
|
|
|
|
// 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_type) {
|
|
case TradeInType::MOTOLITE:
|
|
case TradeInType::OTHER:
|
|
break;
|
|
|
|
default:
|
|
$trade_in_type = '';
|
|
break;
|
|
}
|
|
|
|
// add the actual battery item first
|
|
$icrit->addEntry($batt, null, 1);
|
|
|
|
// if we have a trade in, add it as well
|
|
if (!empty($trade_in_type) && !empty($trade_in_batt)) {
|
|
$ti_batt_obj = $this->em->getRepository(Battery::class)->find($trade_in_batt);
|
|
if (!empty($ti_batt_obj)) {
|
|
$battery_size = $ti_batt_obj->getSize();
|
|
$icrit->addTradeInEntry($battery_size, $trade_in_type, 1);
|
|
}
|
|
}
|
|
|
|
// set taxable
|
|
$icrit->setIsTaxable();
|
|
|
|
// set JO source
|
|
$icrit->setSource(TransactionOrigin::MOBILE_APP);
|
|
|
|
// set price tier
|
|
$pt_id = $pt_manager->getPriceTier($jo->getCoordinates());
|
|
$icrit->setPriceTier($pt_id);
|
|
|
|
// send to invoice generator
|
|
$invoice = $ic->generateInvoice($icrit);
|
|
$jo->setInvoice($invoice);
|
|
|
|
// assign hub and rider
|
|
// check if hub is null
|
|
if ($hub == null) {
|
|
// TODO: need to factor out the setting of HubCriteria fields
|
|
$hub_criteria = new HubCriteria();
|
|
$hub_criteria->setPoint($jo->getCoordinates());
|
|
|
|
// get distance limit for mobile from env
|
|
// get value of hub_filter_enable from env
|
|
$limit_distance = $_ENV['CUST_DISTANCE_LIMIT'];
|
|
$hub_filter_enabled = $_ENV['HUB_FILTER_ENABLE'];
|
|
|
|
// set distance limit
|
|
$hub_criteria->setLimitDistance($limit_distance);
|
|
|
|
// check if hub filter is enabled. If not, use default values
|
|
// for the rest of the HubCriteria fields
|
|
if ($hub_filter_enabled == 'true') {
|
|
// error_log('hub filter is enabled');
|
|
// check if customer location is in hub filter area
|
|
if ($hub_geofence->isCovered($long, $lat)) {
|
|
// if true, set other values for HubCriteria
|
|
// TODO: set this properly, since the other flags
|
|
// are on default values
|
|
// error_log('Area is covered by hub filtering');
|
|
$hub_criteria->setJoType($jo->getServiceType())
|
|
->setPaymentMethod($jo->getModeOfPayment())
|
|
->setRoundRobin(true);
|
|
}
|
|
}
|
|
|
|
// check if batt is null
|
|
if ($batt != null) {
|
|
// 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);
|
|
|
|
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) {
|
|
// check if hub can be auto assigned
|
|
// if not, move on to the next hub in the list
|
|
if (($nearest_hub['hub']->isHubAutoAssign())) {
|
|
// check if hub has riders that can be auto assigned
|
|
// if not, move on to the next hub
|
|
if (($nearest_hub['hub']->isRiderAutoAssign())) {
|
|
$available_riders = $nearest_hub['hub']->getAvailableRiders();
|
|
if (count($available_riders) >= 1) {
|
|
$assigned_rider = null;
|
|
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);
|
|
$jo->setDeliveryStatus(DeliveryStatus::RIDER_ASSIGN);
|
|
|
|
// set date_assigned for job order
|
|
$jo->setDateAssign(new DateTime());
|
|
|
|
$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 {
|
|
// we just create the JO and let admin panel handle the hub assignment
|
|
// 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
|
|
}
|
|
} else {
|
|
// TODO: log hub as cannot be auto rider assigned somewhere
|
|
// assign hub
|
|
// error_log('Rider cannot be auto assigned ' . $nearest_hub['hub']->getID());
|
|
$jo->setHub($nearest_hub['hub']);
|
|
$jo->setStatus(JOStatus::RIDER_ASSIGN);
|
|
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_ASSIGNED);
|
|
|
|
// update redis hub_jo_count for hub
|
|
$hub_dist->incrementJoCountForHub($nearest_hub['hub']);
|
|
|
|
break;
|
|
}
|
|
} else {
|
|
// TODO: log hub as cannot be auto assigned somewhere
|
|
// move to next hub
|
|
error_log('Hub cannot be auto-assigned ' . $nearest_hub['hub']->getID());
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$jo->setHub($hub);
|
|
$jo->setStatus(JOStatus::RIDER_ASSIGN);
|
|
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_ASSIGNED);
|
|
|
|
if ($date_schedule != null)
|
|
$jo->setDateSchedule($date_schedule);
|
|
|
|
// update redis hub_jo_count for hub
|
|
$hub_dist->incrementJoCountForHub($hub);
|
|
}
|
|
|
|
$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);
|
|
|
|
$this->em->flush();
|
|
|
|
// 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',
|
|
];
|
|
$mclientv2->sendEvent($jo, $payload);
|
|
$fcmclient->sendJoEvent($jo, "jo_fcm_title_outlet_assign", "jo_fcm_body_outlet_assign");
|
|
|
|
$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);
|
|
|
|
$this->em->persist($hub_assign_event);
|
|
|
|
// user mqtt event
|
|
$payload = [
|
|
'event' => 'outlet_assign',
|
|
];
|
|
$mclientv2->sendEvent($jo, $payload);
|
|
$fcmclient->sendJoEvent($jo, "jo_fcm_title_outlet_assign", "jo_fcm_body_outlet_assign");
|
|
}
|
|
|
|
$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;
|
|
|
|
// need to check for customer tag/promo
|
|
// 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('session_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,
|
|
]);
|
|
}
|
|
|
|
// TODO: remove later
|
|
// mobile app no longer calls this
|
|
public function requestJobOrder(
|
|
Request $req,
|
|
InvoiceGeneratorInterface $ic,
|
|
GeofenceTracker $geo,
|
|
MapTools $map_tools,
|
|
InventoryManager $im,
|
|
MQTTClientApiv2 $mclientv2,
|
|
FCMSender $fcmclient,
|
|
RiderAssignmentHandlerInterface $rah,
|
|
PromoLogger $promo_logger,
|
|
HubSelector $hub_select,
|
|
HubDistributor $hub_dist,
|
|
HubFilterLogger $hub_filter_logger,
|
|
HubFilteringGeoChecker $hub_geofence,
|
|
JobOrderManager $jo_manager,
|
|
PriceTierManager $pt_manager
|
|
) {
|
|
// validate params
|
|
$validity = $this->validateRequest($req, [
|
|
'service_type',
|
|
'cv_id',
|
|
// 'batt_id',
|
|
'long',
|
|
'lat',
|
|
'warranty',
|
|
'mode_of_payment',
|
|
]);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// trade in type
|
|
$trade_in_batt = $req->request->get('trade_in_batt');
|
|
$trade_in_type = $req->request->get('trade_in_type', '');
|
|
|
|
// 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_type)
|
|
->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.');
|
|
}
|
|
|
|
// check if customer has more than one job order already
|
|
$flag_cust_new = false;
|
|
|
|
$cust_jo_count = $jo_manager->getCustomerJobOrderCount($cust->getID());
|
|
if ($cust_jo_count <= 1)
|
|
$flag_cust_new = true;
|
|
|
|
$jo->setCustomer($cust);
|
|
$jo->setCustNew($flag_cust_new);
|
|
|
|
// 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_type) {
|
|
case TradeInType::MOTOLITE:
|
|
case TradeInType::OTHER:
|
|
break;
|
|
|
|
default:
|
|
$trade_in_type = '';
|
|
break;
|
|
}
|
|
|
|
// add the actual battery item first
|
|
$icrit->addEntry($batt, null, 1);
|
|
|
|
// if we have a trade in, add it as well
|
|
if (!empty($trade_in_type) && !empty($trade_in_batt)) {
|
|
$ti_batt_obj = $this->em->getRepository(Battery::class)->find($trade_in_batt);
|
|
if (!empty($ti_batt_obj)) {
|
|
$battery_size = $ti_batt_obj->getSize();
|
|
$icrit->addTradeInEntry($battery_size, $trade_in_type, 1);
|
|
}
|
|
}
|
|
|
|
// set taxable
|
|
$icrit->setIsTaxable();
|
|
|
|
// set JO source
|
|
$icrit->setSource(TransactionOrigin::MOBILE_APP);
|
|
|
|
// set price tier
|
|
$pt_id = $pt_manager->getPriceTier($jo->getCoordinates());
|
|
$icrit->setPriceTier($pt_id);
|
|
|
|
// 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',
|
|
];
|
|
$mclientv2->sendEvent($jo, $payload);
|
|
$fcmclient->sendJoEvent($jo, "jo_fcm_title_outlet_assign", "jo_fcm_body_outlet_assign");
|
|
|
|
$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('session_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
|
|
/*
|
|
public function getCompletedJobOrders(Request $req, EntityManagerInterface $em, RiderTracker $rt)
|
|
{
|
|
// validate params
|
|
$validity = $this->validateRequest($req);
|
|
|
|
if (!$validity['is_valid']) {
|
|
return new ApiResponse(false, $validity['error']);
|
|
}
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
return new ApiResponse(false, 'No customer information found.');
|
|
}
|
|
|
|
$completed_jos = $this->getCompletedJOs($cust);
|
|
|
|
// initialize data
|
|
$jo_data = [];
|
|
foreach ($completed_jos as $jo)
|
|
{
|
|
$jo_data[] = $this->generateJobOrderData($req, $jo, $rt);
|
|
}
|
|
|
|
// response
|
|
return new ApiResponse(true, '', [
|
|
'completed_job_orders' => $jo_data,
|
|
]);
|
|
}
|
|
|
|
protected function getCompletedJOs($cust)
|
|
{
|
|
$completed_jos = $this->em->getRepository(JobOrder::class)->findBy([
|
|
'customer' => $cust,
|
|
'status' => [JOStatus::CANCELLED, JOStatus::FULFILLED],
|
|
], ['date_schedule' => 'desc']);
|
|
|
|
return $completed_jos;
|
|
}
|
|
*/
|
|
|
|
protected function generateJobOrderData($req, $jo, $rt)
|
|
{
|
|
$status = $jo->getStatus();
|
|
|
|
$dest = $jo->getCoordinates();
|
|
|
|
$jo_data = [
|
|
'id' => $jo->getID(),
|
|
'date_create' => $jo->getDateCreate()->format('M d, Y'),
|
|
'date_schedule' => $jo->getDateSchedule()->format('M d, Y H:i'),
|
|
'service_type' => $jo->getServiceType(),
|
|
'destination' => [
|
|
'long' => $dest->getLongitude(),
|
|
'lat' => $dest->getLatitude(),
|
|
],
|
|
'delivery_address' => $jo->getDeliveryAddress(),
|
|
'delivery_instructions' => $jo->getDeliveryInstructions(),
|
|
'landmark' => $jo->getLandmark(),
|
|
'jo_status' => $status,
|
|
'status' => $this->generateAPIRiderStatus($status),
|
|
];
|
|
|
|
// customer vehicle and warranty
|
|
$cv = $jo->getCustomerVehicle();
|
|
|
|
// get latest warranty using plate number
|
|
$warranty = $this->findWarranty($cv->getPlateNumber());
|
|
|
|
$jo_data['customer_vehicle'] = [
|
|
'id' => $cv->getID(),
|
|
'plate_number' => $cv->getPlateNumber(),
|
|
'warranty' => $warranty,
|
|
];
|
|
|
|
// customer information
|
|
$customer = $jo->getCustomer();
|
|
$jo_data['customer'] = [
|
|
'first_name' => $customer->getFirstName(),
|
|
'last_name' => $customer->getLastName(),
|
|
'mobile_number' => $customer->getPhoneMobile(),
|
|
];
|
|
|
|
// rider
|
|
$rider = $jo->getRider();
|
|
if ($rider != null) {
|
|
// default image url
|
|
$url_prefix = $req->getSchemeAndHttpHost();
|
|
$image_url = $url_prefix . '/assets/images/user.gif';
|
|
if ($rider->getImageFile() != null)
|
|
$image_url = $url_prefix . '/uploads/' . $rider->getImageFile();
|
|
|
|
$coord = $rt->getRiderLocation($rider->getID());
|
|
|
|
$jo_data['rider'] = [
|
|
'id' => $rider->getID(),
|
|
'name' => $rider->getFullName(),
|
|
'plate_num' => $rider->getPlateNumber(),
|
|
'contact_num' => $rider->getContactNumber(),
|
|
'curr_rating' => $rider->getCurrentRating(),
|
|
'image_url' => $image_url,
|
|
'location' => [
|
|
'long' => $coord->getLongitude(),
|
|
'lat' => $coord->getLatitude()
|
|
]
|
|
];
|
|
|
|
// check if jo has rider rating set to true
|
|
$has_rider_rating = $jo->hasRiderRating();
|
|
$rating = 0;
|
|
$comment = '';
|
|
if ($rider != null) {
|
|
// find the rider rating if any
|
|
if ($has_rider_rating) {
|
|
$jo_rating = $jo->getRating();
|
|
if ($jo_rating != null) {
|
|
$rating = $jo_rating->getRating();
|
|
|
|
// get comment
|
|
$comment = $jo_rating->getComment();
|
|
}
|
|
}
|
|
}
|
|
|
|
// rider rating for jo
|
|
$jo_data['has_rider_rating'] = $has_rider_rating;
|
|
$jo_data['rider_rating'] = $rating;
|
|
$jo_data['comment'] = $comment;
|
|
} else {
|
|
$jo_data['rider'] = null;
|
|
$jo_data['has_rider_rating'] = null;
|
|
$jo_data['rider_rating'] = null;
|
|
$jo_data['comment'] = null;
|
|
}
|
|
|
|
// invoice items
|
|
$items = [];
|
|
$jo_items = $jo->getInvoice()->getItems();
|
|
foreach ($jo_items as $item) {
|
|
$items[] = [
|
|
'id' => $item->getID(),
|
|
'title' => $item->getTitle(),
|
|
'qty' => $item->getQuantity(),
|
|
'price' => $item->getPrice(),
|
|
];
|
|
}
|
|
|
|
$jo_data['items'] = $items;
|
|
|
|
|
|
// dates depending on status
|
|
switch ($status) {
|
|
case JOStatus::FULFILLED:
|
|
if ($jo->getDateFulfill() == null)
|
|
$jo_data['date_fulfilled'] = '';
|
|
else
|
|
$jo_data['date_fulfilled'] = $jo->getDateFulfill()->format('M d, Y');
|
|
break;
|
|
case JOStatus::CANCELLED:
|
|
$date_cancel = $jo->getDateCancel();
|
|
if ($date_cancel == null)
|
|
$date_cancel = new DateTime();
|
|
$jo_data['date_cancelled'] = $date_cancel->format('M d, Y');
|
|
break;
|
|
}
|
|
|
|
return $jo_data;
|
|
}
|
|
|
|
protected function generateAPIRiderStatus($status)
|
|
{
|
|
switch ($status) {
|
|
case JOStatus::PENDING:
|
|
return APIRiderStatus::OUTLET_ASSIGN;
|
|
case JOStatus::RIDER_ASSIGN:
|
|
return APIRiderStatus::RIDER_ASSIGN;
|
|
case JOStatus::ASSIGNED:
|
|
case JOStatus::IN_TRANSIT:
|
|
case JOStatus::IN_PROGRESS:
|
|
return APIRiderStatus::RIDER_PICK_UP;
|
|
}
|
|
return 'unknown';
|
|
}
|
|
|
|
protected function generateLatestJobOrderData($req, $jo, $rt)
|
|
{
|
|
$status = $jo->getStatus();
|
|
|
|
$dest = $jo->getCoordinates();
|
|
|
|
$jo_data = [
|
|
'id' => $jo->getID(),
|
|
'date_create' => $jo->getDateCreate()->format('M d, Y'),
|
|
'service_type' => $jo->getServiceType(),
|
|
'destination' => [
|
|
'long' => $dest->getLongitude(),
|
|
'lat' => $dest->getLatitude(),
|
|
],
|
|
'delivery_address' => $jo->getDeliveryAddress(),
|
|
'delivery_instructions' => $jo->getDeliveryInstructions(),
|
|
'jo_status' => $status,
|
|
'status' => $this->generateAPIRiderStatus($status),
|
|
'landmark' => $jo->getLandmark(),
|
|
];
|
|
|
|
// customer vehicle and warranty
|
|
$cv = $jo->getCustomerVehicle();
|
|
|
|
// get latest warranty using plate number
|
|
$warranty = $this->findWarranty($cv->getPlateNumber());
|
|
|
|
$jo_data['customer_vehicle'] = [
|
|
'id' => $cv->getID(),
|
|
'plate_number' => $cv->getPlateNumber(),
|
|
'warranty' => $warranty,
|
|
];
|
|
|
|
// customer information
|
|
$customer = $jo->getCustomer();
|
|
$jo_data['customer'] = [
|
|
'first_name' => $customer->getFirstName(),
|
|
'last_name' => $customer->getLastName(),
|
|
'mobile_number' => $customer->getPhoneMobile(),
|
|
];
|
|
|
|
// rider
|
|
$rider = $jo->getRider();
|
|
if ($rider != null) {
|
|
// default image url
|
|
$url_prefix = $req->getSchemeAndHttpHost();
|
|
$image_url = $url_prefix . '/assets/images/user.gif';
|
|
if ($rider->getImageFile() != null)
|
|
$image_url = $url_prefix . '/uploads/' . $rider->getImageFile();
|
|
|
|
$coord = $rt->getRiderLocation($rider->getID());
|
|
|
|
$jo_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()
|
|
]
|
|
];
|
|
} else {
|
|
$jo_data['rider'] = null;
|
|
}
|
|
|
|
// invoice items
|
|
$items = [];
|
|
$jo_items = $jo->getInvoice()->getItems();
|
|
foreach ($jo_items as $item) {
|
|
$items[] = [
|
|
'id' => $item->getID(),
|
|
'title' => $item->getTitle(),
|
|
'qty' => $item->getQuantity(),
|
|
'price' => $item->getPrice(),
|
|
];
|
|
}
|
|
|
|
$jo_data['items'] = $items;
|
|
|
|
|
|
// dates depending on status
|
|
switch ($status) {
|
|
case JOStatus::FULFILLED:
|
|
if ($jo->getDateFulfill() == null)
|
|
$jo_data['date_fulfilled'] = '';
|
|
else
|
|
$jo_data['date_fulfilled'] = $jo->getDateFulfill()->format('M d, Y');
|
|
break;
|
|
case JOStatus::CANCELLED:
|
|
$date_cancel = $jo->getDateCancel();
|
|
if ($date_cancel == null)
|
|
$date_cancel = new DateTime();
|
|
$jo_data['date_cancelled'] = $date_cancel->format('M d, Y');
|
|
break;
|
|
}
|
|
|
|
return $jo_data;
|
|
}
|
|
|
|
protected function findWarranty($plate_number)
|
|
{
|
|
// NOTE: Modify the search for the latest warranty. This seems hacky.
|
|
// get latest warranty using plate number
|
|
$warranty_results = $this->em->getRepository(Warranty::class)->findBy(
|
|
['plate_number' => $plate_number],
|
|
['date_create' => 'desc']
|
|
);
|
|
|
|
$warr = [];
|
|
|
|
// check if warranty_results is empty
|
|
if (empty($warranty_results)) {
|
|
/*
|
|
$res->setError(true)
|
|
->setErrorMessage('No warranty found for plate number');
|
|
return $res->getReturnResponse();
|
|
*/
|
|
|
|
return $warr;
|
|
}
|
|
|
|
// get first entry
|
|
$warranty = current($warranty_results);
|
|
|
|
// check for null values for battery and date claim and date expire
|
|
$batt_model = '';
|
|
$batt_size = '';
|
|
$sap_batt = '';
|
|
$claim_date = '';
|
|
$expiry_date = '';
|
|
|
|
if (!(is_null($warranty->getBatteryModel()))) {
|
|
$batt_model = $warranty->getBatteryModel()->getName();
|
|
}
|
|
if (!(is_null($warranty->getBatterySize()))) {
|
|
$batt_size = $warranty->getBatterySize()->getName();
|
|
}
|
|
if (!(is_null($warranty->getSAPBattery()))) {
|
|
$sap_batt = $warranty->getSAPBattery()->getID();
|
|
}
|
|
if (!(is_null($warranty->getDateClaim()))) {
|
|
$claim_date = $warranty->getDateClaim()->format("d M Y");
|
|
}
|
|
if (!(is_null($warranty->getDateExpire()))) {
|
|
$expiry_date = $warranty->getDateExpire()->format("d M Y");
|
|
}
|
|
|
|
$warr[] = [
|
|
'id' => $warranty->getID(),
|
|
'serial' => $warranty->getSerial(),
|
|
'warranty_class' => $warranty->getWarrantyClass(),
|
|
'plate_number' => $warranty->getPlateNumber(),
|
|
'first_name' => $warranty->getFirstName(),
|
|
'last_name' => $warranty->getLastName(),
|
|
'mobile_number' => $warranty->getMobileNumber(),
|
|
'battery_model' => $batt_model,
|
|
'battery_size' => $batt_size,
|
|
'sap_battery' => $sap_batt,
|
|
'status' => $warranty->getStatus(),
|
|
'date_create' => $warranty->getDateCreate()->format("d M Y g:i A"),
|
|
'date_purchase' => $warranty->getDatePurchase()->format("d M Y"),
|
|
'date_expire' => $expiry_date,
|
|
'date_claim' => $claim_date,
|
|
'claim_from' => $warranty->getClaimedFrom(),
|
|
'is_activated' => $warranty->isActivated() ? 1 : 0,
|
|
];
|
|
|
|
return $warr;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
protected function randomizeRider($riders)
|
|
{
|
|
// TODO: get redis to track the sales per rider per day
|
|
// check the time they came in
|
|
// for now, randomize the rider
|
|
$selected_index = array_rand($riders);
|
|
|
|
$selected_rider = $riders[$selected_index];
|
|
|
|
return $selected_rider;
|
|
}
|
|
}
|