Merge branch 'master' of gitlab.com:jankstudio/resq into 330-entity-logging-service-bundle

This commit is contained in:
Korina Cordero 2020-04-17 08:11:21 +00:00
commit afbd1221f3
63 changed files with 2966 additions and 137 deletions

View file

@ -63,3 +63,15 @@ COUNTRY_CODE=+insert_country_code_here
# dashboard
DASHBOARD_ENABLE=set_to_true_or_false
# auth token for Inventory API
INVENTORY_API_URL=insert_api_url_here
INVENTORY_API_OCP=insert_ocp_text_here
INVENTORY_API_AUTH_TOKEN_PREFIX=Bearer
INVENTORY_API_AUTH_TOKEN=insert_auth_token_here
# API logging
API_LOGGING=set_to_true_or_false
# customer distance limit in km
CUST_DISTANCE_LIMIT=set_to_number

View file

@ -64,7 +64,7 @@ class TestAPICommand extends Command
'start' => '1',
];
$api->get('/capi/warranties', $params);
//$api->get('/capi/warranties', $params);
// warranty find
@ -123,7 +123,7 @@ class TestAPICommand extends Command
// privacy policy
$privacy_policy_id = 2;
$api->get('/capi/privacy_policy/' . $privacy_policy_id );
//$api->get('/capi/privacy_policy/' . $privacy_policy_id );
// register new customer
$params = [
@ -137,6 +137,19 @@ class TestAPICommand extends Command
'v_condition' => 'new',
'v_fuel_type' => 'gas',
];
$api->post('/capi/quick_registration', $params);
//$api->post('/capi/quick_registration', $params);
// get warranties given list of serial numbers
$serial_list = [
'AJ34LJADR12134LKJM4',
'AJ34LJADR12134LKJL5',
'test',
];
$params = [
'serial_list' => $serial_list,
];
$api->post('/capi/warranties_list', $params);
}
}

View file

@ -268,6 +268,8 @@ access_keys:
label: Walk-in
- id: jo_walkin.edit
label: Walk-in Edit
- id: jo_autoassign.test
label: Autoassign Test
- id: support
label: Customer Support Access

View file

@ -20,6 +20,8 @@ access_keys:
label: Delete
- id: warranty.set.privacypolicy
label: Set Privacy Policy
- id: warranty.list.serial
label: List by Serial
- id: batterybrand
label: Battery Brand Access
acls:

View file

@ -65,6 +65,7 @@ services:
arguments:
$em: "@doctrine.orm.entity_manager"
$gmaps_api_key: "%env(GMAPS_API_KEY)%"
$cust_dist_limit: "%env(CUST_DISTANCE_LIMIT)%"
App\Service\RisingTideGateway:
arguments:
@ -257,3 +258,7 @@ services:
- name: 'doctrine.event_listener'
event: 'postPersist'
# API logging
App\EventSubscriber\LogSubscriber:
arguments:
$api_log_flag: "%env(API_LOGGING)%"

View file

@ -37,10 +37,6 @@ main_menu:
acl: rider.list
label: Riders
parent: logistics
- id: service_charge_list
acl: service_charge.list
label: Service Charges
parent: logistics
- id: battery
acl: battery.menu
@ -102,13 +98,21 @@ main_menu:
acl: joborder.menu
label: Job Order
icon: flaticon-calendar-3
- id: jo_onestep_form
acl: jo_onestep.form
label: One-step Process
- id: jo_in
acl: jo_in.list
label: Incoming
parent: joborder
- id: jo_walkin_form
acl: jo_walkin.form
label: Walk-in
- id: jo_proc
acl: jo_proc.list
label: Dispatch
parent: joborder
- id: jo_assign
acl: jo_assign.list
label: Rider Assignment
parent: joborder
- id: jo_fulfill
acl: jo_fulfill.list
label: Fulfillment
parent: joborder
- id: jo_open
acl: jo_open.list

View file

@ -65,6 +65,7 @@ services:
arguments:
$em: "@doctrine.orm.entity_manager"
$gmaps_api_key: "%env(GMAPS_API_KEY)%"
$cust_dist_limit: "%env(CUST_DISTANCE_LIMIT)%"
App\Service\RisingTideGateway:
arguments:
@ -256,3 +257,15 @@ services:
- name: 'doctrine.event_listener'
event: 'postPersist'
# inventory manager
App\Service\InventoryManager:
arguments:
$api_url: "%env(INVENTORY_API_URL)%"
$api_ocp_key: "%env(INVENTORY_API_OCP)%"
$api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%"
$api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%"
# API logging
App\EventSubscriber\LogSubscriber:
arguments:
$api_log_flag: "%env(API_LOGGING)%"

View file

@ -108,6 +108,12 @@ capi_warranty_privacy_policy:
controller: App\Controller\CAPI\WarrantyController::setPrivacyPolicy
methods: [POST]
# get list of warranties given list of serials
capi_warranty_get_warranties_from_serials:
path: /capi/warranties_list
controller: App\Controller\CAPI\WarrantyController::getWarrantiesBySerialList
methods: [POST]
# customer vehicle api
# find customer vehicle by id

View file

@ -226,3 +226,12 @@ jo_walkin_edit_submit:
controller: App\Controller\JobOrderController::walkInEditSubmit
methods: [POST]
jo_autoassign:
path: /job-order/autoassign
controller: App\Controller\JobOrderController::autoAssignForm
methods: [GET]
jo_autoassign_test_submit:
path: /job-order/autoassign
controller: App\Controller\JobOrderController::autoAssignSubmit
methods: [POST]

View file

