Add route for job order creation using third party API. #686

This commit is contained in:
Korina Cordero 2022-06-20 06:50:06 +00:00
parent c8a8bc53af
commit 08050416bb
4 changed files with 269 additions and 151 deletions

6
config/routes/tapi.yaml Normal file
View file

@ -0,0 +1,6 @@
# third party api
tapi_jo_request:
path: /tapi/job_order
controller: App\Controller\TAPI\JobOrderController::requestJobOrder
methods: [POST]

View file

@ -160,7 +160,8 @@ class APIUserController extends Controller
$meta = ['rider_id' => $rider_id];
// set api user in rider
$rider->setAPIUser($obj);
if ($rider != null)
$rider->setAPIUser($obj);
// set and save values
$obj->setName($req->request->get('name'))

View file

@ -48,6 +48,7 @@ use App\Entity\JOEvent;
use App\Entity\Customer;
use App\Entity\Hub;
use App\Entity\Invoice;
use App\Entity\Vehicle;
use DateTime;
use DateInterval;
@ -70,6 +71,7 @@ class JobOrderController extends APIController
HubSelector $hub_select, HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger,
HubFilteringGeoChecker $hub_geofence, EntityManagerInterface $em)
{
// TODO: fix all the responses
$this->denyAccessUnlessGranted('tapi_jo.request', null, 'No access.');
// check required parameters and api key
@ -82,21 +84,19 @@ class JobOrderController extends APIController
'first_name',
'last_name',
'mobile_number',
'vehicle_manufacturer',
'vehicle_model',
'vehicle_manufacturer_id',
'vehicle_model_id',
'plate_number'
];
$res = $this->checkParamsAndKey($req, $em, $required_params);
if ($res->isError())
return $res->getReturnResponse();
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get data from request
$data = [];
$data = $this->getJobOrderRequestInfo($req, $data);
// process customer and vehicle information
$this->processCustomerAndVehicleInformation($data, $em);
$status = $this->getJobOrderRequestInfo($req, $data);
if ($status != null)
return new APIResponse(false, $status);
$is_covered = false;
// geofence
@ -105,72 +105,43 @@ class JobOrderController extends APIController
if (!$is_covered)
{
// TODO: put geofence error message in config file somewhere
$res->setError(true)
->setErrorMessage('Oops! Our service is limited to some areas in Metro Manila, Laguna, and Baguio only. We will update you as soon as we are able to cover your area');
return $res->getReturnResponse();
$msg = 'Oops! Our service is limited to some areas in Metro Manila, Laguna, and Baguio only. We will update you as soon as we are able to cover your area';
return new APIResponse(false, $msg);
}
$jo = new JobOrder();
$jo->setSource(TransactionOrigin::MOBILE_APP)
$jo->setSource($data['source'])
->setStatus(JOStatus::PENDING)
->setDeliveryInstructions('')
->setDeliveryInstructions($data['instructions'])
->setTier1Notes('')
->setTier2Notes('')
->setDeliveryAddress($address)
->setTradeInType($trade_in)
->setDeliveryInstructions($instructions)
// TODO: error check for valid mode of payment
->setDeliveryAddress($data['address'])
->setTradeInType($data['trade_in_type'])
->setDeliveryInstructions($data['instructions'])
->setModeOfPayment($data['payment_mode'])
->setAdvanceOrder($data['is_advance_order'])
->setStatusAutoAssign(AutoAssignStatus::NOT_ASSIGNED)
->setLandmark($landmark);
->setLandmark($data['landmark']);
$jo->setCustomer($cust);
$jo->setCustomer($data['customer']);
// set coordinates
$point = new Point($long, $lat);
$point = new Point($data['long'], $data['lat']);
$jo->setCoordinates($point);
// make invoice criteria
$icrit = new InvoiceCriteria();
$icrit->setServiceType($stype);
$icrit->setServiceType($data['service_type']);
// TODO add promo to criteria if any
// check promo
// put in criteria
$icrit->addPromo($promo);
$icrit->addPromo($data['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);
$icrit->setCustomerVehicle($data['customer_vehicle']);
$jo->setCustomerVehicle($data['customer_vehicle']);
// check if customer owns vehicle
if ($cust->getID() != $cv->getCustomer()->getID())
{
$res->setError(true)
->setErrorMessage('Customer does not own vehicle');
return $res->getReturnResponse();
}
switch ($trade_in)
{
case TradeInType::MOTOLITE:
case TradeInType::OTHER:
break;
default:
$trade_in = '';
break;
}
$icrit->addEntry($batt, $trade_in, 1);
$icrit->addEntry($data['batt'], $data['trade_in_type'], 1);
// send to invoice generator
$invoice = $ic->generateInvoice($icrit);
@ -200,7 +171,7 @@ class JobOrderController extends APIController
{
// error_log('hub filter is enabled');
// check if customer location is in hub filter area
if ($hub_geofence->isCovered($long, $lat))
if ($hub_geofence->isCovered($data['long'], $data['lat']))
{
// if true, set other values for HubCriteria
// TODO: set this properly, since the other flags
@ -213,6 +184,7 @@ class JobOrderController extends APIController
}
// check if batt is null
$batt = $data['batt'];
if ($batt != null)
{
// add battery to items
@ -222,6 +194,7 @@ class JobOrderController extends APIController
}
// get customer id. No JO id at this point
$cust = $data['customer'];
$customer_id = $cust->getID();
$hub_criteria->setCustomerId($customer_id);
@ -326,7 +299,7 @@ class JobOrderController extends APIController
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_ASSIGNED);
if ($date_schedule != null)
$jo->setDateSchedule($date_schedule);
$jo->setDateSchedule($data['date_schedule']);
// update redis hub_jo_count for hub
$hub_dist->incrementJoCountForHub($hub);
@ -414,41 +387,10 @@ class JobOrderController extends APIController
'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)
{
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);
$message = 'Job order created.';
return $res->getReturnResponse();
return new APIResponse(true, $message, $data);
}
public function getEstimate(Request $req, InvoiceGeneratorInterface $ic, EntityManagerInterface $em)
@ -1528,14 +1470,27 @@ class JobOrderController extends APIController
protected function getJobOrderRequestInfo(Request $req, EntityManagerInterface $em, &$data)
{
$error = $this->validateRequest($req);
if ($error != null)
{
// there is a validation error
return $error;
}
$r = $req->request;
// at this point, the request data has been validated
// trade-in type
$trade_in_type = $this->cleanText($r->get('trade_in_type'));
if (!TradeInType::validate($trade_in_type))
switch ($trade_in_type)
{
$message = 'Invalid trade in type';
return $message;
case TradeInType::MOTOLITE:
case TradeInType::OTHER:
break;
default:
$trade_in_type = '';
break;
}
// address
@ -1551,22 +1506,11 @@ class JobOrderController extends APIController
$long = $r->get('longitude');
$lat = $r->get('latitude');
// validate service type
// get service type
$stype = $this->cleanText($r->get('service_type'));
if (!ServiceType::validate($stype))
{
$message = 'Invalid service type';
return $message;
}
// get mode of payment
// TODO: do we need to validate this?
$payment_mode = $this->clean($r->get('mode_of_payment'));
if (!ModeOfPayment::validate($payment_mode))
{
$message = 'Invalid mode of payment';
return $message;
}
$advance_order = $r->get('flag_advance_order');
// check for 'false' text
@ -1596,6 +1540,97 @@ class JobOrderController extends APIController
}
}
// get promo
$promo_id = $r->get('promo_id');
$promo = $em->getRepository(Promo::class)->find($promo_id);
// check battery
$batt_id = $req->request->get('batt_id');
$batt = $em->getRepository(Battery::class)->find($batt_id);
// get customer and vehicle info
$fname = trim($r->get('first_name', ''));
$lname = trim($r->get('last_name', ''));
$mobile = $r->get('mobile_number', '');
// validate mobile number
$clean_mobile = $this->cleanPhoneNumber($mobile);
$vmanu_id = $r->get('vehicle_manufacturer');
// find vehicle manufacturer
$vmanu = $em->getRepository(VehicleManufacturer::class)->find($vmanu_id);
$vmodel_id = $r->get('vehicle_model');
// find vehicle
$vehicle = $em->getRepository(Vehicle::class)->find($vmodel_id);
$plate_number = $r->get('plate_number');
// clean plate number
$clean_plate = $this->cleanPlateNumber($plate_number);
$c_data = [
'first_name' => $fname,
'last_name' => $lname,
'mobile' => $clean_mobile,
'vmanu' => $vmanu,
'vehicle' => $vehicle,
'plate_number' => $clean_plate,
];
// process customer and vehicle information
$cust_data = $this->processCustomerAndVehicleInformation($c_data, $em);
$data = [
'trade_in_type' => $trade_in_type,
'service_type' => $stype,
'long' => $long,
'lat' => $lat,
'payment_mode' => $payment_mode,
'address' => $address,
'instructions' => $instructions,
'landmark' => $landmark,
'is_advance_order' => $flag_advance_order,
'hub' => $hub,
'date_schedule' => $date_schedule,
'promo' => $promo,
'batt' => $batt,
'customer' => $cust_data['customer'],
'customer_vehicle' => $cust_data['customer_vehicle'],
'source' => TransactionOrigin::THIRD_PARTY,
];
return null;
}
protected function validateRequest(Request $req, EntityManagerInterface $em)
{
$r = $req->request;
// validate trade-in type
$trade_in_type = $this->cleanText($r->get('trade_in_type'));
if (!TradeInType::validate($trade_in_type))
{
$message = 'Invalid trade in type';
return $message;
}
// validate service type
$stype = $this->cleanText($r->get('service_type'));
if (!ServiceType::validate($stype))
{
$message = 'Invalid service type';
return $message;
}
// validate mode of payment
$payment_mode = $this->clean($r->get('mode_of_payment'));
if (!ModeOfPayment::validate($payment_mode))
{
$message = 'Invalid mode of payment';
return $message;
}
// check promo
$promo = null;
$promo_id = $r->get('promo_id');
@ -1603,7 +1638,7 @@ class JobOrderController extends APIController
{
$promo = $em->getRepository(Promo::class)->find($promo_id);
if ($promo == null)
{
{
$message = 'Invalid promo id';
return $message;
}
@ -1612,7 +1647,7 @@ class JobOrderController extends APIController
// check battery
$batt = null;
$batt_id = $req->request->get('batt_id');
if ($batt_id != null)
if ($empty($batt_id))
{
$batt = $em->getRepository(Battery::class)->find($batt_id);
if ($batt == null)
@ -1622,12 +1657,8 @@ class JobOrderController extends APIController
}
}
// get customer and vehicle info
$fname = $r->get('first_name', '');
$lname = $r->get('last_name', '');
$mobile = $r->get('mobile_number', '');
// validate mobile number
$mobile = $r->get('mobile_number', '');
$clean_mobile = $this->cleanPhoneNumber($mobile);
if ($clean_mobile == false)
{
@ -1635,66 +1666,144 @@ class JobOrderController extends APIController
return $message;
}
$vmanu = $r->get('vehicle_manufacturer', '');
$vmodel = $r->get('vehicle_model', '');
$plate_number = $r->get('plate_number');
$vmanu = null;
$vmanu_id = $r->get('vehicle_manufacturer');
// validate the vehicle manufacturer id
// find vehicle manufacturer
$vmanu = $em->getRepository(VehicleManufacturer::class)->find($vmanu_id);
if ($vmanu == null)
{
$message = 'Invalid vehicle manufacturer id.';
return $message;
}
// clean plate number
$clean_plate = $this->cleanPlateNumber($plate_number);
$vmodel = null;
$vmodel_id = $r->get('vehicle_model');
// validate the vehicle model id
// find vehicle
$vmodel = $em->getRepository(Vehicle::class)->find($vmodel_id);
if ($vmodel = null)
{
$message = 'Invalid vehicle model id.';
return $message;
}
$data = [
'trade_in_type' => $trade_in_type,
'service_type' => $stype,
'long' => $long,
'lat' => $lat,
'payment_mode' => $payment_mode,
'first_name' => $fname,
'last_name' => $lname,
'mobile' => $clean_mobile,
'vmanu' => $vmanu,
'vmodel' => $model,
'plate_number' => $clean_plate,
'address' => $address,
'instructions' => $instructions,
'landmark' => $landmark,
'is_advance_order' => $flag_advance_order,
'hub' => $hub,
'date_schedule' => $date_schedule,
'promo' => $promo,
'batt' => $batt,
];
// confirm that vehicle model's manufacturer is the same as the one in vehicle
if ($vmodel->getManufacturer()->getID != $vmanu_id)
{
$message = 'Invalid vehicle manufacturer id for vehicle model.';
return $message;
}
return null;
}
protected function processCustomerAndVehicleInformation($data, EntityManagerInterface $em)
{
$c_data = [];
// retrieve customer info
$fname = $data['first_name'];
$lname = $data['last_name'];
$vmanu = $data['vmanu'];
$vmodel = $data['vmodel'];
$vehicle = $data['vehicle'];
$plate_number = $data['plate_number'];
$mobile = $data['mobile'];
// find customer given phone number
$cust = $em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $mobile]);
$cust = null;
$cust_vehicle = null;
if ($cust == null)
// find customer + customer vehicle combo
$cv = $this->findCustomerAndCustomerVehicle($data, $em);
if ($cv == null)
{
// create new customer and customer vehicle
}
else
{
// find customer vehicle using plate number
$cv = $em->getRepository(CustomerVehicle::class)->findOneBy(['plate_number' => $plate_number]);
if ($cv == null)
// find customer given phone number
$cust = $em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $mobile]);
if ($cust == null)
{
// get the api_user that made the call so that it gets added to the source
// source becomes TAPI_USER_<insert name of api user here>
$user_id = $_SERVER['HTTP_X_CATA_API_KEY'];
$source = 'TAPI_USER';
$username = '';
if (!empty($user_id))
{
$api_user = $this->getUser();
if ($api_user != null)
{
$username = $api_user->getName();
$source = $source . '_' . $username;
}
}
// create new customer and customer vehicle
$cust = new Customer();
$cust->setFirstName($fname)
->setLastName($lname)
->setPhoneMobile($mobile)
->setCreateSource($source);
$em->persist($cust);
// add customer vehicle
$cust_vehicle = $this->createCustomerVehicle($em, $cust, $vehicle);
}
else
{
// create customer vehicle
$cust_vehicle = $this->createCustomerVehicle($em, $cust, $vehicle);
}
$em->flush();
}
return $cust;
$c_data = [
'customer' => $cust,
'customer_vehicle' => $cust_vehicle,
];
return $c_data;
}
protected function createCustomerVehicle(EntityManagerInterface $em, Customer $cust, Vehicle $vehicle)
{
// add customer vehicle
$cust_vehicle = new CustomerVehicle();
$cust_vehicle->setCustomer($cust)
->setPlateNumber($plate_number)
->setVehicle($vehicle);
$em->persist($cust_vehicle);
return $cust_vehicle;
}
protected function findCustomerAndCustomerVehicle($data, EntityManagerInterface $em)
{
$plate_number = $data['plate_number'];
$mobile = $data['mobile'];
$query = $em->createQuery('SELECT cv, c FROM App\Entity\CustomerVehicle cv
JOIN cv.customer c
WHERE cv.plate_number = :plate_number
AND c.phone_mobile = :phone_mobile');
$query->setParameter('plate_number', $plate_number)
->setParameter('phone_mobile', $mobile);
$cust_results = $query->iterate();
$cust_vehicle = null;
foreach ($cust_results as $row)
{
$cust_vehicle = $row[0];
}
return $cust_vehicle;
}
protected function cleanPhoneNumber($mobile)

View file

@ -11,6 +11,7 @@ class TransactionOrigin extends NameValue
const MOBILE_APP = 'mobile_app';
const WALK_IN = 'walk_in';
const LAZADA = 'lazada';
const THIRD_PARTY = 'third_party';
// TODO: for now, resq also gets the walk-in option
const COLLECTION = [
@ -21,5 +22,6 @@ class TransactionOrigin extends NameValue
'mobile_app' => 'Mobile App',
'walk_in' => 'Walk-in',
'lazada' => 'Lazada',
'third_party' => 'Third Party',
];
}