4826 lines
158 KiB
PHP
4826 lines
158 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use Doctrine\ORM\Query;
|
|
use Doctrine\ORM\QueryBuilder;
|
|
use Doctrine\DBAL\DBALException;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\Dotenv\Dotenv;
|
|
use Symfony\Component\HttpFoundation\RequestStack;
|
|
use Symfony\Component\HttpKernel\KernelInterface;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
|
|
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
|
|
|
use App\Ramcar\APIResult;
|
|
use App\Ramcar\JOStatus;
|
|
use App\Ramcar\InvoiceCriteria;
|
|
use App\Ramcar\ServiceType;
|
|
use App\Ramcar\WarrantyClass;
|
|
use App\Ramcar\APIRiderStatus;
|
|
use App\Ramcar\TransactionOrigin;
|
|
use App\Ramcar\TradeInType;
|
|
use App\Ramcar\JOEventType;
|
|
use App\Ramcar\AdvanceOrderSlot;
|
|
use App\Ramcar\AutoAssignStatus;
|
|
use App\Ramcar\WarrantySource;
|
|
use App\Ramcar\HubCriteria;
|
|
use App\Ramcar\CustomerSource;
|
|
use App\Ramcar\DeliveryStatus;
|
|
|
|
use App\Service\InvoiceGeneratorInterface;
|
|
use App\Service\RisingTideGateway;
|
|
use App\Service\MQTTClient;
|
|
use App\Service\GeofenceTracker;
|
|
use App\Service\RiderTracker;
|
|
use App\Service\MapTools;
|
|
use App\Service\InventoryManager;
|
|
use App\Service\RiderAssignmentHandlerInterface;
|
|
use App\Service\WarrantyRaffleLogger;
|
|
use App\Service\WarrantyAPILogger;
|
|
use App\Service\PromoLogger;
|
|
use App\Service\HubSelector;
|
|
use App\Service\HubDistributor;
|
|
use App\Service\HubFilterLogger;
|
|
use App\Service\HubFilteringGeoChecker;
|
|
use App\Service\HashGenerator;
|
|
|
|
use App\Entity\MobileSession;
|
|
use App\Entity\Customer;
|
|
use App\Entity\VehicleManufacturer;
|
|
use App\Entity\Vehicle;
|
|
use App\Entity\CustomerVehicle;
|
|
use App\Entity\JobOrder;
|
|
use App\Entity\Promo;
|
|
use App\Entity\Battery;
|
|
use App\Entity\RiderRating;
|
|
use App\Entity\JOEvent;
|
|
use App\Entity\Warranty;
|
|
use App\Entity\Service;
|
|
use App\Entity\Partner;
|
|
use App\Entity\Review;
|
|
use App\Entity\PrivacyPolicy;
|
|
use App\Entity\Hub;
|
|
use App\Entity\SAPBattery;
|
|
use App\Entity\WarrantySerial;
|
|
use App\Entity\CustomerMetadata;
|
|
|
|
use DateTime;
|
|
use DateInterval;
|
|
use Exception;
|
|
|
|
// mobile API
|
|
class APIController extends Controller implements LoggedController
|
|
{
|
|
const RIDER_SLOT_ARRAY_LENGTH = 8;
|
|
|
|
protected $session;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->session = null;
|
|
}
|
|
|
|
protected function debugRequest(Request $req)
|
|
{
|
|
$all = $req->request->all();
|
|
error_log(print_r($all, true));
|
|
}
|
|
|
|
protected function checkMissingParameters(Request $req, $params = [])
|
|
{
|
|
$missing = [];
|
|
|
|
// check if parameters are there
|
|
foreach ($params as $param)
|
|
{
|
|
if ($req->getMethod() == 'GET')
|
|
{
|
|
$check = $req->query->get($param);
|
|
if (empty($check))
|
|
$missing[] = $param;
|
|
}
|
|
else if ($req->getMethod() == 'POST')
|
|
{
|
|
$check = $req->request->get($param);
|
|
if (empty($check))
|
|
$missing[] = $param;
|
|
}
|
|
else
|
|
return $params;
|
|
}
|
|
|
|
return $missing;
|
|
}
|
|
|
|
// TODO: type hint entity manager
|
|
protected function checkAPIKey($em, $api_key)
|
|
{
|
|
// find the api key (session id)
|
|
$session = $em->getRepository(MobileSession::class)->find($api_key);
|
|
if ($session == null)
|
|
return null;
|
|
|
|
return $session;
|
|
}
|
|
|
|
protected function checkParamsAndKey(Request $req, $em, $params)
|
|
{
|
|
// returns APIResult object
|
|
$res = new APIResult();
|
|
|
|
// check for api_key in query string
|
|
$api_key = $req->query->get('api_key');
|
|
if (empty($api_key))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing API key');
|
|
return $res;
|
|
}
|
|
|
|
// check missing parameters
|
|
$missing = $this->checkMissingParameters($req, $params);
|
|
if (count($missing) > 0)
|
|
{
|
|
$miss_string = implode(', ', $missing);
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing parameter(s): ' . $miss_string);
|
|
return $res;
|
|
}
|
|
|
|
// check api key
|
|
$sess = $this->checkAPIKey($em, $req->query->get('api_key'));
|
|
if ($sess == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid API Key');
|
|
return $res;
|
|
}
|
|
|
|
// store session
|
|
$this->session = $sess;
|
|
|
|
return $res;
|
|
}
|
|
|
|
public function register(Request $req)
|
|
{
|
|
$res = new APIResult();
|
|
|
|
// confirm parameters
|
|
$required_params = [
|
|
'phone_model',
|
|
'os_type',
|
|
'os_version',
|
|
'phone_id'
|
|
];
|
|
|
|
$missing = $this->checkMissingParameters($req, $required_params);
|
|
if (count($missing) > 0)
|
|
{
|
|
$params = implode(', ', $missing);
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing parameter(s): ' . $params);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
|
// retry until we get a unique id
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
// instantiate session
|
|
$sess = new MobileSession();
|
|
$sess->setPhoneModel($req->request->get('phone_model'))
|
|
->setOSType($req->request->get('os_type'))
|
|
->setOSVersion($req->request->get('os_version'))
|
|
->setPhoneID($req->request->get('phone_id'));
|
|
|
|
// reopen in case we get an exception
|
|
if (!$em->isOpen())
|
|
{
|
|
$em = $em->create(
|
|
$em->getConnection(),
|
|
$em->getConfiguration()
|
|
);
|
|
}
|
|
|
|
// save
|
|
$em->persist($sess);
|
|
$em->flush();
|
|
}
|
|
catch (DBALException $e)
|
|
{
|
|
error_log($e->getMessage());
|
|
// delay one second and try again
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// return data
|
|
$data = [
|
|
'session_id' => $sess->getID()
|
|
];
|
|
$res->setData($data);
|
|
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function generateConfirmCode()
|
|
{
|
|
return sprintf("%06d", mt_rand(100000, 999999));
|
|
}
|
|
|
|
protected function sendConfirmationCode(RisingTideGateway $rt, $phone_number, $code, TranslatorInterface $translator)
|
|
{
|
|
// send sms to number
|
|
$message = $translator->trans('message.confirmation_code') . ' ' . $code;
|
|
$rt->sendSMS($phone_number, $translator->trans('message.battery_brand_allcaps'), $message);
|
|
}
|
|
|
|
public function confirmNumber(RisingTideGateway $rt, Request $req, TranslatorInterface $translator)
|
|
{
|
|
// check parameters
|
|
$required_params = [
|
|
'phone_number',
|
|
];
|
|
|
|
// check required parameters and api key
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// phone number
|
|
$phone_number = $req->request->get('phone_number');
|
|
|
|
// get otp_mode from .env
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../.env');
|
|
|
|
$otp_mode = $_ENV['OTP_MODE'];
|
|
|
|
// check for hardcoded phone number for app store testing
|
|
if ($phone_number == '639221111111')
|
|
{
|
|
$code = '123456';
|
|
$this->session->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check if otp_mode is test
|
|
if ($otp_mode == 'test')
|
|
{
|
|
$code = '123456';
|
|
$this->session->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// TODO: spam protection
|
|
|
|
// TODO: validate phone number
|
|
|
|
// generate code and save
|
|
$code = $this->generateConfirmCode();
|
|
$this->session->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
if ($otp_mode != 'test')
|
|
{
|
|
// send sms to number
|
|
$this->sendConfirmationCode($rt, $phone_number, $code, $translator);
|
|
}
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// TODO: find session customer by phone number
|
|
protected function findNumberSession($number)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
$query = $em->getRepository(MobileSession::class)->createQueryBuilder('s')
|
|
->where('s.phone_number = :number')
|
|
->andWhere('s.customer is not null')
|
|
->andWhere('s.confirm_flag = 1')
|
|
->setParameter('number', $number)
|
|
->setMaxResults(1)
|
|
->getQuery();
|
|
|
|
// we just need one
|
|
$res = $query->getOneOrNullResult();
|
|
|
|
return $res;
|
|
}
|
|
|
|
public function validateCode(Request $req)
|
|
{
|
|
// check parameters
|
|
$required_params = [
|
|
'code',
|
|
];
|
|
|
|
// check required parameters and api key
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// code is wrong
|
|
$code = $req->request->get('code');
|
|
if ($this->session->getConfirmCode() != $code)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Wrong confirm code');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// set confirm date
|
|
$date = new DateTime();
|
|
$this->session->setDateConfirmed($date)
|
|
->setConfirmed();
|
|
|
|
|
|
// TODO: check if we have the number registered before and merge
|
|
$dupe_sess = $this->findNumberSession($this->session->getPhoneNumber());
|
|
if ($dupe_sess != null)
|
|
{
|
|
$dupe_cust = $dupe_sess->getCustomer();
|
|
$this->session->setCustomer($dupe_cust);
|
|
}
|
|
|
|
// TODO: check if mobile matches mobile of customer
|
|
$customer = $this->findCustomerByNumber($this->session->getPhoneNumber());
|
|
if ($customer != null)
|
|
{
|
|
// TODO: if there is a dupe_sess, do we need to check if
|
|
// dupe_cust is the same as the customer we found?
|
|
$this->session->setCustomer($customer);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getInfo(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// if no customer found
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$data = [
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'priv_third_party' => (bool) false,
|
|
'priv_promo' => (bool) false,
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// send back customer details
|
|
$data = [
|
|
'first_name' => $cust->getFirstName(),
|
|
'last_name' => $cust->getLastName(),
|
|
'priv_third_party' => (bool) $cust->getPrivacyThirdParty(),
|
|
'priv_promo' => (bool) $cust->getPrivacyPromo(),
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function updateCustomerInfo($req, $em)
|
|
{
|
|
// create new customer if it's not there
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$cust = new Customer();
|
|
|
|
// set customer source
|
|
$cust->setCreateSource(CustomerSource::MOBILE);
|
|
$em->persist($cust);
|
|
|
|
$this->session->setCustomer($cust);
|
|
}
|
|
|
|
$cust->setFirstName($req->request->get('first_name'))
|
|
->setLastName($req->request->get('last_name'))
|
|
->setEmail($req->request->get('email', ''))
|
|
->setConfirmed($this->session->isConfirmed());
|
|
|
|
// update mobile phone of customer
|
|
$cust->setPhoneMobile(substr($this->session->getPhoneNumber(), 2));
|
|
|
|
return $cust;
|
|
}
|
|
|
|
public function updateInfo(Request $req, EntityManagerInterface $em)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'first_name',
|
|
'last_name',
|
|
];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$cust = $this->updateCustomerInfo($req, $em);
|
|
|
|
// get privacy policy for mobile
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../.env');
|
|
|
|
$policy_mobile_id = $_ENV['POLICY_MOBILE'];
|
|
|
|
$mobile_policy = $em->getRepository(PrivacyPolicy::class)->find($policy_mobile_id);
|
|
|
|
// set policy id
|
|
if ($mobile_policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyMobile($mobile_policy);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getStatus(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// set data
|
|
$data = [];
|
|
if ($this->session->isConfirmed())
|
|
$data['status'] = 'confirmed';
|
|
else
|
|
$data['status'] = 'unconfirmed';
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function listVehicleManufacturers(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get manufacturer list
|
|
$mfgs = $em->getRepository(VehicleManufacturer::class)->findBy(['flag_mobile' => true], ['name' => 'asc']);
|
|
$mfg_list = [];
|
|
foreach ($mfgs as $mfg)
|
|
{
|
|
$mfg_list[] = [
|
|
'id' => $mfg->getID(),
|
|
'name' => $mfg->getName(),
|
|
];
|
|
}
|
|
|
|
$data = [
|
|
'manufacturers' => $mfg_list
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function listVehicleMakes(Request $req, $mfg_id)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get manufacturer
|
|
$mfg = $em->getRepository(VehicleManufacturer::class)->find($mfg_id);
|
|
if ($mfg == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid vehicle manufacturer id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get makes
|
|
$vehicles = $em->getRepository(Vehicle::class)->findBy(
|
|
[
|
|
'flag_mobile' => true,
|
|
'manufacturer' => $mfg_id,
|
|
],
|
|
['make' => 'asc']
|
|
);
|
|
// $vehicles = $mfg->getVehicles();
|
|
$vlist = [];
|
|
foreach ($vehicles as $v)
|
|
{
|
|
$vlist[] = [
|
|
'id' => $v->getID(),
|
|
'make' => trim($v->getMake() . ' ' . $v->getModelYearFormatted(false)),
|
|
// 'make' => $v->getMake() . ' ' . $v->getModelYearFrom() . '-' . $v->getModelYearTo(),
|
|
];
|
|
}
|
|
|
|
$data = [
|
|
'manufacturer' => [
|
|
'id' => $mfg->getID(),
|
|
'name' => $mfg->getName(),
|
|
],
|
|
'makes' => $vlist,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function checkVehicleRequirements(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'make_id',
|
|
'name',
|
|
'plate_num',
|
|
'model_year',
|
|
'color',
|
|
'condition',
|
|
'fuel_type',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res;
|
|
|
|
// TODO: check valid plate number
|
|
// TODO: check valid fuel type (gas / diesel)
|
|
// TODO: check current battery id
|
|
// TODO: check condition (brand new / second-hand)
|
|
// TODO: check is_motolite and is_active (1 or 0)
|
|
// TODO: check warranty expiration date (YYYYMMDD)
|
|
// TODO: check model year coverage if it fits in between
|
|
|
|
return $res;
|
|
}
|
|
|
|
protected function setCustomerVehicleObject(Request $req, APIResult $res, CustomerVehicle $cv)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
|
// check customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res;
|
|
}
|
|
|
|
// get vehicle
|
|
$vehicle = $em->getRepository(Vehicle::class)->find($req->request->get('make_id'));
|
|
if ($vehicle == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid vehicle make id');
|
|
return $res;
|
|
}
|
|
|
|
$cv->setCustomer($cust)
|
|
->setVehicle($vehicle)
|
|
->setName($req->request->get('name'))
|
|
->setPlateNumber($req->request->get('plate_num'))
|
|
->setModelYear($req->request->get('model_year'))
|
|
->setColor($req->request->get('color'))
|
|
->setFuelType($this->normalizeString($req->request->get('fuel_type')))
|
|
->setStatusCondition($this->normalizeString($req->request->get('condition')));
|
|
|
|
// set warranty code and expiration
|
|
// TODO: check warranty requirements
|
|
if (!empty($req->request->get('wty_code')))
|
|
$cv->setWarrantyCode($req->request->get('wty_code'));
|
|
if (!empty($req->request->get('wty_expire')))
|
|
$cv->setWarrantyExpiration(new DateTime($req->request->get('wty_expire')));
|
|
|
|
// TODO: get current battery
|
|
|
|
// is motolite
|
|
if ($req->request->get('is_motolite') == 0)
|
|
$cv->setHasMotoliteBattery(false);
|
|
else
|
|
$cv->setHasMotoliteBattery(true);
|
|
|
|
// is active
|
|
if ($req->request->get('is_active') == 0)
|
|
$cv->setActive(false);
|
|
else
|
|
$cv->setActive(true);
|
|
|
|
// save
|
|
$em->persist($cv);
|
|
$em->flush();
|
|
|
|
// data
|
|
$data = [
|
|
'cv_id' => $cv->getID()
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res;
|
|
}
|
|
|
|
public function addVehicle(Request $req)
|
|
{
|
|
// check requirements
|
|
$res = $this->checkVehicleRequirements($req);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// customer vehicle
|
|
$cv = new CustomerVehicle();
|
|
|
|
$res = $this->setCustomerVehicleObject($req, $res, $cv);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function updateVehicle(Request $req, $id)
|
|
{
|
|
// check requirements
|
|
$res = $this->checkVehicleRequirements($req);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer vehicle
|
|
$em = $this->getDoctrine()->getManager();
|
|
$cv = $em->getRepository(CustomerVehicle::class)->find($id);
|
|
|
|
// check if it exists
|
|
if ($cv == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Vehicle does not exist');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check if it's owned by customer
|
|
if ($cv->getCustomer()->getID() != $this->session->getCustomer()->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid vehicle');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$res = $this->setCustomerVehicleObject($req, $res, $cv);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function getBatteryImageURL($req, $batt)
|
|
{
|
|
// TODO: workaround for now, we get static image of battery based on model name
|
|
$filename = trim(strtolower($batt->getModel()->getName())) . '_mobile.jpg';
|
|
$file_path = $req->getSchemeAndHttpHost() . $this->generateUrl('static_battery_image') . '/' . $filename;
|
|
|
|
return $file_path;
|
|
}
|
|
|
|
public function listVehicles(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// vehicles
|
|
$cv_list = [];
|
|
// $cvs = $cust->getVehicles();
|
|
// only get the customer's vehicles whose flag_active is true
|
|
$cvs = $em->getRepository(CustomerVehicle::class)->findBy(['flag_active' => true, 'customer' => $cust]);
|
|
foreach ($cvs as $cv)
|
|
{
|
|
$battery_id = null;
|
|
if ($cv->getCurrentBattery() != null)
|
|
$battery_id = $cv->getCurrentBattery()->getID();
|
|
|
|
$wty_ex = null;
|
|
if ($cv->getWarrantyExpiration() != null)
|
|
$wty_ex = $cv->getWarrantyExpiration()->format('Y-m-d');
|
|
|
|
$warranty = $this->findWarranty($cv->getPlateNumber());
|
|
|
|
$cv_name = '';
|
|
if ($cv->getName() != null)
|
|
$cv_name = $cv->getName();
|
|
|
|
$cv_list[] = [
|
|
'cv_id' => $cv->getID(),
|
|
'mfg_id' => $cv->getVehicle()->getManufacturer()->getID(),
|
|
'make_id' => $cv->getVehicle()->getID(),
|
|
'name' => $cv_name,
|
|
'plate_num' => $cv->getPlateNumber(),
|
|
'model_year' => $cv->getModelYear(),
|
|
'color' => $cv->getColor(),
|
|
'condition' => $cv->getStatusCondition(),
|
|
'fuel_type' => $cv->getFuelType(),
|
|
'wty_code' => $cv->getWarrantyCode(),
|
|
'wty_expire' => $wty_ex,
|
|
'curr_batt_id' => $battery_id,
|
|
'is_motolite' => $cv->hasMotoliteBattery() ? 1 : 0,
|
|
'is_active' => $cv->isActive() ? 1 : 0,
|
|
'warranty' => $warranty,
|
|
];
|
|
}
|
|
|
|
// data
|
|
$data = [
|
|
'vehicles' => $cv_list
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function listPromos(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getCompatibleBatteries(Request $req, $vid)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get vehicle
|
|
$vehicle = $em->getRepository(Vehicle::class)->find($vid);
|
|
if ($vehicle == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid vehicle');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// batteries
|
|
$batt_list = [];
|
|
// $batts = $vehicle->getBatteries();
|
|
$batts = $vehicle->getActiveBatteries();
|
|
foreach ($batts as $batt)
|
|
{
|
|
// TODO: Add warranty_tnv to battery information
|
|
$batt_list[] = [
|
|
'id' => $batt->getID(),
|
|
'mfg_id' => $batt->getManufacturer()->getID(),
|
|
'mfg_name' => $batt->getManufacturer()->getName(),
|
|
'model_id' => $batt->getModel()->getID(),
|
|
'model_name' => $batt->getModel()->getName(),
|
|
'size_id' => $batt->getSize()->getID(),
|
|
'size_name' => $batt->getSize()->getName(),
|
|
'price' => $batt->getSellingPrice(),
|
|
'wty_private' => $batt->getWarrantyPrivate(),
|
|
'wty_commercial' => $batt->getWarrantyCommercial(),
|
|
'image_url' => $this->getBatteryImageURL($req, $batt),
|
|
];
|
|
}
|
|
|
|
// data
|
|
$data = [
|
|
'vehicle' => [
|
|
'id' => $vehicle->getID(),
|
|
'mfg_id' => $vehicle->getManufacturer()->getID(),
|
|
'mfg_name' => $vehicle->getManufacturer()->getName(),
|
|
'make' => $vehicle->getMake(),
|
|
'model_year_from' => $vehicle->getModelYearFrom(),
|
|
'model_year_to' => $vehicle->getModelYearTo(),
|
|
],
|
|
'batteries' => $batt_list,
|
|
];
|
|
$res->setData($data);
|
|
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'service_type',
|
|
'cv_id',
|
|
// 'batt_id',
|
|
'trade_in',
|
|
'long',
|
|
'lat',
|
|
'warranty',
|
|
'mode_of_payment',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// trade in type
|
|
$trade_in = $req->request->get('trade_in');
|
|
|
|
// address
|
|
$address = $req->request->get('delivery_address', 'Set by mobile application');
|
|
|
|
// instructions
|
|
$instructions = $req->request->get('delivery_instructions', '');
|
|
|
|
// longitude and latitude
|
|
$long = $req->request->get('long');
|
|
$lat = $req->request->get('lat');
|
|
|
|
// geofence
|
|
$is_covered = $geo->isCovered($long, $lat);
|
|
if (!$is_covered)
|
|
{
|
|
// TODO: put geofence error message in config file somewhere
|
|
$res->setError(true)
|
|
->setErrorMessage($this->getGeoErrorMessage());
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$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)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$jo->setCustomer($cust);
|
|
|
|
// validate service type
|
|
$stype = $req->request->get('service_type');
|
|
if (!ServiceType::validate($stype))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid service type');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$jo->setServiceType($stype);
|
|
|
|
// validate warranty
|
|
$warr = $req->request->get('warranty');
|
|
if (!WarrantyClass::validate($warr))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid warranty class');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$jo->setWarrantyClass($warr);
|
|
|
|
// set coordinates
|
|
$point = new Point($long, $lat);
|
|
$jo->setCoordinates($point);
|
|
|
|
// make invoice criteria
|
|
$icrit = new InvoiceCriteria();
|
|
$icrit->setServiceType($stype);
|
|
|
|
// check promo
|
|
$promo_id = $req->request->get('promo_id');
|
|
if (!empty($promo_id))
|
|
{
|
|
$promo = $em->getRepository(Promo::class)->find($promo_id);
|
|
if ($promo == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid promo id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// put in criteria
|
|
$icrit->addPromo($promo);
|
|
}
|
|
|
|
// check customer vehicle
|
|
$cv = $em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id'));
|
|
if ($cv == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid customer vehicle id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$icrit->setCustomerVehicle($cv);
|
|
$jo->setCustomerVehicle($cv);
|
|
|
|
// check if customer owns vehicle
|
|
if ($cust->getID() != $cv->getCustomer()->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Customer does not own vehicle');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check battery
|
|
$batt_id = $req->request->get('batt_id');
|
|
if ($batt_id != null)
|
|
{
|
|
$batt = $em->getRepository(Battery::class)->find($batt_id);
|
|
if ($batt == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid battery id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
else
|
|
$batt = null;
|
|
|
|
/*
|
|
// put battery in criteria
|
|
$icrit->addBattery($batt);
|
|
*/
|
|
|
|
// check trade-in
|
|
// only allow motolite, other, none
|
|
switch ($trade_in)
|
|
{
|
|
case TradeInType::MOTOLITE:
|
|
case TradeInType::OTHER:
|
|
break;
|
|
|
|
default:
|
|
$trade_in = '';
|
|
break;
|
|
}
|
|
|
|
// right now, the app does not include trade-ins but this might change in the future
|
|
if (empty($trade_in))
|
|
$icrit->addEntry($batt, null, 1);
|
|
else
|
|
$icrit->addEntry($batt, $trade_in, 1);
|
|
|
|
// set if taxable
|
|
$icrit->setIsTaxable();
|
|
|
|
// 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
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../.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
|
|
}
|
|
}
|
|
}
|
|
|
|
$em->persist($jo);
|
|
$em->persist($invoice);
|
|
|
|
// add event log for JO
|
|
$event = new JOEvent();
|
|
$event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::CREATE)
|
|
->setJobOrder($jo);
|
|
$em->persist($event);
|
|
|
|
// check JO status
|
|
if ($jo->getStatus() == JOStatus::ASSIGNED)
|
|
{
|
|
// add event logs for hub and rider assignments
|
|
$hub_assign_event = new JOEvent();
|
|
$hub_assign_event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::HUB_ASSIGN)
|
|
->setJobOrder($jo);
|
|
|
|
$em->persist($hub_assign_event);
|
|
|
|
$rider_assign_event = new JOEvent();
|
|
$rider_assign_event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::RIDER_ASSIGN)
|
|
->setJobOrder($jo);
|
|
|
|
$em->persist($rider_assign_event);
|
|
|
|
// user mqtt event
|
|
$payload = [
|
|
'event' => 'outlet_assign'
|
|
];
|
|
$mclient->sendEvent($jo, $payload);
|
|
|
|
$rah->assignJobOrder($jo, $jo->getRider());
|
|
}
|
|
|
|
$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;
|
|
|
|
// make job order data
|
|
$data = [
|
|
'jo_id' => $jo->getID(),
|
|
'invoice' => $invoice_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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// set data
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getEstimate(Request $req, InvoiceGeneratorInterface $ic)
|
|
{
|
|
// $this->debugRequest($req);
|
|
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'service_type',
|
|
'cv_id',
|
|
// 'batt_id',
|
|
'trade_in',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// 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 = $em->getRepository(Promo::class)->find($promo_id);
|
|
if ($promo == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid promo id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// put in criteria
|
|
$icrit->addPromo($promo);
|
|
}
|
|
|
|
// check customer vehicle
|
|
$cv = $em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id'));
|
|
if ($cv == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid customer vehicle id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$icrit->setCustomerVehicle($cv);
|
|
|
|
// check if customer owns vehicle
|
|
if ($cust->getID() != $cv->getCustomer()->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Customer does not own vehicle');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check battery
|
|
$batt_id = $req->request->get('batt_id');
|
|
if ($batt_id != null)
|
|
{
|
|
$batt = $em->getRepository(Battery::class)->find($batt_id);
|
|
if ($batt == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid battery id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
else
|
|
$batt = null;
|
|
|
|
/*
|
|
// put battery in criteria
|
|
$icrit->addBattery($batt);
|
|
*/
|
|
|
|
// set taxable
|
|
$icrit->setIsTaxable(true);
|
|
|
|
// 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;
|
|
}
|
|
|
|
// right now, the app does not include trade-ins but this might change in the future
|
|
if (empty($trade_in))
|
|
$icrit->addEntry($batt, null, 1);
|
|
else
|
|
$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));
|
|
|
|
// set data
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getRiderStatus(Request $req, RiderTracker $rt)
|
|
{
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check if we have an ongoing job order
|
|
/*
|
|
$ongoing_jos = $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);
|
|
|
|
// $res->setData(['here' => count($ongoing_jos)]);
|
|
// return $res->getReturnResponse();
|
|
if (count($ongoing_jos) <= 0)
|
|
{
|
|
try
|
|
{
|
|
// check if the latest fulfilled jo they have needs rider rating
|
|
$query = $em->createQuery('select jo from App\Entity\JobOrder jo where jo.customer = :cust and jo.status = :status order by jo.date_fulfill desc');
|
|
$fulfill_jo = $query->setParameters([
|
|
'cust' => $cust,
|
|
'status' => JOStatus::FULFILLED,
|
|
])
|
|
->setMaxResults(1)
|
|
->getSingleResult();
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
// no pending
|
|
$res->setData([
|
|
'status' => APIRiderStatus::NO_PENDING_JO
|
|
]);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// we got a recently fulfilled job order
|
|
if ($fulfill_jo)
|
|
{
|
|
// check if the rider has been rated
|
|
if (!$fulfill_jo->hasRiderRating())
|
|
{
|
|
$dest = $fulfill_jo->getCoordinates();
|
|
|
|
$data = [
|
|
'jo_id' => $fulfill_jo->getID(),
|
|
'service_type' => $fulfill_jo->getServiceType(),
|
|
'destination' => [
|
|
'long' => $dest->getLongitude(),
|
|
'lat' => $dest->getLatitude(),
|
|
],
|
|
'delivery_address' => $fulfill_jo->getDeliveryAddress(),
|
|
'delivery_instructions' => $fulfill_jo->getDeliveryInstructions(),
|
|
];
|
|
|
|
$rider = $fulfill_jo->getRider();
|
|
|
|
// 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();
|
|
|
|
$data['status'] = APIRiderStatus::RIDER_RATING;
|
|
// default rider location to hub
|
|
$data['rider'] = [
|
|
'id' => $rider->getID(),
|
|
'name' => $rider->getFullName(),
|
|
'plate_num' => $rider->getPlateNumber(),
|
|
'contact_num' => $rider->getContactNumber(),
|
|
'image_url' => $image_url,
|
|
];
|
|
$res->setData($data);
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
|
|
|
|
// no pending
|
|
$res->setData([
|
|
'status' => APIRiderStatus::NO_PENDING_JO
|
|
]);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get first jo that's pending
|
|
$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:
|
|
$data['status'] = APIRiderStatus::OUTLET_ASSIGN;
|
|
$res->setData($data);
|
|
return $res->getReturnResponse();
|
|
case JOStatus::RIDER_ASSIGN:
|
|
$data['status'] = APIRiderStatus::RIDER_ASSIGN;
|
|
$res->setData($data);
|
|
return $res->getReturnResponse();
|
|
case JOStatus::ASSIGNED:
|
|
case JOStatus::IN_TRANSIT:
|
|
case JOStatus::IN_PROGRESS:
|
|
$rider = $jo->getRider();
|
|
// get rider coordinates from redis
|
|
$coord = $rt->getRiderLocation($rider->getID());
|
|
|
|
// 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();
|
|
|
|
$data['status'] = APIRiderStatus::RIDER_PICK_UP;
|
|
// TODO: fix this to actual location of rider
|
|
// default rider location to hub
|
|
$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()
|
|
]
|
|
];
|
|
$res->setData($data);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
|
|
|
|
$res->setData($data);
|
|
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
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 getOngoingJobOrders($cust)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
$ongoing_jos = $em->getRepository(JobOrder::class)->findBy([
|
|
'customer' => $cust,
|
|
'status' => [JOStatus::PENDING, JOStatus::RIDER_ASSIGN, JOStatus::IN_TRANSIT, JOStatus::ASSIGNED, JOStatus::IN_PROGRESS],
|
|
], ['date_schedule' => 'desc']);
|
|
|
|
return $ongoing_jos;
|
|
}
|
|
|
|
public function getOngoing(Request $req)
|
|
{
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
/*
|
|
// check if we have an ongoing job order
|
|
$ongoing_jos = $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,
|
|
];
|
|
}
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function addRiderRating(Request $req)
|
|
{
|
|
$required_params = [
|
|
'jo_id',
|
|
'rating',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get job order
|
|
$jo_id = $req->request->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 rider
|
|
$rider = $jo->getRider();
|
|
if ($rider == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No rider 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();
|
|
}
|
|
|
|
// TODO: check job order status, if it's complete
|
|
|
|
// add rider rating
|
|
$rating_num = $req->request->get('rating', -1);
|
|
|
|
// if rating is -1
|
|
if ($rating_num == -1)
|
|
{
|
|
$jo->setHasRiderRating();
|
|
$em->flush();
|
|
|
|
$res->setData([]);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
|
|
$rating = new RiderRating();
|
|
$rating->setRider($rider)
|
|
->setCustomer($cust)
|
|
->setJobOrder($jo)
|
|
->setRating($rating_num);
|
|
|
|
// rider rating comment
|
|
$comment = $req->request->get('comment');
|
|
if (!empty($comment))
|
|
$rating->setComment($comment);
|
|
|
|
// mark jo as rider rated already
|
|
$jo->setHasRiderRating();
|
|
|
|
$em->persist($rating);
|
|
$em->flush();
|
|
|
|
// TODO: set average rating in rider entity
|
|
|
|
$res->setData([]);
|
|
|
|
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();
|
|
}
|
|
|
|
$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;
|
|
|
|
// set data
|
|
$res->setData($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,
|
|
],
|
|
];
|
|
|
|
|
|
$res->setData($data);
|
|
*/
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function cancelJobOrder(Request $req, MQTTClient $mclient)
|
|
{
|
|
$required_params = [
|
|
'jo_id',
|
|
'reason'
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get job order
|
|
$jo_id = $req->request->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();
|
|
}
|
|
|
|
// 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);
|
|
$em->persist($event);
|
|
|
|
$em->flush();
|
|
|
|
// send mobile app event
|
|
$payload = [
|
|
'event' => 'cancelled',
|
|
'reason' => $cancel_reason,
|
|
'jo_id' => $jo->getID(),
|
|
];
|
|
// $mclient->sendEvent($jo, $payload);
|
|
$mclient->sendRiderEvent($jo, $payload);
|
|
|
|
|
|
$res->setData([]);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// we can't use param converter for now because we want to output the proper 404
|
|
public function getJobOrderInfo($id, Request $req, EntityManagerInterface $em, RiderTracker $rt)
|
|
{
|
|
// check required parameters and api key
|
|
$res = $this->checkParamsAndKey($req, $em, []);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get job order data
|
|
$jo = $em->getRepository(JobOrder::class)->find($id);
|
|
if ($jo == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No job order information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check if job order belongs to customer / user
|
|
if ($cust->getID() != $jo->getCustomer()->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No job order information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// put into job order data array
|
|
$jo_data = $this->generateJobOrderData($req, $jo, $rt);
|
|
|
|
|
|
$data = [
|
|
'job_order' => $jo_data
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
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'),
|
|
'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),
|
|
];
|
|
|
|
// 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;
|
|
}
|
|
|
|
public function getJOHistory(Request $req)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, []);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// 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 = $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;
|
|
}
|
|
|
|
// return data
|
|
$data = [
|
|
'job_orders' => $all_jo_data
|
|
];
|
|
$res->setData($data);
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function updateDeviceID(Request $req)
|
|
{
|
|
$required_params = [
|
|
'device_id',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$device_id = $req->request->get('device_id');
|
|
$this->session->setDevicePushID($device_id);
|
|
|
|
$em->flush();
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function resendCode(Request $req, RisingTideGateway $rt)
|
|
{
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// already confirmed
|
|
if ($this->session->isConfirmed())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('User is already confirmed.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// have sent code before
|
|
if ($this->session->getDateCodeSent() != null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Can only send confirm code every 5 mins.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
|
|
// TODO: send via sms
|
|
$phone_number = $this->session->getPhoneNumber();
|
|
$code = $this->session->getConfirmCode();
|
|
$this->sendConfirmationCode($rt, $phone_number, $code);
|
|
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function privacySettings(Request $req)
|
|
{
|
|
$required_params = [
|
|
'priv_third_party',
|
|
// 'priv_promo',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// set privacy settings
|
|
$priv_promo = $req->request->get('priv_promo', false);
|
|
$priv_third_party = $req->request->get('priv_third_party');
|
|
$cust->setPrivacyThirdParty($priv_third_party)
|
|
->setPrivacyPromo($priv_promo);
|
|
|
|
// get the policy ids from .env
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../.env');
|
|
|
|
$policy_promo_id = $_ENV['POLICY_PROMO'];
|
|
$policy_third_party_id = $_ENV['POLICY_THIRD_PARTY'];
|
|
|
|
// check if privacy settings are true
|
|
// if true, set the private policy for the customer
|
|
if ($priv_promo)
|
|
{
|
|
// find the promo policy
|
|
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_promo_id);
|
|
|
|
// set policy id
|
|
if ($policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyPromo($policy);
|
|
}
|
|
}
|
|
|
|
if ($priv_third_party)
|
|
{
|
|
// find the third party policy
|
|
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_third_party_id);
|
|
|
|
// set policy id
|
|
if ($policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyThirdParty($policy);
|
|
}
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function locationSupport(Request $req, GeofenceTracker $geo)
|
|
{
|
|
$required_params = [
|
|
'longitude',
|
|
'latitude',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$long = $req->query->get('longitude');
|
|
$lat = $req->query->get('latitude');
|
|
|
|
// NOTE: had to add this for promo tag
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$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);
|
|
}
|
|
|
|
// geofence
|
|
// $is_covered = $geo->isCovered($long, $lat);
|
|
|
|
$data = [
|
|
'longitude' => $long,
|
|
'latitude' => $lat,
|
|
'supported' => $is_covered,
|
|
];
|
|
$res->setData($data);
|
|
|
|
// check if is_covered is false. If so, we need to set the error part in the response
|
|
if (!$is_covered)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage($this->getGeoErrorMessage());
|
|
}
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function activateWarranty(Request $req)
|
|
{
|
|
$required_params = ['plate_number'];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$plate_number = $req->request->get('plate_number');
|
|
|
|
// find warranty using plate number
|
|
$warranty_results = $em->getRepository(Warranty::class)->findBy(['plate_number' => $plate_number],
|
|
['date_create' => 'desc']);
|
|
|
|
// check if warranty_results is empty
|
|
if (empty($warranty_results))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No warranty found for plate number');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// activate all entries
|
|
foreach ($warranty_results as $warranty)
|
|
{
|
|
$warranty->setActivated();
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function findWarranty($plate_number)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
// NOTE: Modify the search for the latest warranty. This seems hacky.
|
|
// get latest warranty using plate number
|
|
$warranty_results = $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;
|
|
}
|
|
|
|
public function listServices(Request $req)
|
|
{
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// services
|
|
$results = $em->getRepository(Service::class)->findAll();
|
|
if (empty($results))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No services available.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$services = [];
|
|
foreach ($results as $result)
|
|
{
|
|
/*
|
|
// get partners
|
|
$partners = [];
|
|
$service_partners = $result->getPartners();
|
|
foreach($service_partners as $sp)
|
|
{
|
|
$partners[] = [
|
|
'id' => $sp->getID(),
|
|
'name' => $sp->getName(),
|
|
'branch' => $sp->getBranch(),
|
|
'address' => $sp->getAddress(),
|
|
'contact_nums' => $sp->getContactNumbers(),
|
|
'time_open' => $sp->getTimeOpen()->format("g:i A"),
|
|
'time_close' => $sp->getTimeClose()->format("g:i A"),
|
|
];
|
|
}
|
|
*/
|
|
|
|
$services[] = [
|
|
'id' => $result->getID(),
|
|
'name' => $result->getName(),
|
|
// 'partners' => $partners,
|
|
];
|
|
}
|
|
|
|
$data['services'] = $services;
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getPartnerInformation(Request $req, $pid)
|
|
{
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get partner
|
|
$partner = $em->getRepository(Partner::class)->findOneBy(['id' => $pid]);
|
|
if ($partner == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No partner found.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get reviews for partner
|
|
$reviews = $em->getRepository(Review::class)->findBy(['partner' => $partner]);
|
|
|
|
// get average rating for all reviews
|
|
$average_rating = 0;
|
|
if (!empty($reviews))
|
|
{
|
|
$rating = 0;
|
|
foreach($reviews as $review)
|
|
{
|
|
$rating = $rating + $review->getRating();
|
|
}
|
|
|
|
$average_rating = $rating / sizeof($reviews);
|
|
}
|
|
|
|
$data['partner'] = [
|
|
'id' => $partner->getID(),
|
|
'name' => $partner->getName(),
|
|
'branch' => $partner->getBranch(),
|
|
'address' => $partner->getAddress(),
|
|
'contact_nums' => $partner->getContactNumbers(),
|
|
'time_open' => $partner->getTimeOpen()->format("g:i A"),
|
|
'time_close' => $partner->getTimeClose()->format("g:i A"),
|
|
'longitude' => $partner->getCoordinates()->getLongitude(),
|
|
'latitude' => $partner->getCoordinates()->getLatitude(),
|
|
'average_rating' => $average_rating,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getClosestPartners(Request $req)
|
|
{
|
|
$required_params = [
|
|
'longitude',
|
|
'latitude',
|
|
'service_id',
|
|
'limit',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$long = $req->query->get('longitude');
|
|
$lat = $req->query->get('latitude');
|
|
$service_id = $req->query->get('service_id');
|
|
$limit = $req->query->get('limit');
|
|
|
|
// get partners within range
|
|
$query = $em->createQuery('SELECT p, st_distance(p.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Partner p
|
|
JOIN App\Entity\Service s where s.id = :service_id ORDER BY dist')
|
|
->setParameter('lat', $lat)
|
|
->setParameter('lng', $long)
|
|
->setParameter('service_id', $service_id);
|
|
|
|
$query->setMaxResults($limit);
|
|
$result = $query->getResult();
|
|
|
|
$data = [];
|
|
$partners = [];
|
|
foreach($result as $row)
|
|
{
|
|
// get all the reviews for each partner and average the ratings
|
|
$partner_id = $row[0]->getID();
|
|
$partner = $em->getRepository(Partner::class)->find($partner_id);
|
|
$partner_reviews = $em->getRepository(Review::class)->findBy(['partner' => $partner]);
|
|
|
|
$average_rating = 0;
|
|
if (count($partner_reviews) > 0)
|
|
{
|
|
$rating = 0;
|
|
foreach ($partner_reviews as $review)
|
|
{
|
|
$rating = $rating + $review->getRating();
|
|
}
|
|
|
|
$average_rating = $rating / sizeof($partner_reviews);
|
|
}
|
|
|
|
$partners[] = [
|
|
'id' => $row[0]->getID(),
|
|
'name' => $row[0]->getName(),
|
|
'branch' => $row[0]->getBranch(),
|
|
'address' => $row[0]->getAddress(),
|
|
'contact_nums' => $row[0]->getContactNumbers(),
|
|
'time_open' => $row[0]->getTimeOpen()->format("g:i A"),
|
|
'time_close' => $row[0]->getTimeClose()->format("g:i A"),
|
|
'longitude' => $row[0]->getCoordinates()->getLongitude(),
|
|
'latitude' => $row[0]->getCoordinates()->getLatitude(),
|
|
'db_distance' => $row['dist'],
|
|
'rating' => $average_rating,
|
|
];
|
|
}
|
|
|
|
$data['partners'] = $partners;
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function reviewPartner($pid, Request $req, EntityManagerInterface $em)
|
|
{
|
|
$required_params = [
|
|
'rating',
|
|
'message',
|
|
];
|
|
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$rating = $req->request->get('rating');
|
|
$msg = $req->request->get('message');
|
|
|
|
// TODO: check rating if 1 - 5
|
|
|
|
// check if partner exists
|
|
$partner = $em->getRepository(Partner::class)->find($pid);
|
|
if ($partner == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No partner found.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$rev = new Review();
|
|
$rev->setRating($rating)
|
|
->setMessage($msg)
|
|
->setPartner($partner)
|
|
->setMobileSession($this->session);
|
|
|
|
// save to db
|
|
$em->persist($rev);
|
|
$em->flush();
|
|
|
|
$data = [];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getNearestHubAndSlots(Request $req, EntityManagerInterface $em,
|
|
MapTools $map_tools)
|
|
{
|
|
$required_params = [
|
|
'longitude',
|
|
'latitude',
|
|
];
|
|
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$coordinates = new Point($req->query->get('longitude'), $req->query->get('latitude'));
|
|
|
|
// add checking if customer has a pre-registered hub
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check if customer has customer tag 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, get the hub where customer is pre-registered
|
|
$car_club_cust_hub = $cust->getCarClubCustomerHub();
|
|
if ($car_club_cust_hub != null)
|
|
{
|
|
// need to get the rider slots for the pre-registered hub
|
|
$hub = $car_club_cust_hub->getHub();
|
|
$nearest_hub_slots = $this->findAdvanceNearestHubAndSlots($coordinates, $em, $map_tools, $hub);
|
|
}
|
|
else
|
|
{
|
|
$nearest_hub_slots = $this->findAdvanceNearestHubAndSlots($coordinates, $em, $map_tools);
|
|
|
|
if (empty($nearest_hub_slots['hub']))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Thank you for reaching out to us. Please expect a call from us and we will assist you with your request. Thank you and stay safe!');
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$nearest_hub_slots = $this->findAdvanceNearestHubAndSlots($coordinates, $em, $map_tools);
|
|
|
|
if (empty($nearest_hub_slots['hub']))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Thank you for reaching out to us. Please expect a call from us and we will assist you with your request. Thank you and stay safe!');
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
|
|
// make hub data
|
|
$data = [
|
|
'hub_id' => $nearest_hub_slots['hub']->getID(),
|
|
'hub_slots' => $nearest_hub_slots['slots'],
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
|
|
}
|
|
|
|
public function newRequestJobOrder(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)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'service_type',
|
|
'cv_id',
|
|
'trade_in',
|
|
'long',
|
|
'lat',
|
|
'warranty',
|
|
'mode_of_payment',
|
|
];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// trade in type
|
|
$trade_in = $req->request->get('trade_in');
|
|
|
|
// address
|
|
$address = $req->request->get('delivery_address', 'Set by mobile application');
|
|
|
|
// instructions
|
|
$instructions = $req->request->get('delivery_instructions', '');
|
|
|
|
// 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)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$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
|
|
$res->setError(true)
|
|
->setErrorMessage($this->getGeoErrorMessage());
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$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)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Book Now no longer available.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
if (strlen($hub_id) > 0)
|
|
$hub = $em->getRepository(Hub::class)->find($hub_id);
|
|
|
|
$schedule_date = $req->request->get('date_schedule');
|
|
$slot_id = $req->request->get('slot_id');
|
|
|
|
// 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)
|
|
->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();
|
|
// }
|
|
$jo->setCustomer($cust);
|
|
|
|
// validate service type
|
|
$stype = $req->request->get('service_type');
|
|
if (!ServiceType::validate($stype))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid service type');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$jo->setServiceType($stype);
|
|
|
|
// validate warranty
|
|
$warr = $req->request->get('warranty');
|
|
if (!WarrantyClass::validate($warr))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid warranty class');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$jo->setWarrantyClass($warr);
|
|
|
|
// set coordinates
|
|
$point = new Point($long, $lat);
|
|
$jo->setCoordinates($point);
|
|
|
|
// make invoice criteria
|
|
$icrit = new InvoiceCriteria();
|
|
$icrit->setServiceType($stype);
|
|
|
|
// set taxable
|
|
$icrit->setIsTaxable(true);
|
|
|
|
// check promo
|
|
$promo_id = $req->request->get('promo_id');
|
|
if (!empty($promo_id))
|
|
{
|
|
$promo = $em->getRepository(Promo::class)->find($promo_id);
|
|
if ($promo == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid promo id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// put in criteria
|
|
$icrit->addPromo($promo);
|
|
}
|
|
|
|
// check customer vehicle
|
|
$cv = $em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id'));
|
|
if ($cv == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid customer vehicle id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
$icrit->setCustomerVehicle($cv);
|
|
$jo->setCustomerVehicle($cv);
|
|
|
|
// check if customer owns vehicle
|
|
if ($cust->getID() != $cv->getCustomer()->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Customer does not own vehicle');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// check battery
|
|
$batt_id = $req->request->get('batt_id');
|
|
if ($batt_id != null)
|
|
{
|
|
$batt = $em->getRepository(Battery::class)->find($batt_id);
|
|
if ($batt == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid battery id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
}
|
|
else
|
|
$batt = null;
|
|
|
|
/*
|
|
// put battery in criteria
|
|
$icrit->addBattery($batt);
|
|
*/
|
|
|
|
// check trade-in
|
|
// only allow motolite, other, none
|
|
switch ($trade_in)
|
|
{
|
|
case TradeInType::MOTOLITE:
|
|
case TradeInType::OTHER:
|
|
break;
|
|
|
|
default:
|
|
$trade_in = '';
|
|
break;
|
|
}
|
|
|
|
// right now, the app does not include trade-ins but this might change in the future
|
|
if (empty($trade_in))
|
|
$icrit->addEntry($batt, null, 1);
|
|
else
|
|
$icrit->addEntry($batt, $trade_in, 1);
|
|
|
|
// send to invoice generator
|
|
$invoice = $ic->generateInvoice($icrit);
|
|
$jo->setInvoice($invoice);
|
|
|
|
// assign hub and rider
|
|
// check if hub is null
|
|
if ($hub == null)
|
|
{
|
|
// 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
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../.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);
|
|
}
|
|
|
|
$em->persist($jo);
|
|
$em->persist($invoice);
|
|
|
|
// add event log for JO
|
|
$event = new JOEvent();
|
|
$event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::CREATE)
|
|
->setJobOrder($jo);
|
|
$em->persist($event);
|
|
|
|
// check JO status
|
|
if ($jo->getStatus() == JOStatus::ASSIGNED)
|
|
{
|
|
// add event logs for hub and rider assignments
|
|
$hub_assign_event = new JOEvent();
|
|
$hub_assign_event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::HUB_ASSIGN)
|
|
->setJobOrder($jo);
|
|
|
|
$em->persist($hub_assign_event);
|
|
|
|
$rider_assign_event = new JOEvent();
|
|
$rider_assign_event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::RIDER_ASSIGN)
|
|
->setJobOrder($jo);
|
|
|
|
$em->persist($rider_assign_event);
|
|
|
|
// user mqtt event
|
|
$payload = [
|
|
'event' => 'outlet_assign'
|
|
];
|
|
$mclient->sendEvent($jo, $payload);
|
|
|
|
$rah->assignJobOrder($jo, $jo->getRider());
|
|
}
|
|
|
|
if ($jo->getStatus() == JOStatus::RIDER_ASSIGN)
|
|
{
|
|
// add event logs for hub assignments
|
|
$hub_assign_event = new JOEvent();
|
|
$hub_assign_event->setDateHappen(new DateTime())
|
|
->setTypeID(JOEventType::HUB_ASSIGN)
|
|
->setJobOrder($jo);
|
|
|
|
$em->persist($hub_assign_event);
|
|
|
|
// user mqtt event
|
|
$payload = [
|
|
'event' => 'outlet_assign'
|
|
];
|
|
$mclient->sendEvent($jo, $payload);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
// make invoice json data
|
|
$invoice_data = [
|
|
'total_price' => $invoice->getTotalPrice(),
|
|
'vat_ex_price' => (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;
|
|
|
|
// make job order data
|
|
$data = [
|
|
'jo_id' => $jo->getID(),
|
|
'invoice' => $invoice_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('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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// set data
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function versionCheck(Request $req)
|
|
{
|
|
$res = new APIResult();
|
|
|
|
$required_params = [
|
|
'version',
|
|
];
|
|
|
|
$missing = $this->checkMissingParameters($req, $required_params);
|
|
if (count($missing) > 0)
|
|
{
|
|
$params = implode(', ', $missing);
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing parameter(s): ' . $params);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$need_update = false;
|
|
$msg = 'Version is up to date.';
|
|
|
|
$api_version = $this->getParameter('api_version');
|
|
|
|
$app_version = $req->query->get('version');
|
|
// putting this in for the future, in case we have diverging versions
|
|
$os = $req->query->get('os');
|
|
$platform = $req->query->get('platform');
|
|
|
|
$api_v = explode('.', $api_version);
|
|
$app_v = explode('.', $app_version);
|
|
|
|
if ($api_v[0] < $app_v[0])
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid application version: ' . $app_version);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
if ($api_v[0] > $app_v[0])
|
|
{
|
|
$need_update = true;
|
|
$msg = 'Your version is outdated and needs an update to use the latest features RES-Q has to offer.';
|
|
}
|
|
|
|
|
|
$data = [
|
|
'need_update' => $need_update,
|
|
'message' => $msg,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function scheduleOptionStatus(Request $req)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$em = $this->getDoctrine()->getManager();
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
$schedule_choice = true;
|
|
|
|
// remove the time check after ECQ. This will then always return true
|
|
// get current time
|
|
$current_datetime = new DateTime();
|
|
//$current_datetime = DateTime::createFromFormat('Y-m-d H:i', '2020-04-30 17:01');
|
|
|
|
// get the hour
|
|
$hour = $current_datetime->format('G');
|
|
|
|
// commenting out the time check since we can now book 24/7
|
|
// this will get uncommented out if and when ECQ will kick in
|
|
//if (($hour < 8) || ($hour > 16))
|
|
// $schedule_choice = false;
|
|
|
|
// add checking if customer has a pre-registered hub
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
// check if customer has customer tag 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, get the hub where customer is pre-registered
|
|
$car_club_hub = $cust->getCarClubCustomerHub();
|
|
if ($car_club_hub != null)
|
|
{
|
|
$schedule_choice = false;
|
|
}
|
|
}
|
|
|
|
// schedule_choice will always be true aka customer can opt to
|
|
// Book Now or Schedule Order EXCEPT if customer has customer tag promo
|
|
// or ECQ comes back
|
|
$data = [
|
|
'display_schedule_choice' => $schedule_choice,
|
|
];
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function checkCustomerPlateNumber($plate_number, $cust)
|
|
{
|
|
// strip spaces and make all caps
|
|
$plate_number = preg_replace('/\s+/', '', strtoupper($plate_number));
|
|
|
|
// if there's no customer linked to session
|
|
if ($cust != null)
|
|
{
|
|
// check all the customer vehicles
|
|
$cvs = $cust->getVehicles();
|
|
foreach ($cvs as $cv)
|
|
{
|
|
$cv_plate = preg_replace('/\s+/', '', strtoupper($cv->getPlateNumber()));
|
|
|
|
// did we find a match?
|
|
if ($cv_plate == $plate_number)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// TODO: put this in a service
|
|
protected function cleanSerial($serial)
|
|
{
|
|
// trim and make everything upper case
|
|
$clean_serial = trim(strtoupper($serial));
|
|
|
|
|
|
// remove QR prefix if it exists
|
|
// $prefix = substr($clean_serial, 0, 2);
|
|
// if ($prefix == 'QR')
|
|
// $clean_serial = substr($clean_serial, 2);
|
|
|
|
return $clean_serial;
|
|
}
|
|
|
|
public function warrantyCheck($serial, EntityManagerInterface $em, Request $req, WarrantyRaffleLogger $raffle_logger)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// check if warranty serial is there
|
|
$serial = $this->cleanSerial($serial);
|
|
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
|
|
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
|
|
$batt = null;
|
|
$is_registered = false;
|
|
|
|
if ($warr_serial == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid warranty serial code.');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$today = new DateTime();
|
|
|
|
$user_id = $req->query->get('api_key');
|
|
$raffle_data = [
|
|
'user_id' => $user_id,
|
|
'serial' => $serial,
|
|
'warranty_id' => null,
|
|
'action' => '',
|
|
'bmodel_name' => '',
|
|
'bsize_name' => '',
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'plate_number' => '',
|
|
'contact_num' => '',
|
|
'email' => '',
|
|
'address' => '',
|
|
];
|
|
|
|
$data_sent = [];
|
|
|
|
// if we have a warranty entry for the serial already
|
|
if ($warr != null)
|
|
{
|
|
$warr_plate = $warr->getPlateNumber();
|
|
$is_registered = true;
|
|
$is_customer_warranty = false;
|
|
|
|
// check if the warranty is registered to a car owned by the customer
|
|
$cust = $this->session->getCustomer();
|
|
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
|
|
|
|
// null mobile number should be blank string instead
|
|
if ($warr->getMobileNumber() == null)
|
|
$mobile_num = '';
|
|
else
|
|
$mobile_num = $warr->getMobileNumber();
|
|
|
|
$can_edit = $is_customer_warranty;
|
|
|
|
// if customer plate number matches the one registered on the warranty
|
|
if ($is_customer_warranty)
|
|
{
|
|
// purchase date of customer
|
|
if ($warr->getDatePurchaseCustomer() != null)
|
|
$date_purchase_cust = $warr->getDatePurchaseCustomer()->format('Y-m-d');
|
|
else
|
|
$date_purchase_cust = $today->format('Y-m-d');
|
|
|
|
|
|
// invoice
|
|
if ($warr->getFileInvoice() != null)
|
|
$invoice_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileInvoice();
|
|
else
|
|
$invoice_url = '';
|
|
|
|
// warranty card
|
|
if ($warr->getFileWarrantyCard() != null)
|
|
$warr_card_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileWarrantyCard();
|
|
else
|
|
$warr_card_url = '';
|
|
|
|
$customer = [
|
|
'first_name' => $warr->getFirstName() ?? '',
|
|
'last_name' => $warr->getLastName() ?? '',
|
|
'mobile_number' => $mobile_num,
|
|
'plate_number' => $warr_plate,
|
|
'email' => $warr->getEmail() ?? '',
|
|
'contact_num' => $warr->getContactNumber() ?? '',
|
|
'address' => $warr->getCustomerAddress() ?? '',
|
|
];
|
|
$other_data = [
|
|
'odometer' => (int) $warr->getOdometer() ?? 0,
|
|
'date_purchase' => $date_purchase_cust,
|
|
'invoice' => $invoice_url,
|
|
'warr_card' => $warr_card_url,
|
|
'dealer_name' => $warr->getDealerName() ?? '',
|
|
'dealer_address' => $warr->getDealerAddress() ?? '',
|
|
'branch_code' => $warr->getDealerBranchCode() ?? '',
|
|
];
|
|
|
|
// set customer info and action for raffle log
|
|
$raffle_data['action'] = 'serial_check_customer';
|
|
$raffle_data['first_name'] = $customer['first_name'];
|
|
$raffle_data['last_name'] = $customer['last_name'];
|
|
$raffle_data['plate_number'] = $customer['plate_number'];
|
|
$raffle_data['email'] = $customer['email'];
|
|
$raffle_data['contact_num'] = $customer['contact_num'];
|
|
$raffle_data['address'] = $customer['address'];
|
|
$raffle_data['warranty_id'] = $warr->getID();
|
|
}
|
|
else
|
|
{
|
|
// hide customer information if customer is not the one registered
|
|
$customer = [
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'mobile_number' => '',
|
|
'plate_number' => '',
|
|
'email' => '',
|
|
'contact_num' => '',
|
|
'address' => '',
|
|
];
|
|
$other_data = [
|
|
'odometer' => 0,
|
|
'date_purchase' => $today->format('Y-m-d'),
|
|
'invoice' => '',
|
|
'warr_card' => '',
|
|
'dealer_name' => '',
|
|
'dealer_address' => '',
|
|
'branch_code' => '',
|
|
];
|
|
|
|
// set action for raffle log
|
|
$raffle_data['action'] = 'serial_check_not_customer';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$can_edit = true;
|
|
$customer = [
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'mobile_number' => '',
|
|
'plate_number' => '',
|
|
'email' => '',
|
|
'contact_num' => '',
|
|
'address' => '',
|
|
];
|
|
$other_data = [
|
|
'odometer' => 0,
|
|
'date_purchase' => $today->format('Y-m-d'),
|
|
'invoice' => '',
|
|
'warr_card' => '',
|
|
'dealer_name' => '',
|
|
'dealer_address' => '',
|
|
'branch_code' => '',
|
|
];
|
|
|
|
// set action for raffle log
|
|
$raffle_data['action'] = 'serial_check_customer';
|
|
}
|
|
|
|
$sku = $warr_serial->getSKU();
|
|
$batt = null;
|
|
$cat_name = '';
|
|
if ($sku != null)
|
|
$batt = $em->getRepository(SAPBattery::class)->find($sku);
|
|
else
|
|
{
|
|
// get the category name of the serial
|
|
$cat_name = $warr_serial->getMetaInfo('category_name');
|
|
}
|
|
|
|
// TODO: put this in a config file
|
|
$image_url = $req->getSchemeAndHttpHost() . '/battery/generic.png';
|
|
if ($batt != null)
|
|
{
|
|
$battery = [
|
|
'brand' => $batt->getBrand()->getName(),
|
|
'size' => $batt->getSize()->getName(),
|
|
'image_url' => $image_url,
|
|
];
|
|
}
|
|
else
|
|
{
|
|
$battery = [
|
|
'brand' => $cat_name,
|
|
'size' => '',
|
|
'image_url' => '',
|
|
];
|
|
}
|
|
|
|
// populate data
|
|
$data = [
|
|
'is_valid' => true,
|
|
'is_registered' => $is_registered,
|
|
'can_edit' => $can_edit,
|
|
'customer' => $customer,
|
|
'battery' => $battery,
|
|
'odometer' => $other_data['odometer'],
|
|
'invoice' => $other_data['invoice'],
|
|
'warr_card' => $other_data['warr_card'],
|
|
'date_purchase' => $other_data['date_purchase'],
|
|
'dealer_name' => $other_data['dealer_name'],
|
|
'dealer_address' => $other_data['dealer_address'],
|
|
'branch_code' => $other_data['branch_code'],
|
|
'message' => [
|
|
'register_error' => 'Warranty serial code has already been registered.',
|
|
'edit_error' => 'Sorry, warranty is registered under another vehicle not in your list of vehicles.',
|
|
],
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
// set the rest of the raffle log entry
|
|
$raffle_data['bmodel_name'] = $battery['brand'];
|
|
$raffle_data['bsize_name'] = $battery['size'];
|
|
|
|
// log the raffle log
|
|
$raffle_logger->logRaffleInfo($data_sent, $raffle_data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function handlePictureUpload($file, $target_dir, $serial, $name)
|
|
{
|
|
// error_log("handling $name upload");
|
|
// no file sent
|
|
if ($file == null)
|
|
{
|
|
error_log("handling $name upload - no file");
|
|
return null;
|
|
}
|
|
|
|
// create target dir if it doesn't exist
|
|
if (!file_exists($target_dir))
|
|
{
|
|
if (!mkdir($target_dir, 0744, true))
|
|
{
|
|
error_log('failed to create folder for warranty pictures');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// move file
|
|
$filename = $name . '.' . $file->getClientOriginalExtension();
|
|
$file->move($target_dir . '/' . $serial, $filename);
|
|
|
|
// error_log("filename - $filename");
|
|
// error_log($target_dir . '/' . $serial . '/' . $filename);
|
|
|
|
return $serial . '/' . $filename;
|
|
}
|
|
|
|
public function warrantyRegister($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt,
|
|
TranslatorInterface $trans, WarrantyRaffleLogger $raffle_logger, WarrantyAPILogger $logger)
|
|
{
|
|
// check required parameters and api key
|
|
$required_params = [
|
|
'first_name',
|
|
'last_name',
|
|
'plate_number',
|
|
'date_purchase',
|
|
];
|
|
|
|
// handle file uploads
|
|
$invoice = $req->files->get('invoice');
|
|
$warr_card = $req->files->get('warr_card');
|
|
|
|
// normalize serial
|
|
$serial = $this->cleanSerial($serial);
|
|
// $serial = trim(strtoupper($serial));
|
|
|
|
// process picture uploads
|
|
$upload_dir = $kernel->getProjectDir() . '/public/warranty_uploads';
|
|
$inv_filename = $this->handlePictureUpload($invoice, $upload_dir, $serial, 'invoice');
|
|
$wcard_filename = $this->handlePictureUpload($warr_card, $upload_dir, $serial, 'wcard');
|
|
|
|
$user_id = $req->query->get('api_key');
|
|
$log_data = [
|
|
'plate_number' => $req->request->get('plate_num'),
|
|
'first_name' => $req->request->get('first_name'),
|
|
'last_name' => $req->request->get('last_name'),
|
|
'date_purchase' => $req->request->get('date_purchase'),
|
|
];
|
|
$action = 'create/update';
|
|
$source = WarrantySource::MOBILE;
|
|
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
{
|
|
$logger->logWarrantyInfo($log_data, $res->getErrorMessage(), $user_id, $action, $source);
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// update customer information
|
|
// $cust = $this->updateCustomerInfo($req, $em);
|
|
|
|
// update warranty
|
|
$res = $this->updateWarranty($res, $em, $rt, $trans, $req, $serial, $inv_filename, $wcard_filename,
|
|
$logger, $log_data, $user_id, $action, $source, $raffle_logger);
|
|
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getAllOngoingJobOrders(EntityManagerInterface $em, Request $req, RiderTracker $rt)
|
|
{
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$ongoing_jos = $this->getOngoingJobOrders($cust);
|
|
|
|
// initialize data
|
|
$jo_data = [];
|
|
foreach ($ongoing_jos as $jo)
|
|
{
|
|
$jo_data[] = $this->generateJobOrderData($req, $jo, $rt);
|
|
}
|
|
|
|
$data = [
|
|
'ongoing_job_orders' => $jo_data,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getOngoingJobOrderCount(EntityManagerInterface $em, Request $req)
|
|
{
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$ongoing_jos = $this->getOngoingJobOrders($cust);
|
|
|
|
$data = [
|
|
'ongoing_job_order_count' => count($ongoing_jos),
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function addLocation(EntityManagerInterface $em, Request $req)
|
|
{
|
|
$required_params = [
|
|
'name',
|
|
'address',
|
|
'longitude',
|
|
'latitude',
|
|
'landmark',
|
|
];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get the information
|
|
$name = $req->request->get('name');
|
|
$address = $req->request->get('address');
|
|
$lng = $req->request->get('longitude');
|
|
$lat = $req->request->get('latitude');
|
|
$landmark = $req->request->get('landmark');
|
|
|
|
$loc_info = [
|
|
'address' => $address,
|
|
'longitude' => $lng,
|
|
'latitude' => $lat,
|
|
'landmark' => $landmark,
|
|
];
|
|
|
|
// check if customer already has existing metadata
|
|
$c_meta = $em->getRepository(CustomerMetadata::class)->findOneBy(['customer' => $cust]);
|
|
if ($c_meta == null)
|
|
{
|
|
// create new customer meta
|
|
$cust_meta = new CustomerMetadata();
|
|
$cust_meta->setCustomer($cust);
|
|
$cust_meta->addMetaInfo($name, $loc_info);
|
|
|
|
$em->persist($cust_meta);
|
|
}
|
|
else
|
|
{
|
|
// limit locations to 6. If more than 6, pop the first one out
|
|
// add location to existing customer meta
|
|
$meta_count = count($c_meta->getAllMetaInfo());
|
|
|
|
if ($meta_count >= 6)
|
|
$c_meta->popMetaInfo();
|
|
|
|
$c_meta->addMetaInfo($name, $loc_info);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getLocations(EntityManagerInterface $em, Request $req)
|
|
{
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get the customer meta for customer
|
|
$locations = [];
|
|
$cust_meta = $em->getRepository(CustomerMetadata::class)->findOneBy(['customer' => $cust]);
|
|
if ($cust_meta != null)
|
|
{
|
|
$locations[] = $cust_meta->getAllMetaInfo();
|
|
}
|
|
|
|
$data = [
|
|
'locations' => $locations,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function removeVehicle($id, EntityManagerInterface $em, Request $req)
|
|
{
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// find customer vehicle
|
|
$cv = $em->getRepository(CustomerVehicle::class)->find($id);
|
|
if ($cv == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid customer vehicle id');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// confirm that customer vehicle belongs to customer
|
|
if ($cv->getCustomer()->getID() != $cust->getID())
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Vehicle does not belong to customer');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// we cannot remove a vehicle from customer if customer vehicle has already has JOs for it.
|
|
// instead we set the customer vehicle's flag_active to false
|
|
$cv->setActive(false);
|
|
$em->flush();
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getLatestJobOrder(EntityManagerInterface $em, Request $req, RiderTracker $rt)
|
|
{
|
|
// check required parameters and api key
|
|
$res = $this->checkParamsAndKey($req, $em, []);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// get the latest job order for customer
|
|
$latest_jo = $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);
|
|
}
|
|
|
|
$data = [
|
|
'latest_job_order' => $jo_data,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
public function getCustomerHash(Request $req, EntityManagerInterface $em, HashGenerator $hash)
|
|
{
|
|
// check required parameters and api key
|
|
$res = $this->checkParamsAndKey($req, $em, []);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// hash customer id
|
|
$hashed_id = $hash->getHash($cust->getID());
|
|
|
|
$data = [
|
|
'cust_hash' => $hashed_id,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
// response
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
$required_params = [];
|
|
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
|
if ($res->isError())
|
|
return $res->getReturnResponse();
|
|
|
|
// get customer
|
|
$cust = $this->session->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('No customer information found');
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
$completed_jos = $this->getCompletedJOs($cust, $em);
|
|
|
|
// initialize data
|
|
$jo_data = [];
|
|
foreach ($completed_jos as $jo)
|
|
{
|
|
$jo_data[] = $this->generateJobOrderData($req, $jo, $rt);
|
|
}
|
|
|
|
$data = [
|
|
'completed_job_orders' => $jo_data,
|
|
];
|
|
|
|
$res->setData($data);
|
|
|
|
return $res->getReturnResponse();
|
|
}
|
|
|
|
protected function getCompletedJOs($cust, EntityManagerInterface $em)
|
|
{
|
|
$completed_jos = $em->getRepository(JobOrder::class)->findBy([
|
|
'customer' => $cust,
|
|
'status' => [JOStatus::CANCELLED, JOStatus::FULFILLED],
|
|
], ['date_schedule' => 'desc']);
|
|
|
|
return $completed_jos;
|
|
}
|
|
*/
|
|
|
|
protected function updateWarranty($res, $em, $rt, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null, $logger, $log_data, $user_id, $action, $source, $raffle_logger)
|
|
{
|
|
// prepare raffle log entry
|
|
$raffle_data = [
|
|
'user_id' => $user_id,
|
|
'serial' => $serial,
|
|
'warranty_id' => null,
|
|
'action' => '',
|
|
'bmodel_name' => '',
|
|
'bsize_name' => '',
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'plate_number' => '',
|
|
'contact_num' => '',
|
|
'email' => '',
|
|
'address' => '',
|
|
];
|
|
|
|
// get serial
|
|
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
|
|
if ($warr_serial == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid warranty serial code.');
|
|
$logger->logWarrantyInfo($log_data, $res->getErrorMessage(), $user_id, $action, $source);
|
|
return $res;
|
|
}
|
|
|
|
// check if warranty exists already
|
|
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
|
|
|
|
// skip warranty if it already exists
|
|
if ($warr != null)
|
|
{
|
|
/*
|
|
// NOTE: we could not update in the old version
|
|
$res->setError(true)
|
|
->setErrorMessage('Warranty registration entry already exists.');
|
|
return $res;
|
|
*/
|
|
|
|
// check if warranty is registered to a serial owned by customer
|
|
$warr_plate = $warr->getPlateNumber();
|
|
$cust = $this->session->getCustomer();
|
|
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
|
|
|
|
if (!$is_customer_warranty)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Warranty registered to a vehicle not in your list of vehicles.');
|
|
// set action to update
|
|
$action = 'update';
|
|
$logger->logWarrantyInfo($log_data, $res->getErrorMessage(), $user_id, $action, $source);
|
|
return $res;
|
|
}
|
|
|
|
$sms_msg = $trans->trans('warranty_update_confirm');
|
|
|
|
// update raffle data action
|
|
$raffle_data['action'] = 'warranty_update';
|
|
}
|
|
else
|
|
{
|
|
$warr = new Warranty();
|
|
$sms_msg = $trans->trans('warranty_register_confirm');
|
|
|
|
// set warranty source
|
|
$warr->setCreateSource($source);
|
|
|
|
// update raffle data action
|
|
$raffle_data['action'] = 'warranty_create';
|
|
}
|
|
|
|
// get sap battery
|
|
$sku = $warr_serial->getSKU();
|
|
$sap_bty = null;
|
|
if ($sku != null)
|
|
{
|
|
$sap_bty = $em->getRepository(SAPBattery::class)->find($sku);
|
|
if ($sap_bty == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Could not find battery entry for warranty.');
|
|
$logger->logWarrantyInfo($log_data, $res->getErrorMessage(), $user_id, $action, $source);
|
|
return $res;
|
|
}
|
|
}
|
|
|
|
// default date purchase to today
|
|
// NOTE: might need to change this later
|
|
$date_pur = new DateTime();
|
|
|
|
// get date purchase specified by customer
|
|
$date_pur_cust = DateTime::createFromFormat('Y-m-d', $req->request->get('date_purchase'));
|
|
if (!$date_pur_cust)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid date format for date of purchase.');
|
|
$logger->logWarrantyInfo($log_data, $res->getErrorMessage(), $user_id, $action, $source);
|
|
return $res;
|
|
}
|
|
|
|
$customer = $this->session->getCustomer();
|
|
if ($customer != null)
|
|
{
|
|
$warr->setCustomer($customer);
|
|
// get customer vehicles
|
|
|
|
$vehicle = $this->findCustomerVehicle($em, $customer, $req->request->get('plate_number'));
|
|
if ($vehicle != null)
|
|
$warr->setVehicle($vehicle);
|
|
}
|
|
|
|
// TODO: make a standard clean plate number service
|
|
// clean plate number
|
|
$plate = $req->request->get('plate_number');
|
|
// upper case and remove spaces
|
|
$plate = strtoupper(str_replace(' ', '', $plate));
|
|
// remove special characters
|
|
$plate = preg_replace('/[^A-Za-z0-9. -]/', '', $plate);
|
|
|
|
// create or update warranty entry
|
|
$warr->setSerial($serial)
|
|
->setFirstName($req->request->get('first_name'))
|
|
->setLastName($req->request->get('last_name'))
|
|
->setEmail($req->request->get('email'))
|
|
->setPlateNumber($plate)
|
|
// TODO: figure out how to compute date of purchase
|
|
->setDatePurchase($date_pur)
|
|
// TODO: set status
|
|
// ->setStatus()
|
|
// TODO: set battery model and size id
|
|
// ->setBatterySize()
|
|
// ->setBatteryModel()
|
|
->setSAPBattery($sap_bty)
|
|
->setMobileNumber(substr($this->session->getPhoneNumber(), 2))
|
|
->setActivated(true)
|
|
|
|
// files
|
|
->setFileInvoice($inv_filename)
|
|
->setFileWarrantyCard($wcard_filename)
|
|
|
|
// new fields
|
|
->setOdometer($req->request->get('odometer', 0))
|
|
->setDatePurchaseCustomer($date_pur_cust)
|
|
->setContactNumber($req->request->get('contact_num'))
|
|
->setCustomerAddress($req->request->get('cust_address'))
|
|
->setDealerName($req->request->get('dealer_name'))
|
|
->setDealerAddress($req->request->get('dealer_address'))
|
|
->setDealerBranchCode($req->request->get('branch_code'))
|
|
->setValidated(false);
|
|
|
|
// TODO: check for date purchase and date expire
|
|
|
|
$em->persist($warr);
|
|
|
|
// TODO: check if we need to do anyting else
|
|
$data = [];
|
|
|
|
// set data to retrun to user
|
|
$res->setData($data);
|
|
|
|
$logger->logWarrantyInfo($log_data, '', $user_id, $action, $source);
|
|
|
|
// send sms
|
|
// error_log('sending sms to - ' . $this->session->getPhoneNumber());
|
|
$rt->sendSMS($this->session->getPhoneNumber(), $trans->trans('message.battery_brand_allcaps'), $sms_msg);
|
|
|
|
// prepare the rest of the raffle log entry
|
|
$raffle_data['warranty_id'] = $warr->getID();
|
|
$raffle_data['bmodel_name'] = $sap_bty->getBrand()->getName();
|
|
$raffle_data['bsize_name'] = $sap_bty->getSize()->getName();
|
|
$raffle_data['first_name'] = $req->request->get('first_name', '');
|
|
$raffle_data['last_name'] = $req->request->get('last_name', '');
|
|
$raffle_data['plate_number'] = $plate;
|
|
$raffle_data['contact_num'] = $req->request->get('contact_num', '');
|
|
$raffle_data['email'] = $req->request->get('email', '');
|
|
$raffle_data['address'] = $req->request->get('cust_address', '');
|
|
|
|
$data_sent = [
|
|
'plate_number' => $req->request->get('plate_number'),
|
|
'first_name' => $req->request->get('first_name'),
|
|
'last_name' => $req->request->get('last_name'),
|
|
'date_purchase' => $req->request->get('date_purchase'),
|
|
'address' => $req->request->get('cust_address', ''),
|
|
'email' => $req->request->get('email', ''),
|
|
'contact_num' => $req->request->get('contact_num', ''),
|
|
];
|
|
|
|
// log raffle data
|
|
$raffle_logger->logRaffleInfo($data_sent, $raffle_data);
|
|
|
|
return $res;
|
|
}
|
|
|
|
protected function findCustomerByNumber($number)
|
|
{
|
|
$em = $this->getDoctrine()->getManager();
|
|
$customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]);
|
|
|
|
// find the customer with the most number of cars
|
|
$car_count = 0;
|
|
$cust = null;
|
|
|
|
foreach($customers as $customer)
|
|
{
|
|
$vehicles = $customer->getVehicles();
|
|
if (count($vehicles) > $car_count)
|
|
{
|
|
$car_count = count($vehicles);
|
|
|
|
// "save" customer object
|
|
$cust = $customer;
|
|
}
|
|
}
|
|
|
|
return $cust;
|
|
}
|
|
|
|
protected function findCustomerVehicle($em, $customer, $plate_number)
|
|
{
|
|
$clean_plate = Warranty::cleanPlateNumber($plate_number);
|
|
if ($clean_plate)
|
|
{
|
|
// find the customer vehicle and get the vehicle
|
|
$cv = $em->getRepository(CustomerVehicle::class)->findOneBy(['plate_number' => $clean_plate, 'customer' => $customer]);
|
|
if ($cv != null)
|
|
{
|
|
$vehicle = $cv->getVehicle();
|
|
return $vehicle;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function findNearestHub($jo, EntityManagerInterface $em, MapTools $map_tools)
|
|
{
|
|
// get the nearest 10 hubs
|
|
$selected_hub = null;
|
|
$hubs = $map_tools->getClosestOpenHubs($jo->getCoordinates(), 10, date("H:i:s"));
|
|
|
|
$nearest_hubs_with_distance = [];
|
|
$nearest_branch_codes = [];
|
|
foreach ($hubs as $hub)
|
|
{
|
|
$nearest_hubs_with_distance[] = $hub;
|
|
//if (!empty($hub['hub']->getBranchCode()))
|
|
// $nearest_branch_codes[] = $hub['hub']->getBranchCode();
|
|
}
|
|
|
|
// check if nearest hubs have branch codes
|
|
//if (count($nearest_branch_codes) == 0)
|
|
// return $selected_hub;
|
|
|
|
// assume all 10 have stock
|
|
// find the nearest hub with available riders
|
|
$nearest = null;
|
|
foreach ($nearest_hubs_with_distance as $nhd)
|
|
{
|
|
// get number of available riders
|
|
$count_riders = count($nhd['hub']->getAvailableRiders());
|
|
|
|
// get number of advance orders in the next 3 hours
|
|
$time_now = new DateTime();
|
|
$date_end = new DateTime();
|
|
$date_end->add(new DateInterval('PT2H'));
|
|
|
|
// NOTE: get advance orders via query
|
|
// get JOs assigned to hub that are advance orders and scheduled within X hours with
|
|
// for rider assignment status
|
|
$query = $em->createQuery('select count(jo) from App\Entity\JobOrder jo where jo.hub = :hub and jo.flag_advance = true and jo.date_schedule <= :date_end and jo.status = :status');
|
|
$count_advance_orders = $query->setParameters([
|
|
'hub' => $nhd['hub'],
|
|
'date_end' => $date_end,
|
|
'status' => JOStatus::RIDER_ASSIGN,
|
|
])
|
|
->setMaxResults(1)
|
|
->getSingleScalarResult();
|
|
|
|
// error_log('HUB - ' . $nhd['hub']->getID());
|
|
// error_log('RIDER COUNT - ' . $count_riders);
|
|
// error_log('ADVANCE ORDER COUNT - ' . $count_advance_orders);
|
|
|
|
// if (count($nhd['hub']->getAvailableRiders()) > 0)
|
|
// if we have more riders than we have advance orders
|
|
if ($count_riders - $count_advance_orders > 0)
|
|
{
|
|
if (empty($nearest))
|
|
$nearest = $nhd;
|
|
else
|
|
{
|
|
if ($nhd['distance'] < $nearest['distance'])
|
|
$nearest = $nhd;
|
|
}
|
|
}
|
|
}
|
|
|
|
$selected_hub = $nearest['hub'];
|
|
|
|
return $selected_hub;
|
|
}
|
|
|
|
protected function findNearestHubWithInventory($jo, Battery $batt, EntityManagerInterface $em,
|
|
MapTools $map_tools, InventoryManager $im)
|
|
{
|
|
// get the nearest 10 hubs
|
|
$selected_hub = null;
|
|
$hubs = $map_tools->getClosestOpenHubs($jo->getCoordinates(), 10, date("H:i:s"));
|
|
|
|
$nearest_hubs_with_distance = [];
|
|
$nearest_branch_codes = [];
|
|
foreach ($hubs as $hub)
|
|
{
|
|
$nearest_hubs_with_distance[] = $hub;
|
|
//if (!empty($hub['hub']->getBranchCode()))
|
|
// $nearest_branch_codes[] = $hub['hub']->getBranchCode();
|
|
}
|
|
|
|
// check if nearest hubs have branch codes
|
|
//if (count($nearest_branch_codes) == 0)
|
|
// return $selected_hub;
|
|
|
|
// assume all 10 have stock
|
|
// find the nearest hub with available riders
|
|
$nearest = null;
|
|
foreach ($nearest_hubs_with_distance as $nhd)
|
|
{
|
|
if (count($nhd['hub']->getAvailableRiders()) > 0)
|
|
{
|
|
if (empty($nearest))
|
|
$nearest = $nhd;
|
|
else
|
|
{
|
|
if ($nhd['distance'] < $nearest['distance'])
|
|
$nearest = $nhd;
|
|
}
|
|
}
|
|
}
|
|
|
|
$selected_hub = $nearest['hub'];
|
|
|
|
// uncomment this snippet when inventory check becomes active
|
|
// get battery sku
|
|
/*
|
|
if ($batt != null)
|
|
{
|
|
$skus[] = $batt->getSAPCode();
|
|
|
|
// api call to check inventory
|
|
// pass the list of branch codes of nearest hubs and the skus
|
|
// go through returned list of branch codes
|
|
// bypass inventory check for now
|
|
// $hubs_with_inventory = $im->getBranchesInventory($nearest_branch_codes, $skus);
|
|
if (!empty($hubs_with_inventory))
|
|
{
|
|
$nearest = [];
|
|
$flag_hub_found = false;
|
|
foreach ($hubs_with_inventory as $hub_with_inventory)
|
|
{
|
|
// find hub according to branch code
|
|
$found_hub = $em->getRepository(Hub::class)->findOneBy(['branch_code' => $hub_with_inventory['BranchCode']]);
|
|
if ($found_hub != null)
|
|
{
|
|
// check rider availability
|
|
if (count($found_hub->getAvailableRiders()) > 0)
|
|
{
|
|
// check against nearest hubs with distance
|
|
foreach ($nearest_hubs_with_distance as $nhd)
|
|
{
|
|
// get distance of hub from location, compare with $nearest. if less, replace nearest
|
|
if ($found_hub->getID() == $nhd['hub']->getID())
|
|
{
|
|
if (empty($nearest))
|
|
{
|
|
$nearest = $nhd;
|
|
$flag_hub_found = true;
|
|
}
|
|
else
|
|
{
|
|
if ($nhd['distance'] < $nearest['distance'])
|
|
{
|
|
$nearest = $nhd;
|
|
$flag_hub_found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$selected_hub = $nearest['hub'];
|
|
}
|
|
} */
|
|
return $selected_hub;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
protected function findAdvanceNearestHubAndSlots(Point $coordinates, EntityManagerInterface $em, MapTools $map_tools, $hub=null)
|
|
{
|
|
$hub_data = [];
|
|
|
|
if ($hub != null)
|
|
{
|
|
// get the slots of hub
|
|
$hub_slots = $this->getHubRiderSlots($hub, $em);
|
|
|
|
$slots = $hub_slots['slot_data'];
|
|
|
|
$hub_data = [
|
|
'hub' => $hub,
|
|
'slots' => $slots,
|
|
];
|
|
return $hub_data;
|
|
}
|
|
|
|
// get the nearest 10 hubs
|
|
$nearest_hubs_with_distance = [];
|
|
$hubs = $map_tools->getClosestOpenHubs($coordinates, 10);
|
|
|
|
foreach ($hubs as $hub)
|
|
{
|
|
$nearest_hubs_with_distance[] = $hub;
|
|
// TODO: insert checking for branch code here when inventory manager is up
|
|
}
|
|
|
|
$nearest = null;
|
|
$hub_slots = [];
|
|
$slot_found = false;
|
|
// find the nearest hub
|
|
if (!empty($nearest_hubs_with_distance))
|
|
{
|
|
// get slots of nearest hub right after getting nearest hub.
|
|
// then check if hub has available slots. If not, get next nearest hub.
|
|
foreach ($nearest_hubs_with_distance as $nhd)
|
|
{
|
|
if (empty($nearest))
|
|
{
|
|
// get the slots for the hub to check if hub is available for assignment
|
|
$hub_slots = $this->getHubRiderSlots($nhd['hub'], $em);
|
|
|
|
$flag_hub_available = $hub_slots['flag_hub_available'];
|
|
if ($flag_hub_available == true)
|
|
{
|
|
$nearest = $nhd;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($nhd['distance'] < $nearest['distance'])
|
|
{
|
|
// get the slots for nearest which is nhd right now
|
|
$hub_slots = $this->getHubRiderSlots($nhd['hub'], $em);
|
|
|
|
$flag_hub_available = $hub_slots['flag_hub_available'];
|
|
|
|
// if hub is available, set hub to nearest
|
|
if ($flag_hub_available == true)
|
|
{
|
|
$nearest = $nhd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($nearest != null)
|
|
{
|
|
// set hub data to what is in nearest
|
|
$hub_data = [
|
|
'hub' => $nearest['hub'],
|
|
'slots' => $hub_slots['slot_data'],
|
|
];
|
|
}
|
|
|
|
return $hub_data;
|
|
|
|
}
|
|
|
|
protected function getHubRiderSlots(Hub $hub, EntityManagerInterface $em)
|
|
{
|
|
// check hub's advance orders for the day
|
|
|
|
/*
|
|
// get number of advance orders for the next day if request came in before midnight
|
|
// or for current day if request came in after midnight
|
|
// check request_time
|
|
$request_time = time();
|
|
$midnight = strtotime('00:00');
|
|
*/
|
|
$start_date = new DateTime();
|
|
$end_date = new DateTime();
|
|
|
|
// to keep things simple, just start on next day regardless of midnight timer
|
|
$start_date->add(new DateInterval('P1D'));
|
|
$end_date->add(new DateInterval('P3D'));
|
|
|
|
/*
|
|
if ($request_time < $midnight)
|
|
{
|
|
// add +1 to start date to get the next day
|
|
// add +3 to date to end date to get the advance orders for the next three days
|
|
$start_date->add(new DateInterval('P1D'));
|
|
$end_date->add(new DateInterval('P1D'));
|
|
}
|
|
$end_date->add(new DateInterval('P2D'));
|
|
*/
|
|
|
|
// set time bounds for the start and end date
|
|
$start_date->setTime(0, 1);
|
|
$end_date->setTime(23, 59);
|
|
|
|
// NOTE: get advance orders via query
|
|
// get JOs assigned to hub that are advance orders and scheduled for the next three days with
|
|
// for hub assignment status
|
|
$query = $em->createQuery('select jo from App\Entity\JobOrder jo where jo.hub = :hub and jo.flag_advance = true and
|
|
jo.date_schedule >= :date_start and jo.date_schedule <= :date_end and jo.status != :status_cancelled
|
|
and jo.status != :status_fulfilled');
|
|
$jos_advance_orders = $query->setParameters([
|
|
'hub' => $hub,
|
|
'date_start' => $start_date,
|
|
'date_end' => $end_date,
|
|
'status_cancelled' => JOStatus::CANCELLED,
|
|
'status_fulfilled' => JOStatus::FULFILLED,
|
|
])
|
|
->getResult();
|
|
// check request_time
|
|
|
|
// define slots
|
|
$slots = [
|
|
'08_09' => '8:00 AM',
|
|
'09_10' => '9:00 AM',
|
|
'10_11' => '10:00 AM',
|
|
'11_12' => '11:00 AM',
|
|
'12_13' => '12:00 PM',
|
|
'13_14' => '1:00 PM',
|
|
'14_15' => '2:00 PM',
|
|
'15_16' => '3:00 PM',
|
|
'16_17' => '4:00 PM',
|
|
];
|
|
|
|
|
|
// get the dates for the next three days
|
|
$first_date = $start_date->format('Y-m-d');
|
|
$second_date = $start_date->add(new DateInterval('P1D'));
|
|
$sec_date = $second_date->format('Y-m-d');
|
|
$third_date = $end_date->format('Y-m-d');
|
|
|
|
// define days
|
|
$days = [
|
|
$first_date => $first_date,
|
|
$sec_date => $sec_date,
|
|
$third_date => $third_date,
|
|
];
|
|
|
|
// initialize hub rider slots
|
|
$hub_rider_slots = [];
|
|
foreach ($days as $day)
|
|
{
|
|
foreach ($slots as $slot_key => $slot)
|
|
{
|
|
$hub_rider_slots[$day][$slot_key] = $hub->getRiderSlots();
|
|
}
|
|
}
|
|
|
|
// check each JO's date_schedule, decrement rider_slots if date schedule falls in that slot
|
|
foreach ($jos_advance_orders as $jo)
|
|
{
|
|
// get date key
|
|
$date_sched = $jo->getDateSchedule();
|
|
$date_string = $date_sched->format('Y-m-d');
|
|
$hour = $date_sched->format('H');
|
|
$slot_id = sprintf('%02d_%02d', $hour, $hour + 1);
|
|
|
|
// error_log("SLOT - $date_string - $slot_id");
|
|
|
|
// decrement rider slot
|
|
if (isset($hub_rider_slots[$date_string][$slot_id]))
|
|
$hub_rider_slots[$date_string][$slot_id]--;
|
|
|
|
// check if it goes through next slot (10 min allowance)
|
|
$mins = $date_sched->format('i');
|
|
if ($mins > 10)
|
|
{
|
|
$next_slot_id = sprintf('%02d_%02d', $hour + 1, $hour + 2);
|
|
// error_log("NEXT SLOT - $date_string - $next_slot_id");
|
|
// decrement rider slot
|
|
if (isset($hub_rider_slots[$date_string][$next_slot_id]))
|
|
$hub_rider_slots[$date_string][$next_slot_id]--;
|
|
|
|
}
|
|
}
|
|
|
|
// error_log(print_r($hub_rider_slots, true));
|
|
|
|
$hub_slots = $this->generateHubSlots($hub_rider_slots, $slots);
|
|
|
|
// error_log(print_r($hub_slots, true));
|
|
|
|
return $hub_slots;
|
|
}
|
|
|
|
protected function generateHubSlots($rider_slots, $slots)
|
|
{
|
|
$data = [];
|
|
$total_rslots = 0;
|
|
$total_unavailable_rslots = 0;
|
|
foreach ($rider_slots as $day_id => $rslot)
|
|
{
|
|
$data[$day_id] = [];
|
|
|
|
foreach ($rslot as $slot_id => $avail_slots)
|
|
{
|
|
// increment total rider slots
|
|
$total_rslots++;
|
|
|
|
$slot_data = [
|
|
'id' => $slot_id,
|
|
'label' => $slots[$slot_id],
|
|
'available' => true,
|
|
];
|
|
|
|
// mark unavailable ones
|
|
if ($avail_slots <= 0)
|
|
{ // increment total number of unavailable slots
|
|
$total_unavailable_rslots++;
|
|
$slot_data['available'] = false;
|
|
}
|
|
|
|
// add to day data
|
|
$data[$day_id][] = $slot_data;
|
|
}
|
|
}
|
|
|
|
// check if hub has available slots
|
|
$hub_available = true;
|
|
// error_log('total rider slots ' . $total_rslots);
|
|
// error_log('total unavailable slots ' . $total_unavailable_rslots);
|
|
if ($total_rslots == $total_unavailable_rslots)
|
|
{
|
|
// error_log('hub has no available slots');
|
|
$hub_available = false;
|
|
}
|
|
|
|
$hs_data = [
|
|
'flag_hub_available' => $hub_available,
|
|
'slot_data' => $data,
|
|
];
|
|
|
|
return $hs_data;
|
|
}
|
|
|
|
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 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 normalizeString($string)
|
|
{
|
|
return trim(strtolower($string));
|
|
}
|
|
|
|
protected function getGeoErrorMessage() {
|
|
return 'Oops! Our service is limited to some areas in Metro Manila, Laguna, Cavite, Pampanga and Baguio only. We will update you as soon as we are able to cover your area';
|
|
}
|
|
}
|