@ -65,6 +65,7 @@ services:
arguments:
$em: "@doctrine.orm.entity_manager"
$gmaps_api_key: "%env(GMAPS_API_KEY)%"
$cust_dist_limit: "%env(CUST_DISTANCE_LIMIT)%"
App\Service\RisingTideGateway:
arguments:
@ -158,62 +159,41 @@ services:
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
# CMB invoice generator
App\Service\InvoiceGenerator\CMBInvoiceGenerator: ~
# Resq invoice generator
#App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~
# invoice generator
App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~
# invoice generator interface
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CMBInvoiceGenerator"
#App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator"
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator"
# Resq job order generator
#App\Service\JobOrderHandler\ResqJobOrderHandler:
# arguments:
# $country_code: "%env(COUNTRY_CODE)%"
# CMB job order generator
App\Service\JobOrderHandler\CMBJobOrderHandler:
# job order generator
App\Service\JobOrderHandler\ResqJobOrderHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
$country_code: "%env(COUNTRY_CODE)%"
#job order generator interface
App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\CMBJobOrderHandler"
#App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\ResqJobOrderHandler"
App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\ResqJobOrderHandler"
# CMB customer generator
App\Service\CustomerHandler\CMBCustomerHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
# Resq customer generator
#App\Service\CustomerHandler\ResqCustomerHandler:
# arguments:
# $country_code: "%env(COUNTRY_CODE)%"
# customer generator interface
App\Service\CustomerHandlerInterface: "@App\\Service\\CustomerHandler\\CMBCustomerHandler"
#App\Service\CustomerHandlerInterface: "@App\\Service\\CustomerHandler\\ResqCustomerHandler"
# rider assignment
#App\Service\RiderAssignmentHandler\CMBRiderAssignmentHandler: ~
# rider assignment interface
App\Service\RiderAssignmentHandlerInterface: "@App\\Service\\RiderAssignmentHandler\\CMBRiderAssignmentHandler"
# rider API service
App\Service\RiderAPIHandler\CMBRiderAPIHandler:
# customer generator
App\Service\CustomerHandler\ResqCustomerHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
#App\Service\RiderAPIHandler\ResqRiderAPIHandler:
# arguments:
# $country_code: "%env(COUNTRY_CODE)%"
# customer generator interface
App\Service\CustomerHandlerInterface: "@App\\Service\\CustomerHandler\\ResqCustomerHandler"
# rider API interface
App\Service\RiderAPIHandlerInterface: "@App\\Service\\RiderAPIHandler\\CMBRiderAPIHandler"
# rider assignment
App\Service\RiderAssignmentHandler\ResqRiderAssignmentHandler: ~
# rider assignment interface
App\Service\RiderAssignmentHandlerInterface: "@App\\Service\\RiderAssignmentHandler\\ResqRiderAssignmentHandler"
# rider API service
App\Service\RiderAPIHandler\ResqRiderAPIHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
App\Service\RiderAPIHandlerInterface: "@App\\Service\\RiderAPIHandler\\ResqRiderAPIHandler"
# map manager
#App\Service\GISManager\Bing: ~
App\Service\GISManager\OpenStreet: ~
@ -276,3 +256,16 @@ services:
event: 'onFlush'
- name: 'doctrine.event_listener'
event: 'postPersist'
# inventory manager
App\Service\InventoryManager:
arguments:
$api_url: "%env(INVENTORY_API_URL)%"
$api_ocp_key: "%env(INVENTORY_API_OCP)%"
$api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%"
$api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%"
# API logging
App\EventSubscriber\LogSubscriber:
arguments:
$api_log_flag: "%env(API_LOGGING)%"

View file

@ -46,5 +46,7 @@ class AdjustLongLatCommand extends Command
}
$em->flush();
return 0;
}
}

View file

@ -71,5 +71,7 @@ class ComputeWarrantyExpiryDateCommand extends Command
$this->em->clear();
}
return 0;
}
}

View file

@ -290,6 +290,8 @@ class CreateCustomerFromWarrantyCommand extends Command
//$output->writeln('Total warranties with no mobile number: ' . $total_inv_warr);
$output->writeln('Total customers added: ' . $total_cust_added);
$output->writeln('Total customer vehicles added: ' . $total_cv_added);
return 0;
}
protected function getDefaultVehicle()

View file

@ -22,9 +22,9 @@ class FulfillOldJobOrderCommand extends Command
{
protected $em;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
parent::__construct();
}
@ -76,5 +76,7 @@ class FulfillOldJobOrderCommand extends Command
}
$em->flush();
return 0;
}
}

View file

@ -22,9 +22,9 @@ class FulfillPendingJobOrderCommand extends Command
{
protected $em;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
parent::__construct();
}
@ -79,5 +79,7 @@ class FulfillPendingJobOrderCommand extends Command
}
$em->flush();
return 0;
}
}

View file

@ -21,9 +21,9 @@ class GenerateBatteryCompatibilityCommand extends Command
protected $em;
protected $vmfg_index;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
parent::__construct();
}
@ -100,5 +100,7 @@ class GenerateBatteryCompatibilityCommand extends Command
fwrite($json_file, json_encode($this->vmfg_index, JSON_PRETTY_PRINT));
fclose($json_file);
return 0;
}
}

View file

@ -211,5 +211,7 @@ class GenerateWarrantyFromJobOrderCommand extends Command
$em->detach($row[0]);
$em->clear();
}
return 0;
}
}

View file

@ -30,9 +30,9 @@ class ImportBatteryPriceCommand extends Command
protected $em;
protected $size_index;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
$this->size_index = [];
parent::__construct();
@ -174,5 +174,7 @@ class ImportBatteryPriceCommand extends Command
}
$em->flush();
return 0;
}
}

