Merge branch 'master' into 111-sms-feature-for-security-code
Conflicts: src/Controller/APIController.php
This commit is contained in:
commit
e93fec2811
19 changed files with 1074 additions and 13 deletions
|
|
@ -23,6 +23,10 @@ security:
|
|||
pattern: ^\/api\/
|
||||
security: false
|
||||
|
||||
rider_api:
|
||||
pattern: ^\/rapi\/
|
||||
security: false
|
||||
|
||||
main:
|
||||
form_login:
|
||||
login_path: login
|
||||
|
|
|
|||
|
|
@ -104,3 +104,13 @@ api_device_id:
|
|||
path: /api/device_id
|
||||
controller: App\Controller\APIController:updateDeviceID
|
||||
methods: [POST]
|
||||
|
||||
api_privacy:
|
||||
path: /api/privacy
|
||||
controller: App\Controller\APIController:privacySettings
|
||||
methods: [POST]
|
||||
|
||||
api_resend_code:
|
||||
path: /api/resend_code
|
||||
controller: App\Controller\APIController:resendCode
|
||||
methods: [POST]
|
||||
|
|
|
|||
41
config/routes/rider_api.yaml
Normal file
41
config/routes/rider_api.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# rider app api
|
||||
|
||||
rapi_register:
|
||||
path: /rapi/register
|
||||
controller: App\Controller\RAPIController::register
|
||||
methods: [POST]
|
||||
|
||||
rapi_login:
|
||||
path: /rapi/login
|
||||
controller: App\Controller\RAPIController::login
|
||||
methods: [POST]
|
||||
|
||||
rapi_logout:
|
||||
path: /rapi/logout
|
||||
controller: App\Controller\RAPIController::logout
|
||||
methods: [POST]
|
||||
|
||||
rapi_jo_get:
|
||||
path: /rapi/joborder
|
||||
controller: App\Controller\RAPIController::getJobOrder
|
||||
methods: [GET]
|
||||
|
||||
rapi_jo_accept:
|
||||
path: /rapi/accept
|
||||
controller: App\Controller\RAPIController::acceptJobOrder
|
||||
methods: [POST]
|
||||
|
||||
rapi_jo_cancel:
|
||||
path: /rapi/cancel
|
||||
controller: App\Controller\RAPIController::cancelJobOrder
|
||||
methods: [POST]
|
||||
|
||||
rapi_arrive:
|
||||
path: /rapi/arrive
|
||||
controller: App\Controller\RAPIController::arrive
|
||||
methods: [POST]
|
||||
|
||||
rapi_payment:
|
||||
path: /rapi/payment
|
||||
controller: App\Controller\RAPIController::payment
|
||||
methods: [POST]
|
||||
117
public/static/privacy.html
Normal file
117
public/static/privacy.html
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<h3>Privacy Policy</h3>
|
||||
<p>
|
||||
Oriental and Motolite Marketing Corporation ("Company," "We," "Us," "Our"), is committed to protecting the privacy and security of all personal and/or sensitive information ("Personal Data") related to its employees, customers, business partners, suppliers, contractors, and other parties that the Company will and is engaged into. For this reason, uniform practice and procedure for collecting, recording, consolidating, updating, disclosing, storing, accessing, transferring, retaining, destroying and disposing of Personal Data by the Company is hereby adopted in order to process Personal Data fairly, appropriately, and lawfully.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This Privacy Policy sets out how the Company uses, protects and controls any Personal Data that you will provide in our website and mobile application (the "Site"). The Company may change this policy from time to time by updating it in accordance with subsequent Laws and Implementing Rules and Regulations. The terms of this Privacy Policy apply to all users of this Site.
|
||||
</p>
|
||||
|
||||
<h3>Collection of Personal Data</h3>
|
||||
<p>
|
||||
The Company collects Personal Data you voluntarily submitted in our Site and our mobile apps, as well as non-personal information provided therein.
|
||||
</p>
|
||||
|
||||
<h3>User Registration</h3>
|
||||
<p>
|
||||
We collect information about you (i) when you register in order to receive a product/service; (ii) when you subscribe to marketing emails; (iii) when you apply for a job post; (iv) when you contact us for inquiries, support or feedback. Information may include Personal Data such as but not limited to your first name, last name, email address, birthdate, gender, mobile number, address and password.
|
||||
</p>
|
||||
|
||||
<h3>Log information</h3>
|
||||
<p>
|
||||
When you visit our Site, we may also collect non-personal information such as but not limited to web page from which you came to our Site, your web page request, Internet Protocol (IP) address, geolocation, browser type, browser language, the date and time of your request and your registration data. Please be noted that when you purchase a product or use a web-based service in our Site, we may also log the specific path, actions, and navigation choices you make.
|
||||
</p>
|
||||
|
||||
<h3>Cookies</h3>
|
||||
<p>
|
||||
We may use cookies in analyzing and evaluating performance to provide you better experience when using our Site. Cookies are small files that a Site or its service provider transfers to your computer's hard drive through your web browser (you can disable this) that allows the Site's or service provider's systems to recognize your browser and capture and remember certain information.
|
||||
</p>
|
||||
|
||||
<h3>Location Services</h3>
|
||||
<p>
|
||||
Your current location is only determined if you permit our services to do so. If you allow your location to be obtained using our RESQ app, or with a browser, we will use this information to return your estimated location. We use this information solely to distinguish your current location and not to identify you. Motolite does not automatically track your location.
|
||||
</p>
|
||||
|
||||
<h3>Use of Personal Data</h3>
|
||||
<p>
|
||||
<ul>
|
||||
<li>The Company uses your Personal Data for the following purposes, without limitation:</li>
|
||||
<li>to deliver or improve our products and services</li>
|
||||
<li>to administer a content, promotion, survey or other Site feature</li>
|
||||
<li>to send periodic emails regarding your account or other products and services</li>
|
||||
<li>to process your application for any of our job posts</li>
|
||||
<li>to process your application for a franchise</li>
|
||||
<li>to effectively respond to your customer service requests and support needs.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Company may share the Personal Data gathered from you within the Ramcar Group of Companies and will use it consistent with the purpose of this Privacy Policy. We may also use the information in the aggregate to understand how our users as a group, use the services and resources provided on our Site.
|
||||
</p>
|
||||
|
||||
<h3>Further Disclosure</h3>
|
||||
<p>
|
||||
We take reasonable precautions to be sure that nonaffiliated third parties and affiliates, to whom we disclose your Personal Data are aware of our Privacy Policy and will treat the information in a similarly responsible manner. Our contracts and written agreements with nonaffiliated third parties that receive information from us about you prohibit those parties from transferring the information other than to provide the service that you obtain from us.
|
||||
</p>
|
||||
|
||||
<h3>Agents and contractors</h3>
|
||||
<p>
|
||||
Our contractors sometimes have access to your Personal Data in the course of assisting in operating our business and providing products or services to you. These contractors may include vendors and suppliers that provide us with technology, services, and/or content for the operation and maintenance of our Site. Access to your Personal Data by these contractors is limited to the information reasonably necessary for the contractor to perform its limited function. Contractors have an obligation under their contracts with us to keep your information confidential and to comply with our privacy and security policies.
|
||||
</p>
|
||||
|
||||
<h3>Disclosure for legal reasons</h3>
|
||||
<p>
|
||||
We may release Personal Data to third parties: (1) to comply with valid legal requirements such as a law, regulation, search warrant, subpoena or court order; or (2) in special cases, such as a threat to security, a threat to our system or network, or cases in which we believe it is reasonably necessary to investigate or prevent harm, fraud, abuse, or illegal conduct.
|
||||
</p>
|
||||
|
||||
<h3>Changes in our corporate structure</h3>
|
||||
<p>
|
||||
If all or part of the Company is sold, merged or otherwise transferred to another entity, the Personal Data you have provided to us may be transferred as part of that transaction. We will take steps to ensure that, without your consent, any Personal Data that is transferred will not be used or shared in a manner inconsistent with this Privacy Policy.
|
||||
</p>
|
||||
|
||||
<h3>Accuracy and Access</h3>
|
||||
<p>
|
||||
The Company will keep your Personal Data as accurate, complete and up-to-date as is necessary for the purpose for which it is processed. In case you need to access, correct, amend, delete inaccurate Personal Data, or withdraw your consent, please immediately inform us. (see Contact Us section below)
|
||||
</p>
|
||||
|
||||
<h3>Security</h3>
|
||||
<p>
|
||||
The Company employs adequate organizational, physical and technical security measures such as password protection, encryption, firewalls and other controls, to ensure and preserve the confidentiality, integrity and availability of your Personal Data. We work to protect the security of your information during transmission by using Secure Sockets Layer (SSL) software, which encrypts information you input online. Only authorized persons from the Company will have access to your Personal Data. Employees who misuse any information are subject to disciplinary action, including termination.
|
||||
</p>
|
||||
|
||||
<h3>Third Party Links</h3>
|
||||
<p>
|
||||
The Company may offer links to sites that is run by third parties. If you visit other sites, you should read the site’s privacy policy, terms and conditions, and their other policies. The Company is not responsible for the policies and practices of third parties. Any information you give to those organizations is dealt with under their privacy statement, terms and conditions, and other policies.
|
||||
|
||||
<h3>Retention and Disposal</h3>
|
||||
<p>
|
||||
The Company will retain your Personal Data only as long as necessary for the fulfillment of the stated purposes. In case that the Site is no longer functional or decommissioned, all of your Personal Data in digital or hard copies will be disposed or erased according to the Company's guidelines, where it is irretrievable, unreadable, or unidentifiable. In case you subscribed to email/SMS marketing, you will still receive email/SMS notifications. If you want to cancel your subscription, you may click the unsubscribe link at the bottom of any email message from the Company, or follow the SMS cancellation instructions.
|
||||
</p>
|
||||
|
||||
<h3>Minors' Privacy</h3>
|
||||
<p>
|
||||
The Company takes minors' privacy seriously. If you are under 18 years of age, please do not submit any Personal Data through our Site without the express consent and participation of a parent or guardian. If you are a parent or guardian, please make every effort to guard your children's privacy.
|
||||
</p>
|
||||
|
||||
<h3>Applicable Law and Rights</h3>
|
||||
<p>
|
||||
The Company upholds compliance with Republic Act No. 10173 or the Data Privacy Act of 2012 (DPA), its Implementing Rules and Regulations, and other relevant policies, including issuances of the National Privacy Commission. The Company acknowledges your right to be informed, object processing, access and rectify, suspend or withdraw Personal Data, and be indemnified in case of damages pursuant to the provisions of DPA.
|
||||
</p>
|
||||
|
||||
<h3>Changes to Privacy Policy</h3>
|
||||
<p>
|
||||
The Company reserves the right to amend this Privacy Policy at any time, consistent with applicable law. In such case, an updated version will be posted in our Site. If we are going to process your Personal Data in a manner different from that stated at the time of collection, we will notify you, and you will have a choice as to whether or not we can use your Personal Data in such a way.
|
||||
</p>
|
||||
|
||||
<h3>Contact Us</h3>
|
||||
<p>
|
||||
For any inquiry regarding this Privacy Policy, please contact our Data Privacy Officer, Mr. Luis Quiogue at:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
OMMC<br>
|
||||
Ramcar Center<br>
|
||||
80-82 Roces Ave.<br>
|
||||
Diliman, Quezon City PH<br>
|
||||
(+632) 370-1100
|
||||
</p>
|
||||
|
|
@ -227,6 +227,24 @@ class APIController extends Controller
|
|||
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
|
||||
|
|
@ -253,6 +271,16 @@ class APIController extends Controller
|
|||
$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);
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
|
||||
// response
|
||||
|
|
@ -317,6 +345,9 @@ class APIController extends Controller
|
|||
->setLastName($req->request->get('last_name'))
|
||||
->setConfirmed($this->session->isConfirmed());
|
||||
|
||||
// update mobile phone of customer
|
||||
$cust->setPhoneMobile(substr(2, $this->session->getPhoneNumber()));
|
||||
|
||||
$em->flush();
|
||||
|
||||
return $res->getReturnResponse();
|
||||
|
|
@ -395,7 +426,8 @@ class APIController extends Controller
|
|||
{
|
||||
$vlist[] = [
|
||||
'id' => $v->getID(),
|
||||
'make' => $v->getMake() . ' ' . $v->getModelYearFrom() . '-' . $v->getModelYearTo(),
|
||||
'make' => trim($v->getMake() . ' ' . $v->getModelYearFormatted(false)),
|
||||
// 'make' => $v->getMake() . ' ' . $v->getModelYearFrom() . '-' . $v->getModelYearTo(),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -1197,6 +1229,11 @@ class APIController extends Controller
|
|||
->setJobOrder($jo)
|
||||
->setRating($rating_num);
|
||||
|
||||
// rider rating comment
|
||||
$comment = $req->request->get('comment');
|
||||
if (!empty($comment))
|
||||
$rating->setComment($comment);
|
||||
|
||||
$em->persist($rating);
|
||||
$em->flush();
|
||||
|
||||
|
|
@ -1364,4 +1401,63 @@ class APIController extends Controller
|
|||
// response
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function resendCode(Request $req)
|
||||
{
|
||||
$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
|
||||
|
||||
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
|
||||
$cust->setPrivacyThirdParty($req->request->get('priv_third_party'))
|
||||
->setPrivacyPromo($req->request->get('priv_promo'));
|
||||
|
||||
$em->flush();
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1364,15 +1364,20 @@ class JobOrderController extends BaseController
|
|||
|
||||
protected function sendEvent(JobOrder $job_order, $payload)
|
||||
{
|
||||
$session = $job_order->getCustomer()->getMobileSessions();
|
||||
if (count($session) == 0)
|
||||
$sessions = $job_order->getCustomer()->getMobileSessions();
|
||||
if (count($sessions) == 0)
|
||||
return;
|
||||
|
||||
$phone_num = $session[0]->getPhoneNumber();
|
||||
$channel = 'motolite.control.' . $phone_num;
|
||||
$client = new MosquittoClient();
|
||||
$client->connect('localhost', 1883);
|
||||
$client->publish($channel, json_encode($payload));
|
||||
|
||||
foreach ($sessions as $sess)
|
||||
{
|
||||
$phone_num = $sess->getPhoneNumber();
|
||||
$channel = 'motolite.control.' . $phone_num;
|
||||
$client->publish($channel, json_encode($payload));
|
||||
}
|
||||
|
||||
$client->disconnect();
|
||||
}
|
||||
|
||||
|
|
@ -1783,6 +1788,14 @@ class JobOrderController extends BaseController
|
|||
// save
|
||||
$em->flush();
|
||||
|
||||
// send mobile app event
|
||||
$payload = [
|
||||
'event' => 'cancelled',
|
||||
'reason' => $cancel_reason,
|
||||
'jo_id' => $obj->getID(),
|
||||
];
|
||||
$this->sendEvent($obj, $payload);
|
||||
|
||||
// return successful response
|
||||
return $this->json([
|
||||
'success' => 'Job order has been cancelled!'
|
||||
|
|
|
|||
453
src/Controller/RAPIController.php
Normal file
453
src/Controller/RAPIController.php
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
|
||||
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\Service\InvoiceCreator;
|
||||
|
||||
use App\Entity\RiderSession;
|
||||
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\Rider;
|
||||
use App\Entity\User;
|
||||
|
||||
use DateTime;
|
||||
|
||||
|
||||
// Rider API controller
|
||||
class RAPIController extends Controller
|
||||
{
|
||||
protected $session;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// one device = one session, since we have control over the devices
|
||||
// when a rider logs in, we just change the rider assigned to the device
|
||||
// when a rider logs out, we remove the rider assigned to the device
|
||||
$this->session = null;
|
||||
}
|
||||
|
||||
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(RiderSession::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_number',
|
||||
'device_push_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 RiderSession();
|
||||
$sess->setPhoneNumber($req->request->get('phone_number'))
|
||||
->setDevicePushID($req->request->get('device_push_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();
|
||||
}
|
||||
|
||||
public function login(Request $req, EncoderFactoryInterface $ef)
|
||||
{
|
||||
$required_params = [
|
||||
'user',
|
||||
'pass',
|
||||
];
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// check if session has a rider already
|
||||
if ($this->session->hasRider())
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('Another rider is already logged in. Please logout first.');
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
// look for rider with username
|
||||
$rider = $em->getRepository(Rider::class)->findOneBy(['username' => $req->request->get('user')]);
|
||||
if ($rider == null)
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('Invalid username or password.');
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
// check if rider password is correct
|
||||
$encoder = $ef->getEncoder(new User());
|
||||
if (!$encoder->isPasswordValid($rider->getPassword(), $req->request->get('pass'), ''))
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('Invalid username or password.');
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
// assign rider to session
|
||||
$this->session->setRider($rider);
|
||||
|
||||
// TODO: log rider logging in
|
||||
|
||||
$em->flush();
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function logout(Request $req)
|
||||
{
|
||||
$required_params = [];
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// remove rider from session
|
||||
$this->session->setRider(null);
|
||||
|
||||
// TODO: log rider logging out
|
||||
|
||||
$em->flush();
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function getJobOrder(Request $req)
|
||||
{
|
||||
// get the job order of the rider assigned to this session
|
||||
$required_params = [];
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// are we logged in?
|
||||
if (!$this->session->hasRider())
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('No logged in rider.');
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
$rider = $this->session->getRider();
|
||||
|
||||
// do we have a job order?
|
||||
$jo = $rider->getActiveJobOrder();
|
||||
if ($jo == null)
|
||||
{
|
||||
$data = [
|
||||
'job_order' => null
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$coord = $jo->getCoordinates();
|
||||
$cust = $jo->getCustomer();
|
||||
$cv = $jo->getCustomerVehicle();
|
||||
$v = $cv->getVehicle();
|
||||
$inv = $jo->getInvoice();
|
||||
|
||||
// invoice items
|
||||
$inv_items = [];
|
||||
foreach ($inv->getItems() as $item)
|
||||
{
|
||||
$inv_items[] = [
|
||||
'id' => $item->getID(),
|
||||
'title' => $item->getTitle(),
|
||||
'qty' => $item->getQuantity(),
|
||||
'price' => $item->getPrice(),
|
||||
];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'job_order' => [
|
||||
'id' => $jo->getID(),
|
||||
'service_type' => $jo->getServiceType(),
|
||||
'date_schedule' => $jo->getDateSchedule()->format('Ymd'),
|
||||
'longitude' => $coord->getLongitude(),
|
||||
'latitude' => $coord->getLatitude(),
|
||||
'status' => $jo->getStatus(),
|
||||
'customer' => [
|
||||
'title' => $cust->getTitle(),
|
||||
'first_name' => $cust->getFirstName(),
|
||||
'last_name' => $cust->getLastName(),
|
||||
'phone_mobile' => $cust->getPhoneMobile(),
|
||||
],
|
||||
'vehicle' => [
|
||||
'manufacturer' => $v->getManufacturer()->getName(),
|
||||
'make' => $v->getMake(),
|
||||
'model' => $cv->getModelYear(),
|
||||
'plate_number' => $cv->getPlateNumber(),
|
||||
'color' => $cv->getColor(),
|
||||
],
|
||||
'delivery_instructions' => $jo->getDeliveryInstructions(),
|
||||
'delivery_address' => $jo->getDeliveryAddress(),
|
||||
'landmark' => $jo->getLandmark(),
|
||||
'invoice' => [
|
||||
'discount' => $inv->getDiscount(),
|
||||
'trade_in' => $inv->getTradeIn(),
|
||||
'total_price' => $inv->getTotalPrice(),
|
||||
'vat' => $inv->getVat(),
|
||||
'items' => $inv_items,
|
||||
],
|
||||
'mode_of_payment' => $jo->getModeOfPayment(),
|
||||
|
||||
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
$res->setData($data);
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
protected function checkJO(Request $req, $required_params)
|
||||
{
|
||||
// set jo status to in transit
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$res = $this->checkParamsAndKey($req, $em, $required_params);
|
||||
if ($res->isError())
|
||||
return $res;
|
||||
|
||||
// are we logged in?
|
||||
if (!$this->session->hasRider())
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('No logged in rider.');
|
||||
return $res;
|
||||
}
|
||||
|
||||
$rider = $this->session->getRider();
|
||||
|
||||
// check if we have an active JO
|
||||
$jo = $rider->getActiveJobOrder();
|
||||
if ($jo == null)
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('No active job order.');
|
||||
return $res;
|
||||
}
|
||||
|
||||
// check if the jo_id sent is the same as our active jo
|
||||
if ($req->request->get('jo_id') != $jo->getID())
|
||||
{
|
||||
$res->setError(true)
|
||||
->setErrorMessage('Job order selected is not active job order.');
|
||||
return $res;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function acceptJobOrder(Request $req)
|
||||
{
|
||||
$required_params = ['jo_id'];
|
||||
$res = $this->checkJO($req, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// TODO: refactor this into a jo handler class, so we don't have to repeat for control center
|
||||
|
||||
// set jo status to in transit
|
||||
$jo->setStatus(JOStatus::IN_TRANSIT);
|
||||
|
||||
// TODO: send mqtt event
|
||||
|
||||
// TODO: add event
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function cancelJobOrder(Request $req)
|
||||
{
|
||||
$required_params = ['jo_id'];
|
||||
$res = $this->checkJO($req, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// TODO: refactor this into a jo handler class, so we don't have to repeat for control center
|
||||
|
||||
// set jo status to cancelled
|
||||
$jo->setStatus(JOStatus::CANCELLED);
|
||||
|
||||
// TODO: send mqtt event
|
||||
|
||||
// TODO: add event
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function arrive(Request $req)
|
||||
{
|
||||
$required_params = ['jo_id'];
|
||||
$res = $this->checkJO($req, $required_params);
|
||||
if ($res->isError())
|
||||
return $res->getReturnResponse();
|
||||
|
||||
// TODO: refactor this into a jo handler class, so we don't have to repeat for control center
|
||||
|
||||
// set jo status to in progress
|
||||
$jo->setStatus(JOStatus::IN_PROGRESS);
|
||||
|
||||
// TODO: send mqtt event
|
||||
|
||||
// TODO: add event
|
||||
|
||||
return $res->getReturnResponse();
|
||||
}
|
||||
|
||||
public function payment(Request $req)
|
||||
{
|
||||
// set invoice to paid
|
||||
|
||||
// set jo status to fulfilled
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ use App\Ramcar\DayOfWeek;
|
|||
use App\Entity\Rider;
|
||||
use App\Entity\RiderSchedule;
|
||||
use App\Entity\Hub;
|
||||
use App\Entity\User;
|
||||
use App\Service\FileUploader;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
|
|
@ -14,6 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
|
||||
use DateTime;
|
||||
|
||||
|
|
@ -154,7 +156,8 @@ class RiderController extends BaseController
|
|||
->setContactNumber($req->request->get('contact_no'))
|
||||
->setPlateNumber($req->request->get('plate_number'))
|
||||
->setImageFile($req->request->get('image_file'))
|
||||
->setActive($req->request->get('flag_active') ? true : false);
|
||||
->setActive($req->request->get('flag_active') ? true : false)
|
||||
->setUsername($req->request->get('username'));
|
||||
}
|
||||
|
||||
public function addSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator)
|
||||
|
|
@ -176,6 +179,24 @@ class RiderController extends BaseController
|
|||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// get password inputs
|
||||
$password = $req->request->get('password');
|
||||
$confirm_password = $req->request->get('confirm_password');
|
||||
|
||||
// custom validation for password fields
|
||||
if (!$password) {
|
||||
$error_array['password'] = 'This value should not be blank.';
|
||||
} else if ($password != $confirm_password) {
|
||||
$error_array['confirm_password'] = 'Passwords do not match.';
|
||||
} else {
|
||||
// encode password
|
||||
$enc = $ef->getEncoder(new User());
|
||||
$encoded_password = $enc->encodePassword($req->request->get('password'), '');
|
||||
|
||||
// set password
|
||||
$obj->setPassword($encoded_password);
|
||||
}
|
||||
|
||||
// custom validation for associations
|
||||
$hub_id = $req->request->get('hub');
|
||||
|
||||
|
|
@ -303,6 +324,24 @@ class RiderController extends BaseController
|
|||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// get password inputs
|
||||
$password = $req->request->get('password');
|
||||
$confirm_password = $req->request->get('confirm_password');
|
||||
|
||||
// custom validation for password fields
|
||||
if ($password || $confirm_password) {
|
||||
if ($password != $confirm_password) {
|
||||
$error_array['confirm_password'] = 'Passwords do not match.';
|
||||
} else {
|
||||
// encode password
|
||||
$enc = $ef->getEncoder(new User());
|
||||
$encoded_password = $enc->encodePassword($req->request->get('password'), '');
|
||||
|
||||
// set password
|
||||
$obj->setPassword($encoded_password);
|
||||
}
|
||||
}
|
||||
|
||||
// custom validation for associations
|
||||
$hub_id = $req->request->get('hub');
|
||||
|
||||
|
|
|
|||
|
|
@ -131,6 +131,16 @@ class Customer
|
|||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
protected $priv_third_party;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
protected $priv_promo;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->numbers = new ArrayCollection();
|
||||
|
|
@ -152,6 +162,9 @@ class Customer
|
|||
$this->phone_fax = '';
|
||||
|
||||
$this->email = '';
|
||||
|
||||
$this->priv_third_party = 0;
|
||||
$this->priv_promo = 0;
|
||||
}
|
||||
|
||||
public function getID()
|
||||
|
|
@ -379,4 +392,26 @@ class Customer
|
|||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setPrivacyThirdParty($bool = true)
|
||||
{
|
||||
$this->priv_third_party = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrivacyThirdParty()
|
||||
{
|
||||
return $this->priv_third_party;
|
||||
}
|
||||
|
||||
public function setPrivacyPromo($bool = true)
|
||||
{
|
||||
$this->priv_promo = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrivacyPromo()
|
||||
{
|
||||
return $this->priv_promo;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,13 +167,16 @@ class CustomerVehicle
|
|||
// remove spaces
|
||||
$plate_number = str_replace(' ', '', $plate_number);
|
||||
|
||||
// upper case
|
||||
$plate_number = strtoupper($plate_number);
|
||||
|
||||
$this->plate_number = $plate_number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPlateNumber()
|
||||
{
|
||||
return $this->plate_number;
|
||||
return strtoupper($this->plate_number);
|
||||
}
|
||||
|
||||
public function setModelYear($model_year)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ class MobileSession
|
|||
*/
|
||||
protected $date_confirmed;
|
||||
|
||||
// date and time that the confirmation code was last sent
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true)
|
||||
*/
|
||||
protected $date_code_sent;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -88,6 +94,7 @@ class MobileSession
|
|||
$this->customer = null;
|
||||
$this->confirm_flag = false;
|
||||
$this->date_confirmed = null;
|
||||
$this->date_code_sent = null;
|
||||
}
|
||||
|
||||
public function generateKeyID()
|
||||
|
|
@ -204,4 +211,15 @@ class MobileSession
|
|||
{
|
||||
return $this->date_confirmed;
|
||||
}
|
||||
|
||||
public function setDateCodeSent(DateTime $date)
|
||||
{
|
||||
$this->date_code_sent = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateCodeSent()
|
||||
{
|
||||
return $this->date_code_sent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
use App\Ramcar\JOStatus;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="rider")
|
||||
|
|
@ -92,6 +94,18 @@ class Rider
|
|||
*/
|
||||
protected $flag_active;
|
||||
|
||||
// username for rider api
|
||||
/**
|
||||
* @ORM\Column(type="string", length=80, unique=true, nullable=true)
|
||||
*/
|
||||
protected $username;
|
||||
|
||||
// password for rider api
|
||||
/**
|
||||
* @ORM\Column(type="string", length=64)
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->job_orders = new ArrayCollection();
|
||||
|
|
@ -99,6 +113,8 @@ class Rider
|
|||
$this->curr_rating = 0;
|
||||
$this->flag_available = true;
|
||||
$this->flag_active = true;
|
||||
$this->username = null;
|
||||
$this->password = '';
|
||||
}
|
||||
|
||||
public function getID()
|
||||
|
|
@ -253,4 +269,42 @@ class Rider
|
|||
{
|
||||
return $this->flag_active;
|
||||
}
|
||||
|
||||
public function setUsername($username)
|
||||
{
|
||||
$this->username = $username;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setPassword($pass)
|
||||
{
|
||||
// they have to pass the encoded password
|
||||
$this->password = $pass;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getActiveJobOrder()
|
||||
{
|
||||
$active_status = [
|
||||
JOStatus::ASSIGNED,
|
||||
JOStatus::IN_TRANSIT,
|
||||
JOStatus::IN_PROGRESS,
|
||||
];
|
||||
|
||||
$criteria = Criteria::create();
|
||||
$criteria->where(Criteria::expr()->in('status', $active_status))
|
||||
->getFirstResult(1);
|
||||
|
||||
return $this->job_orders->matching($criteria)[0];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,17 @@ class RiderRating
|
|||
*/
|
||||
protected $rating;
|
||||
|
||||
// customer's comment that goes along with the rating
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
protected $comment;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->date_create = new DateTime();
|
||||
$this->rating = 0;
|
||||
$this->comment = '';
|
||||
}
|
||||
|
||||
public function getID()
|
||||
|
|
@ -111,4 +118,15 @@ class RiderRating
|
|||
{
|
||||
return $this->rating;
|
||||
}
|
||||
|
||||
public function setComment($comment)
|
||||
{
|
||||
$this->comment = $comment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComment()
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
117
src/Entity/RiderSession.php
Normal file
117
src/Entity/RiderSession.php
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="rider_session")
|
||||
*/
|
||||
class RiderSession
|
||||
{
|
||||
// unique id
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="string", length=13)
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
// device id or push id used by device
|
||||
/**
|
||||
* @ORM\Column(type="string", length=50)
|
||||
*/
|
||||
protected $device_push_id;
|
||||
|
||||
// link to customer
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Rider", inversedBy="sessions")
|
||||
* @ORM\JoinColumn(name="rider_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
protected $rider;
|
||||
|
||||
// phone number
|
||||
/**
|
||||
* @ORM\Column(type="string", length=12, nullable=true)
|
||||
*/
|
||||
protected $phone_number;
|
||||
|
||||
// is this device active
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
protected $is_active;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// default date generated to now
|
||||
$this->id = $this->generateKeyID();
|
||||
$this->rider = null;
|
||||
$this->is_active = true;
|
||||
}
|
||||
|
||||
public function generateKeyID()
|
||||
{
|
||||
// use uniqid for now, since primary key dupes will trigger exceptions
|
||||
return uniqid();
|
||||
}
|
||||
|
||||
public function getID()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setDevicePushID($id)
|
||||
{
|
||||
$this->device_push_id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDevicePushID()
|
||||
{
|
||||
return $this->device_push_id;
|
||||
}
|
||||
|
||||
public function setRider(Rider $rider = null)
|
||||
{
|
||||
$this->rider = $rider;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRider()
|
||||
{
|
||||
return $this->rider;
|
||||
}
|
||||
|
||||
public function setPhoneNumber($num)
|
||||
{
|
||||
$this->phone_number = $num;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPhoneNumber()
|
||||
{
|
||||
return $this->phone_number;
|
||||
}
|
||||
|
||||
public function setActive($flag = true)
|
||||
{
|
||||
$this->is_active = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isActive()
|
||||
{
|
||||
return $this->is_active;
|
||||
}
|
||||
|
||||
public function hasRider()
|
||||
{
|
||||
if ($this->rider == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -114,12 +114,17 @@ class Vehicle
|
|||
return $this->model_year_to;
|
||||
}
|
||||
|
||||
public function getModelYearFormatted()
|
||||
public function getModelYearFormatted($has_dash = true)
|
||||
{
|
||||
if ($this->model_year_from == 0)
|
||||
{
|
||||
if ($this->model_year_to == 0)
|
||||
return '-';
|
||||
{
|
||||
if ($has_dash)
|
||||
return '-';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->model_year_to;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class VehicleManufacturer
|
|||
// vehicles
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Vehicle", mappedBy="manufacturer")
|
||||
* @ORM\OrderBy({"make" = "ASC"})
|
||||
*/
|
||||
protected $vehicles;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ namespace App\Ramcar;
|
|||
|
||||
class FuelType extends NameValue
|
||||
{
|
||||
const GAS = 'gas';
|
||||
const DIESEL = 'diesel';
|
||||
const GAS = 'gas';
|
||||
const DIESEL = 'diesel';
|
||||
const LPG = 'lpg';
|
||||
|
||||
const COLLECTION = [
|
||||
'gas' => 'Gas',
|
||||
'diesel' => 'Diesel',
|
||||
'lpg' => 'LPG',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,12 @@ class MapTools
|
|||
|
||||
|
||||
// query google maps api
|
||||
$res = $client->request('GET', $maps_url, ['query' => $gmaps_params]);
|
||||
$res = $client->request('GET', $maps_url, [
|
||||
'query' => $gmaps_params,
|
||||
'curl' => [
|
||||
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
|
||||
],
|
||||
]);
|
||||
|
||||
return $res->getBody();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,36 @@
|
|||
<form id="row-form" class="m-form m-form--fit m-form--label-align-right" method="post" action="{{ mode == 'update' ? url('rider_update_submit', {'id': obj.getId()}) : url('rider_create_submit') }}">
|
||||
<div class="m-portlet__body">
|
||||
<div class="m-form__section m-form__section--first">
|
||||
|
||||
<div class="m-form__heading">
|
||||
<h3 class="m-form__heading-title">
|
||||
Rider App User
|
||||
</h3>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-6">
|
||||
<label data-field="username">Username</label>
|
||||
<input type="text" name="username" class="form-control m-input" value="{{ obj.getUsername() }}">
|
||||
<div class="form-control-feedback hide" data-field="username"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-6">
|
||||
<label data-field="password">Password</label>
|
||||
<input type="password" name="password" class="form-control m-input">
|
||||
<div class="form-control-feedback hide" data-field="password"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-6">
|
||||
<label data-field="confirm_password">Confirm Password</label>
|
||||
<input type="password" name="confirm_password" class="form-control m-input">
|
||||
<div class="form-control-feedback hide" data-field="confirm_password"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-form__seperator m-form__seperator--dashed"></div>
|
||||
<div class="m-form__section m-form__section">
|
||||
<div class="m-form__heading">
|
||||
<h3 class="m-form__heading-title">
|
||||
Rider Details
|
||||
|
|
|
|||
Loading…
Reference in a new issue