View file

@ -170,6 +170,8 @@ class ImportCMBBatteryDataCommand extends Command
}
}
return 0;
}
protected function addBatteryManufacturer($name)

View file

@ -92,9 +92,9 @@ class ImportCMBBatteryTradeInPriceCommand extends Command
{
error_log('Cannot find battery size ' . $size);
}
}
return 0;
}
protected function loadBatterySizes()

View file

@ -289,6 +289,8 @@ class ImportCMBVehicleCompatibilityCommand extends Command
$row_num++;
}
return 0;
}
protected function addVehicleManufacturer($name)

View file

@ -479,5 +479,7 @@ class ImportCustomerCommand extends Command
}
fclose($cust_file);
fclose($cv_file);
return 0;
}
}

View file

@ -35,5 +35,7 @@ class ImportKMLFileCommand extends Command
$kml_file = $input->getArgument('file');
$this->importer->getMapData($kml_file);
return 0;
}
}

View file

@ -44,9 +44,9 @@ class ImportLegacyJobOrderCommand extends Command
protected $row_max_field_size;
protected $data_max_field_size;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
$this->loadBatteryModels();
$this->loadBatterySizes();
@ -544,6 +544,8 @@ class ImportLegacyJobOrderCommand extends Command
fclose($warr_outfile);
fclose($jo_outfile);
fclose($jorow_outfile);
return 0;
}
protected function initializeMaxFieldCounters()

View file

@ -7,6 +7,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Outlet;
@ -17,11 +18,11 @@ use DateTime;
class ImportOutletsCommand extends Command
{
private $object_manager;
private $em;
public function __construct(EntityManagerInterface $om, ValidatorInterface $validator)
public function __construct(EntityManagerInterface $em, ValidatorInterface $validator)
{
$this->object_manager = $om;
$this->em = $em;
$this->validator = $validator;
parent::__construct();
@ -60,7 +61,7 @@ class ImportOutletsCommand extends Command
}
// get entity manager
$em = $this->object_manager;
$em = $this->em;
// row counter
$row = 1;
@ -167,7 +168,8 @@ class ImportOutletsCommand extends Command
{
$output->writeln("Errors occurred! Please check the CSV file is in the proper format.");
}
return 0;
}
protected function setObject($obj, $fields)

View file

@ -34,9 +34,9 @@ class ImportPartnersCommand extends Command
protected $em;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
parent::__construct();
}
@ -163,6 +163,7 @@ class ImportPartnersCommand extends Command
$row_num++;
}
return 0;
}
}

View file

@ -7,6 +7,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\SAPBattery;
@ -37,12 +38,14 @@ class ImportSAPBatteryCommand extends Command
$this->setName('sap_battery:import')
->setDescription('Import a CSV file with SAP battery data.')
->setHelp('Creates SAP battery data entries off imported CSV.')
->addArgument('file', InputArgument::REQUIRED, 'Path to the CSV file.');
->addArgument('file', InputArgument::REQUIRED, 'Path to the CSV file.')
->addArgument('output_file', InputArgument::REQUIRED, 'Path to the output CSV file.');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$csv_file = $input->getArgument('file');
$report_file = $input->getArgument('output_file');
// CSV column order:
// 0 - brand
@ -68,6 +71,9 @@ class ImportSAPBatteryCommand extends Command
// has error?
$has_error = false;
$dupe_brands = [];
$dupe_sizes = [];
$dupe_batteries = [];
// loop through rows and build hashes
while (($fields = fgetcsv($handle)) !== false)
{
@ -77,7 +83,7 @@ class ImportSAPBatteryCommand extends Command
// clean up fields
$clean_brand = trim($fields[0]);
$clean_sku = trim($fields[1]);
$clean_sku = strtoupper(trim($fields[1]));
$clean_size = trim($fields[2]);
$output->writeln("Parsing $clean_sku...");
@ -92,6 +98,11 @@ class ImportSAPBatteryCommand extends Command
$this->batt_brand_hash[$clean_brand] = $brand;
}
else
{
// add to duplicate list
$dupe_brands[] = $clean_brand;
}
// size hash
if (!isset($this->batt_size_hash[$clean_size]))
@ -103,6 +114,10 @@ class ImportSAPBatteryCommand extends Command
$this->batt_size_hash[$clean_size] = $size;
}
else
{
$dupe_sizes[] = $clean_size;
}
// battery hash
if (!isset($this->battery_hash[$clean_sku]))
@ -110,14 +125,28 @@ class ImportSAPBatteryCommand extends Command
// create battery entry
$battery = new SAPBattery();
$battery->setID($clean_sku)
->setSize($size_hash[$clean_size])
->setBrand($brand_hash[$clean_brand]);
->setSize($this->batt_size_hash[$clean_size])
->setBrand($this->batt_brand_hash[$clean_brand]);
$em->persist($battery);
}
else
{
$dupe_batteries[] = $clean_sku;
}
}
$em->flush();
// write dupes report
if ((count($dupe_brands) > 0) ||
(count($dupe_sizes) > 0) ||
(count($dupe_batteries) > 0))
{
$this->writeDupeReport($report_file, $dupe_brands, $dupe_sizes, $dupe_batteries);
}
return 0;
}
protected function initBatteryHash()
@ -146,4 +175,40 @@ class ImportSAPBatteryCommand extends Command
foreach ($brands as $brand)
$this->batt_brand_hash[$brand->getName()] = $brand;
}
protected function writeDupeReport($report_file, $brands, $sizes, $batts)
{
try
{
$fh = fopen($report_file, "w");
}
catch (Exception $e)
{
throw new Exception('The file "' . $report_file . '" could be opened.');
}
fputs($fh, 'Brands not added: ' . "\n");
foreach ($brands as $brand)
{
fputs($fh, $brand, strlen($brand));
fputs($fh, "\n");
}
fputs($fh, 'Sizes not added: ' . "\n");
foreach ($sizes as $size)
{
fputs($fh, $size, strlen($size));
fputs($fh, "\n");
}
fputs($fh, 'SKUs not added: ' . "\n");
foreach ($batts as $batt)
{
fputs($fh, $batt, strlen($batt));
fputs($fh, "\n");
}
fclose($fh);
}
}

View file

@ -35,9 +35,9 @@ class ImportVehicleBatteryCommand extends Command
protected $batt_index;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
$this->vmfg_index = [];
$this->v_index = [];
$this->batt_index = [];
@ -221,6 +221,6 @@ class ImportVehicleBatteryCommand extends Command
$em->flush();
// print_r($batteries);
return 0;
}
}

View file

@ -28,9 +28,9 @@ class ImportVehicleCompatibilityCommand extends Command
protected $bsize_index;
protected $b_index;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
$this->vmfg_index = [];
$this->v_index = [];
$this->b_index = [];
@ -317,6 +317,6 @@ class ImportVehicleCompatibilityCommand extends Command
$em->flush();
// print_r($batteries);
return 0;
}
}

View file

@ -15,9 +15,9 @@ class MergeDuplicateVehiclesCommand extends Command
{
protected $em;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
parent::__construct();
}
@ -161,8 +161,7 @@ class MergeDuplicateVehiclesCommand extends Command
$em->flush();
}
}
// print_r($dupes);
return 0;
}
}

View file

@ -64,5 +64,7 @@ class RefreshJobOrderCacheCommand extends Command
{
$this->jo_cache->addActiveJobOrder($jo);
}
return 0;
}
}

View file

@ -142,5 +142,7 @@ class ReportRiderTime extends Command
}
fclose($fh);
return 0;
}
}

View file

@ -55,5 +55,7 @@ class SeedRiderSessionsCommand extends Command
$this->redis->set($redis_key, $rider_id);
}
}
return 0;
}
}

View file

@ -22,10 +22,10 @@ class SetCustomerPrivacyPolicyCommand extends Command
private $policy_third_party_id;
private $policy_mobile_id;
public function __construct(EntityManagerInterface $om, $policy_promo,
public function __construct(EntityManagerInterface $em, $policy_promo,
$policy_third_party, $policy_mobile)
{
$this->em = $om;
$this->em = $em;
$this->policy_promo_id = $policy_promo;
$this->policy_third_party_id = $policy_third_party;
@ -80,5 +80,7 @@ class SetCustomerPrivacyPolicyCommand extends Command
}
$this->em->flush();
return 0;
}
}

View file

@ -66,5 +66,7 @@ class TestGeneralSearchCommand extends Command
echo "Last Name: " . $warranty->getLastName() . "\n";
echo "First Name: " . $warranty->getFirstName() . "\n";
}
return 0;
}
}

View file

@ -40,5 +40,7 @@ class TestGeofenceCommand extends Command
echo "In geofence\n";
else
echo "NOT in geofence\n";
return 0;
}
}

View file

@ -35,5 +35,7 @@ class TestHubCounterCommand extends Command
$available_rc = $this->hc->getAvailableRiderCount($hub_id);
echo "Available Riders in Hub: " . $available_rc . "\n";
return 0;
}
}

View file

@ -36,5 +36,7 @@ class TestJobOrderManagerCommand extends Command
echo "Job Order successfully updated" . "\n";
else
echo "Job Order not updated" . "\n";
return 0;
}
}

View file

@ -34,5 +34,7 @@ class TestRegAPNSCommand extends Command
{
$push_id = $input->getArgument('push_id');
$this->apns->sendReg($push_id, 'Test Delay', 'Body');
return 0;
}
}

View file

@ -42,5 +42,7 @@ class TestRiderTrackerCommand extends Command
{
echo "Invalid rider id." . "\n";
}
return 0;
}
}

View file

@ -18,9 +18,9 @@ class UpdateCustomerVehicleBatteryCommand extends Command
protected $em;
protected $custvehicle_hash;
public function __construct(EntityManagerInterface $om)
public function __construct(EntityManagerInterface $em)
{
$this->em = $om;
$this->em = $em;
$this->custvehicle_hash = [];
parent::__construct();
@ -63,5 +63,7 @@ class UpdateCustomerVehicleBatteryCommand extends Command
}
}
}
return 0;
}
}

View file

@ -94,5 +94,7 @@ class UpdateCustomerVehicleWarrantyCommand extends Command
$this->em->detach($row[0]);
}
return 0;
}
}

View file

@ -7,6 +7,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Rider;
@ -18,11 +19,11 @@ use DirectoryIterator;
class UploadCleanupCommand extends Command
{
private $encoder_factory;
private $object_manager;
private $em;
public function __construct(EntityManagerInterface $om, Filesystem $fs, FileUploader $uploader)
public function __construct(EntityManagerInterface $em, Filesystem $fs, FileUploader $uploader)
{
$this->object_manager = $om;
$this->em = $em;
$this->filesystem = $fs;
$this->uploader = $uploader;
@ -41,7 +42,7 @@ class UploadCleanupCommand extends Command
$output->writeln('Retrieving file whitelist...');
// get all image filenames
$em = $this->object_manager;
$em = $this->em;
$riders = $em->getRepository(Rider::class)->findAll();
$whitelist = ['.gitkeep'];
@ -95,5 +96,7 @@ class UploadCleanupCommand extends Command
$output->writeln('Deleted ' . $i . ' orphaned file(s). Done!');
else
$output->writeln('No files found. Done!');
return 0;
}
}

View file

@ -8,6 +8,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;
@ -16,12 +17,12 @@ use App\Entity\Role;
class UserCreateCommand extends Command
{
private $encoder_factory;
private $object_manager;
private $em;
public function __construct(EncoderFactoryInterface $ef, EntityManagerInterface $om)
public function __construct(EncoderFactoryInterface $ef, EntityManagerInterface $em)
{
$this->encoder_factory = $ef;
$this->object_manager = $om;
$this->em = $em;
parent::__construct();
}
@ -49,7 +50,7 @@ class UserCreateCommand extends Command
// get entity manager
// $em = $this->getContainer()->get('doctrine')->getEntityManager();
$em = $this->object_manager;
$em = $this->em;
// build user
$user->setUsername($username)
@ -66,5 +67,7 @@ class UserCreateCommand extends Command
$em->persist($user);
$em->flush();
return 0;
}
}

View file

@ -29,6 +29,9 @@ 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\Entity\MobileSession;
use App\Entity\Customer;
@ -45,12 +48,14 @@ use App\Entity\Service;
use App\Entity\Partner;
use App\Entity\Review;
use App\Entity\PrivacyPolicy;
use App\Entity\Hub;
use DateTime;
use DateInterval;
use Exception;
// mobile API
class APIController extends Controller
class APIController extends Controller implements LoggedController
{
protected $session;
@ -817,7 +822,9 @@ class APIController extends Controller
return $res->getReturnResponse();
}
public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo)
public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo,
MapTools $map_tools, InventoryManager $im, MQTTClient $mclient,
RiderAssignmentHandlerInterface $rah)
{
// check required parameters and api key
$required_params = [
@ -982,16 +989,87 @@ class APIController extends Controller
$invoice = $ic->generateInvoice($icrit);
$jo->setInvoice($invoice);
// assign hub and rider
if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) ||
($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY))
{
// get nearest hub
// $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im);
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
}
else
{
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
}
if (!empty($nearest_hub))
{
// assign rider
$available_riders = $nearest_hub->getAvailableRiders();
if (count($available_riders) > 0)
{
$assigned_rider = null;
if (count($available_riders) > 1)
{
// 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);
}
else
$assigned_rider = $available_riders[0];
$jo->setHub($nearest_hub);
$jo->setRider($assigned_rider);
$jo->setStatus(JOStatus::ASSIGNED);
$assigned_rider->setAvailable(false);
}
}
$em->persist($jo);
$em->persist($invoice);
// add event log
// 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
@ -2213,4 +2291,177 @@ class APIController extends Controller
return $cust;
}
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;
}
}

View file

@ -502,6 +502,48 @@ class WarrantyController extends APIController
}
public function getWarrantiesBySerialList(Request $req, EntityManagerInterface $em)
{
$this->denyAccessUnlessGranted('warranty.list.serial', null, 'No access.');
error_log('getWarrantiesBySerialList');
// required parameters
$params = [
'serial_list',
];
$msg = $this->checkRequiredParameters($req, $params);
error_log('msg - ' . $msg);
if ($msg)
return new APIResponse(false, $msg);
$serial_list = $req->request->get('serial_list');
if (empty($serial_list))
return new APIResponse(false, 'Empty serial numbers list.');
$warranty_list = [];
$warr_not_found_list = [];
foreach ($serial_list as $serial)
{
$clean_serial = $this->cleanSerial($serial);
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $clean_serial]);
if ($warr == null)
$warr_not_found_list[] = $clean_serial;
else
$warranty_list[] = $this->generateWarrantyData($warr);
}
$data = [
'warranties_found' => $warranty_list,
'warranties_not_found' => $warr_not_found_list,
];
return new APIResponse(true, 'Warranties found.', $data);
}
protected function getCustomerFromMobile($em, $warranty)
{
$w_mobile = $warranty->getMobileNumber();

View file

@ -181,7 +181,10 @@ class CustomerController extends Controller
public function getCustomerVehicles(Request $req, CustomerHandlerInterface $cust_handler)
{
if (!$this->isGranted('jo_in.list')) {
if (!(($this->isGranted('jo_onestep.form')) ||
($this->isGranted('jo_walkin.form')) ||
($this->isGranted('jo_in.list'))))
{
$exception = $this->createAccessDeniedException('No access.');
throw $exception;
}

View file

@ -150,7 +150,9 @@ class HubController extends Controller
->setContactNumbers($req->request->get('contact_nums'))
->setTimeOpen($time_open)
->setTimeClose($time_close)
->setCoordinates($point);
->setCoordinates($point)
->setBranchCode($req->request->get('branch_code', ''))
->setStatusOpen($req->request->get('status_open') ?? false);
}
protected function setQueryFilters($datatable, QueryBuilder $query)

View file

@ -5,6 +5,7 @@ namespace App\Controller;
use App\Ramcar\JOStatus;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\CMBServiceType;
use App\Ramcar\ServiceType;
use App\Entity\CustomerVehicle;
use App\Entity\Promo;
@ -20,6 +21,7 @@ use App\Service\GISManagerInterface;
use App\Service\MapTools;
use App\Service\MQTTClient;
use App\Service\APNSClient;
use App\Service\InventoryManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -96,7 +98,9 @@ class JobOrderController extends Controller
$this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.');
$error_array = [];
$error_array = $jo_handler->generateJobOrder($req, $id);
$result = $jo_handler->openEditJobOrder($req, $id);
$error_array = $result['error_array'];
// check if any errors were found
if (!empty($error_array)) {
@ -145,7 +149,9 @@ class JobOrderController extends Controller
// initialize error list
$error_array = [];
$id = -1;
$error_array = $jo_handler->generateJobOrder($req, $id);
$result = $jo_handler->generateJobOrder($req, $id);
$error_array = $result['error_array'];
// check if any errors were found
if (!empty($error_array)) {
@ -933,12 +939,18 @@ class JobOrderController extends Controller
/**
* @ParamConverter("jo", class="App\Entity\JobOrder")
*/
public function popupInfo(JobOrder $jo)
public function popupInfo(JobOrder $jo, JobOrderHandlerInterface $jo_handler)
{
if ($jo == null)
return new Response('No job order data');
return $this->render('job-order/popup.html.twig', [ 'jo' => $jo ]);
// get the right template
$template = $jo_handler->getTwigTemplate('jo_popup');
$params['jo'] = $jo;
// response
return $this->render($template, $params);
}
/**
@ -1053,5 +1065,177 @@ class JobOrderController extends Controller
]);
}
/**
* @Menu(selected="jo_autoassign")
*/
public function autoAssignForm(GISManagerInterface $gis, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.');
$params = $jo_handler->initializeIncomingForm();
$params['submit_url'] = $this->generateUrl('jo_autoassign_test_submit');
$params['return_url'] = $this->generateUrl('jo_autoassign');
$params['map_js_file'] = $gis->getJSJOFile();
$template = 'job-order/autoassign.form.html.twig';
// response
return $this->render($template, $params);
}
public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler,
EntityManagerInterface $em, MapTools $map_tools,
InventoryManager $im)
{
$this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.');
// initialize error list
$error_array = [];
$id = -1;
$result = $jo_handler->generateJobOrder($req, $id);
$error_array = $result['error_array'];
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// get job order
$jo = $result['job_order'];
if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) ||
($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY))
$this->autoAssignHubAndRider($jo, $em, $map_tools, $im);
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
protected function autoAssignHubAndRider($jo, EntityManagerInterface $em,
MapTools $map_tools, InventoryManager $im)
{
// get the nearest 10 hubs
// TODO: move this snippet to a function
$hubs = $map_tools->getClosestHubs($jo->getCoordinates(), 10, date("H:i:s"));
$nearest_hubs = [];
$nearest_hubs_with_distance = [];
foreach ($hubs as $hub)
{
$nearest_hubs_with_distance[] = $hub;
// TODO: uncomment this when we have branch codes in data
// and when they have real codes and not test ones
//$nearest_branch_codes[] = $hub['hub']->getBranchCode();
$nearest_branch_codes = ['WestAve','jay_franchise'];
}
// get battery sku
$invoice = $jo->getInvoice();
if ($invoice != null)
{
$items = $invoice->getItems();
$skus = [];
foreach ($items as $item)
{
// TODO: uncomment this when they have real codes and not test ones
//$skus[] = $item->getBattery()->getSAPCode();
$skus[] = 'WMGD31EL-CPNM0-L';
}
// api call to check inventory
// pass the list of branch codes of nearest hubs and the skus
// go through returned list of branch codes
$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;
}
}
}
}
}
}
}
if ($flag_hub_found)
{
$jo->setHub($nearest['hub']);
$hub_riders = $nearest['hub']->getAvailableRiders();
$rider = null;
if (count($hub_riders) > 1)
{
// TODO: this will no longer be necessary when the contents
// of randomizeRider changes
$available_riders = [];
foreach ($hub_riders as $rider)
{
$available_riders[] = $rider;
}
$rider = $this->randomizeRider($available_riders);
}
else
$rider = $hub_riders[0];
$jo->setRider($rider);
$jo->setStatus(JOStatus::ASSIGNED);
$em->persist($jo);
$em->flush();
}
}
}
}
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;
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace App\Controller;
interface LoggedController
{
}

View file

@ -44,12 +44,25 @@ class Hub
*/
protected $outlets;
// branch code
/**
* @ORM\Column(type="string", length=80)
*/
protected $branch_code;
// is hub open
/**
* @ORM\Column(type="boolean")
*/
protected $status_open;
public function __construct()
{
$this->time_open = new DateTime();
$this->time_close = new DateTime();
$this->riders = new ArrayCollection();
$this->outlets = new ArrayCollection();
$this->status_open = true;
}
public function getRiders()
@ -114,4 +127,27 @@ class Hub
{
return $this->outlets;
}
public function setBranchCode($branch_code)
{
$this->branch_code = $branch_code;
return $this;
}
public function getBranchCode()
{
return $this->branch_code;
}
public function setStatusOpen($status = true)
{
$this->status_open = $status;
return $this;
}
public function isStatusOpen()
{
return $this->status_open;
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace App\EventSubscriber;
use App\Controller\LoggedController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
class LogSubscriber implements EventSubscriberInterface
{
protected $allow;
protected $api_log_flag;
public function __construct($api_log_flag)
{
$this->api_log_flag = $api_log_flag;
}
public function onKernelController(ControllerEvent $event)
{
if ($this->api_log_flag == 'false')
return;
$controller = $event->getController();
$this->allow = false;
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
if (is_array($controller))
$controller = $controller[0];
if (!($controller instanceof LoggedController))
return;
$this->allow = true;
$req = $event->getRequest();
$reqdata = [
$req->getPathInfo(),
$req->getMethod(),
$req->query->all(),
$req->request->all(),
];
error_log(print_r($reqdata, true));
}
public function onKernelResponse(ResponseEvent $event)
{
if ($this->api_log_flag == 'false')
return;
if (!$this->allow)
return;
$resp = $event->getResponse();
$content = $resp->getContent();
error_log(print_r($content, true));
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse',
];
}
}

View file

@ -0,0 +1,80 @@
<?php
namespace App\Service;
class InventoryManager
{
protected $api_url;
protected $api_ocp_key;
protected $api_auth_prefix;
protected $api_auth_token;
public function __construct($api_url, $api_ocp_key, $api_auth_prefix, $api_auth_token)
{
$this->api_url = $api_url;
$this->api_ocp_key = $api_ocp_key;
$this->api_auth_prefix = $api_auth_prefix;
$this->api_auth_token = $api_auth_token;
}
public function getBranchesInventory($nearest_branch_codes, $skus)
{
// api call to check inventory
// pass the list of branch codes and the skus
$data = [
"BranchCodes" => $nearest_branch_codes,
"Skus" => $skus,
];
$json_data = json_encode($data);
error_log('JSON ' . $json_data);
// initializes a new cURL session
$curl = curl_init($this->api_url);
// Set the CURLOPT_RETURNTRANSFER option to true
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// Set the CURLOPT_POST option to true for POST request
curl_setopt($curl, CURLOPT_POST, true);
// Set the request data as JSON using json_encode function
curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data);
// set timeout
curl_setopt($curl, CURLOPT_TIMEOUT, 300);
$authorization = $this->api_auth_prefix . ' ' . $this->api_auth_token;
$ocp = $this->api_ocp_key;
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Authorization: ' . $authorization,
'Content-Type: application/json',
'Ocp-Apim-Subscription-Key: ' . $ocp,
]);
$response = curl_exec($curl);
// close cURL session
curl_close($curl);
// response is array of these
// {
// "Id": 37,
// "BranchCode": "WestAve",
// "BranchName": "West ave. Branch",
// "BranchRole": 0,
// "Name": "3SMF / GOLD ",
// "SapCode": "WMGD31EL-CPNM0-L",
// "Quantity": 38
// }
// check if the response is empty
$results = [];
if (!empty($response))
$results = json_decode($response, true);
return $results;
}
}

View file

@ -2838,6 +2838,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
$this->template_hash['jo_onestep_edit_form'] = 'job-order/cmb.form.onestep.html.twig';
$this->template_hash['jo_walkin_form'] = 'job-order/cmb.form.walkin.html.twig';
$this->template_hash['jo_walkin_edit_form'] = 'job-order/cmb.form.walkin.html.twig';
$this->template_hash['jo_popup'] = 'job-order/cmb.popup.html.twig';
}
protected function checkTier($tier)

View file

@ -262,7 +262,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
return $params;
}
// creates/updates job order
// creates job order
public function generateJobOrder(Request $req, $id)
{
// initialize error list
@ -401,7 +401,113 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
}
}
return $error_array;
$data['error_array'] = $error_array;
if ($jo != null)
{
$data['job_order'] = $jo;
}
return $data;
}
// updates job order
public function openEditJobOrder(Request $req, $id)
{
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
// initialize error list
$error_array = [];
// make sure this object exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
}
if (empty($error_array))
{
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
$stype = $req->request->get('service_type');
// set and save values
$obj->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'));
// did they change invoice?
$invoice_items = $req->request->get('invoice_items', []);
$promo_id = $req->request->get('invoice_promo');
$invoice_change = $req->request->get('invoice_change', 0);
if ($invoice_change)
{
$this->ic->generateInvoiceCriteria($obj, $promo_id, $invoice_items, $error_array);
}
// validate
$errors = $this->validator->validate($obj);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::OPEN_EDIT)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
// validated! save the entity
$em->flush();
}
$data['error_array'] = $error_array;
if ($obj != null)
{
$data['job_order'] = $obj;
}
return $data;
}
// dispatch job order
@ -2394,8 +2500,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$this->template_hash['jo_list_fulfillment'] = 'job-order/list.fulfillment.html.twig';
$this->template_hash['jo_list_open'] = 'job-order/list.open.html.twig';
$this->template_hash['jo_list_all'] = 'job-order/list.all.html.twig';
$this->template_hash['jo_onestep'] = 'job-order/form.onestep.html.twig';
$this->template_hash['jo_onestep_edit_form'] = 'job-order/form.onestep.html.twig';
$this->template_hash['jo_popup'] = 'job-order/popup.html.twig';
}
protected function checkTier($tier)

View file

@ -17,10 +17,15 @@ class MapTools
// google maps api key
protected $gmaps_api_key;
public function __construct(EntityManagerInterface $em, $gmaps_api_key)
// customer distance limit
protected $cust_dist_limit;
public function __construct(EntityManagerInterface $em, $gmaps_api_key,
$cust_dist_limit)
{
$this->em = $em;
$this->gmaps_api_key = $gmaps_api_key;
$this->cust_dist_limit = $cust_dist_limit;
}
protected function mapGetDistances(Point $point, $hubs)
@ -148,6 +153,57 @@ class MapTools
return $final_data;
*/
}
// NOTE: only the API calls this
public function getClosestOpenHubs(Point $point, $limit, $time = false)
{
// get closest hubs based on st_distance function from db
$query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE h.status_open = true AND :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist')
->setParameter('lat', $point->getLatitude())
->setParameter('lng', $point->getLongitude());
if ($time) {
$query->setParameter('time', $time);
}
$query->setMaxResults($limit);
// error_log($query->getSql());
$result = $query->getResult();
$hubs = [];
$final_data = [];
foreach ($result as $row)
{
//error_log($row[0]->getName() . ' - ' . $row['dist']);
$hubs[] = $row[0];
// get coordinates of hub
$hub_coordinates = $row[0]->getCoordinates();
$cust_lat = $point->getLatitude();
$cust_lng = $point->getLongitude();
$hub_lat = $hub_coordinates->getLatitude();
$hub_lng = $hub_coordinates->getLongitude();
// get distance in kilometers from customer point to hub point
$dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng);
if ($dist < $this->cust_dist_limit)
{
$final_data[] = [
'hub' => $row[0],
'db_distance' => $row['dist'],
'distance' => $dist,
'duration' => 0,
];
}
}
error_log('nearest open hubs count: ' . count($final_data));
return $final_data;
}
protected function distance($lat1, $lon1, $lat2, $lon2)
{

View file

@ -479,7 +479,9 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface
return $data;
}
// TODO: tag rider as available
// tag rider as available
$rider = $this->session->getRider();
$rider->setAvailable(true);
$this->em->flush();
@ -511,7 +513,8 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface
->setRider($rider);
$this->em->persist($event);
// TODO: tag rider as unavailable
// tag rider as unavailable
$rider->setAvailable(false);
// save to customer vehicle battery record
$this->jo_handler->updateVehicleBattery($jo);

View file

@ -5,7 +5,7 @@
{% endblock %}
{% block body %}
<div id="dashboard_map" style="height:100%;"></div>
<div id="dashboard_map" style="height:100%;z-index:2"></div>
<!-- BEGIN: Subheader -->
<!-- END: Subheader -->
{% endblock %}

View file

@ -82,6 +82,24 @@
<div class="form-control-feedback hide" data-field="contact_nums"></div>
</div>
</div>
<div class="form-group m-form__group row no-border">
<div class="col-lg-6">
<label for="branch_code" data-field="branch_code">
Branch Code
</label>
<input type="text" name="branch_code" class="form-control m-input" value="{{ obj.getBranchCode() }}">
<div class="form-control-feedback hide" data-field="branch_code"></div>
</div>
<div class="col-lg-6">
<span class="m-switch m-switch--icon block-switch">
<label>
<input type="checkbox" name="status_open" id="status-open" value="1"{{ obj.isStatusOpen ? ' checked' }}>
<label class="switch-label">Open</label>
<span></span>
</label>
</span>
</div>
</div>
<div class="form-group m-form__group row no-border">
<div class="col-lg-3">
<label for="time_open">

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{% set cust = jo.getCustomer %}
{% set cv = jo.getCustomerVehicle %}
<strong>{{ cust.getNameDisplay }}</strong><br>
{{ cv.getPlateNumber }}<br>
<a href="{{ url('jo_onestep_edit_form', {'id': jo.getID}) }}">Job Order #{{ jo.getID }}</a><br>
{{ jo.getServiceTypeName }}<br>
{{ jo.getStatusText }}
{% if jo.getRider != null %}
<br><br>
{% set rider = jo.getRider %}
{{ rider.getFullName }}<br>
{{ rider.getPlateNumber }}
{% endif %}

View file

@ -2,7 +2,7 @@
{% set cv = jo.getCustomerVehicle %}
<strong>{{ cust.getNameDisplay }}</strong><br>
{{ cv.getPlateNumber }}<br>
<a href="{{ url('jo_onestep_edit_form', {'id': jo.getID}) }}">Job Order #{{ jo.getID }}</a><br>
<a href="{{ url('jo_open_edit_form', {'id': jo.getID}) }}">Job Order #{{ jo.getID }}</a><br>
{{ jo.getServiceTypeName }}<br>
{{ jo.getStatusText }}
{% if jo.getRider != null %}

View file

@ -1,27 +1,27 @@
# text
title_login: Res-Q for CMB | Login
block_title: Res-Q for CMB
title_login: Motolite Res-Q | Login
block_title: Motolite Res-Q
control_panel_sign_in: Sign-in to Control Panel
alt_image_logo_login: Res-Q for CMB
alt_image_dashboard: Res-Q for CMB
copyright: Res-Q for CMB
alt_image_logo_login: Res-Q
alt_image_dashboard: Motolite
copyright: Motolite Res-Q
battery_size_tradein_brand: Trade-in Motolite
battery_size_tradein_premium: Trade-in Premium
battery_size_tradein_other: Trade-in Other
add_cust_vehicle_battery_info: This vehicle is using a Motolite battery
jo_title_pdf: Res-Q for CMB Job Order
country_code_prefix: '+60'
delivery_instructions_label: 'CarFix Details'
jo_title_pdf: Motolite Res-Q Job Order
country_code_prefix: '+63'
delivery_instructions_label: Delivery Instructions
# images
image_logo_login: /assets/images/black-text-logo-01.png
icon_login: /assets/images/battery-assist-bm-logo-32x32.png
icon_base_32x32: /assets/images/black-text-logo-01-32x32.png
icon_base_16x16: /assets/images/black-text-logo-01-16x16.png
image_dashboard: /assets/images/century_logo.png
image_jo_pdf: /public/assets/images/black-text-logo-01-115x115.png
image_logo_login: /assets/images/logo-resq.png
icon_login: /assets/demo/default/media/img/logo/favicon.ico
icon_base_32x32: /assets/images/favicon/favicon-32x32.png
icon_base_16x16: /assets/images/favicon/favicon-16x16.png
image_dashboard: /assets/images/logo-motolite.png
image_jo_pdf: /public/assets/images/logo-resq.png
# default point for maps
default_lat: 3.084216
default_long: 101.6129996
default_region: my
default_lat: 14.6091
default_long: 121.0223
default_region: ph