From dafe7e6b1c8a8621e1a4dbde9a7f9630ef025354 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 5 Mar 2020 06:53:26 +0000 Subject: [PATCH 01/40] Modify access to getCustomerVehicles. #366 --- src/Controller/CustomerController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php index 7421fec0..dcbecc28 100644 --- a/src/Controller/CustomerController.php +++ b/src/Controller/CustomerController.php @@ -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_onestep.edit')) || + (!$this->isGranted('jo_walkin.edit'))) { $exception = $this->createAccessDeniedException('No access.'); throw $exception; } From 6a7cb9788e2b2e567d16015810761ff74cde4733 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 5 Mar 2020 08:36:24 +0000 Subject: [PATCH 02/40] Fix access to customer vehicle search for walkin and one step. #366 --- src/Controller/CustomerController.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php index dcbecc28..9b62df8c 100644 --- a/src/Controller/CustomerController.php +++ b/src/Controller/CustomerController.php @@ -182,9 +182,7 @@ class CustomerController extends Controller public function getCustomerVehicles(Request $req, CustomerHandlerInterface $cust_handler) { if ((!$this->isGranted('jo_onestep.form')) || - (!$this->isGranted('jo_walkin.form')) || - (!$this->isGranted('jo_onestep.edit')) || - (!$this->isGranted('jo_walkin.edit'))) { + (!$this->isGranted('jo_walkin.form'))) { $exception = $this->createAccessDeniedException('No access.'); throw $exception; } From 1829e9112e17c72f58b1b332291090621868aa3b Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 1 Apr 2020 04:30:08 +0000 Subject: [PATCH 03/40] Add error_logging in case of duplicate SAP battery. #371 --- src/Command/ImportSAPBatteryCommand.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Command/ImportSAPBatteryCommand.php b/src/Command/ImportSAPBatteryCommand.php index fcd54f7d..8ea53a1d 100644 --- a/src/Command/ImportSAPBatteryCommand.php +++ b/src/Command/ImportSAPBatteryCommand.php @@ -77,7 +77,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..."); @@ -110,11 +110,17 @@ 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 + { + // TODO: different batteries but same SKU: WCHD23BL-CPN00-LX + // how to process? + error_log('Battery with that sku already exists.'); + } } $em->flush(); From c38eb147c833126fc697fcca457aab83d8af07f7 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 1 Apr 2020 08:33:25 +0000 Subject: [PATCH 04/40] Add logging of duplicate entries when importing SAP batteries. #371 --- src/Command/AdjustLongLatCommand.php | 6 +- .../ComputeWarrantyExpiryDateCommand.php | 4 +- .../CreateCustomerFromWarrantyCommand.php | 4 +- src/Command/FulfillOldJobOrderCommand.php | 6 +- src/Command/FulfillPendingJobOrderCommand.php | 6 +- .../GenerateBatteryCompatibilityCommand.php | 6 +- .../GenerateWarrantyFromJobOrderCommand.php | 4 +- src/Command/ImportBatteryPriceCommand.php | 6 +- src/Command/ImportCustomerCommand.php | 4 +- src/Command/ImportLegacyJobOrderCommand.php | 6 +- src/Command/ImportOutletsCommand.php | 11 +-- src/Command/ImportPartnersCommand.php | 6 +- src/Command/ImportSAPBatteryCommand.php | 69 +++++++++++++++++-- src/Command/ImportVehicleBatteryCommand.php | 6 +- .../ImportVehicleCompatibilityCommand.php | 6 +- src/Command/MergeDuplicateVehiclesCommand.php | 6 +- src/Command/ReportRiderTime.php | 4 +- .../SetCustomerPrivacyPolicyCommand.php | 6 +- src/Command/TestRegAPNSCommand.php | 2 - .../UpdateCustomerVehicleBatteryCommand.php | 6 +- .../UpdateCustomerVehicleWarrantyCommand.php | 4 +- src/Command/UploadCleanupCommand.php | 11 +-- src/Command/UserCreateCommand.php | 11 +-- 23 files changed, 129 insertions(+), 71 deletions(-) diff --git a/src/Command/AdjustLongLatCommand.php b/src/Command/AdjustLongLatCommand.php index b7e26ad1..62405269 100644 --- a/src/Command/AdjustLongLatCommand.php +++ b/src/Command/AdjustLongLatCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\JobOrder; @@ -17,9 +17,9 @@ class AdjustLongLatCommand extends Command { protected $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/ComputeWarrantyExpiryDateCommand.php b/src/Command/ComputeWarrantyExpiryDateCommand.php index 383370f7..cffc24ef 100644 --- a/src/Command/ComputeWarrantyExpiryDateCommand.php +++ b/src/Command/ComputeWarrantyExpiryDateCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Battery; @@ -18,7 +18,7 @@ class ComputeWarrantyExpiryDateCommand extends Command protected $em; protected $wh; - public function __construct(ObjectManager $em, WarrantyHandler $wh) + public function __construct(EntityManagerInterface $em, WarrantyHandler $wh) { $this->em = $em; $this->wh = $wh; diff --git a/src/Command/CreateCustomerFromWarrantyCommand.php b/src/Command/CreateCustomerFromWarrantyCommand.php index 91684217..42b2fe73 100644 --- a/src/Command/CreateCustomerFromWarrantyCommand.php +++ b/src/Command/CreateCustomerFromWarrantyCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Warranty; use App\Entity\Customer; @@ -33,7 +33,7 @@ class CreateCustomerFromWarrantyCommand extends Command protected $cvu_mfg_id; protected $cvu_brand_id; - public function __construct(ObjectManager $em, $cvu_mfg_id, $cvu_brand_id) + public function __construct(EntityManagerInterface $em, $cvu_mfg_id, $cvu_brand_id) { $this->em = $em; diff --git a/src/Command/FulfillOldJobOrderCommand.php b/src/Command/FulfillOldJobOrderCommand.php index a0cabd57..dc987e8b 100644 --- a/src/Command/FulfillOldJobOrderCommand.php +++ b/src/Command/FulfillOldJobOrderCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\JobOrder; use App\Entity\JOEvent; @@ -22,9 +22,9 @@ class FulfillOldJobOrderCommand extends Command { protected $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/FulfillPendingJobOrderCommand.php b/src/Command/FulfillPendingJobOrderCommand.php index 22180186..0c1fe7b0 100644 --- a/src/Command/FulfillPendingJobOrderCommand.php +++ b/src/Command/FulfillPendingJobOrderCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\JobOrder; use App\Entity\JOEvent; @@ -22,9 +22,9 @@ class FulfillPendingJobOrderCommand extends Command { protected $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/GenerateBatteryCompatibilityCommand.php b/src/Command/GenerateBatteryCompatibilityCommand.php index 57e20076..ec0a1843 100644 --- a/src/Command/GenerateBatteryCompatibilityCommand.php +++ b/src/Command/GenerateBatteryCompatibilityCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\VehicleManufacturer; use App\Entity\Vehicle; @@ -21,9 +21,9 @@ class GenerateBatteryCompatibilityCommand extends Command protected $em; protected $vmfg_index; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php index 86653d97..1d3f100b 100644 --- a/src/Command/GenerateWarrantyFromJobOrderCommand.php +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\JobOrder; use App\Entity\Warranty; @@ -25,7 +25,7 @@ class GenerateWarrantyFromJobOrderCommand extends Command protected $sapbatt_hash; protected $warranties_hash; - public function __construct(ObjectManager $em) + public function __construct(EntityManagerInterface $em) { $this->em = $em; diff --git a/src/Command/ImportBatteryPriceCommand.php b/src/Command/ImportBatteryPriceCommand.php index 02bbbea9..12fade3a 100644 --- a/src/Command/ImportBatteryPriceCommand.php +++ b/src/Command/ImportBatteryPriceCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; use DateTime; @@ -30,9 +30,9 @@ class ImportBatteryPriceCommand extends Command protected $em; protected $size_index; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; $this->size_index = []; parent::__construct(); diff --git a/src/Command/ImportCustomerCommand.php b/src/Command/ImportCustomerCommand.php index f6babefc..4c0e75e7 100644 --- a/src/Command/ImportCustomerCommand.php +++ b/src/Command/ImportCustomerCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use DateTime; @@ -49,7 +49,7 @@ class ImportCustomerCommand extends Command protected $mfg_index; protected $vehicle_index; - public function __construct(ObjectManager $em) + public function __construct(EntityManagerInterface $em) { $this->em = $em; $this->populateMfgIndex(); diff --git a/src/Command/ImportLegacyJobOrderCommand.php b/src/Command/ImportLegacyJobOrderCommand.php index 7546880b..76e30d10 100644 --- a/src/Command/ImportLegacyJobOrderCommand.php +++ b/src/Command/ImportLegacyJobOrderCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Warranty; use App\Entity\Battery; @@ -44,9 +44,9 @@ class ImportLegacyJobOrderCommand extends Command protected $row_max_field_size; protected $data_max_field_size; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; $this->loadBatteryModels(); $this->loadBatterySizes(); diff --git a/src/Command/ImportOutletsCommand.php b/src/Command/ImportOutletsCommand.php index dbcb5979..1558b74e 100644 --- a/src/Command/ImportOutletsCommand.php +++ b/src/Command/ImportOutletsCommand.php @@ -7,7 +7,8 @@ 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\Common\Persistence\ObjectManager; + +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Outlet; use App\Entity\Hub; @@ -17,11 +18,11 @@ use DateTime; class ImportOutletsCommand extends Command { - private $object_manager; + private $em; - public function __construct(ObjectManager $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; diff --git a/src/Command/ImportPartnersCommand.php b/src/Command/ImportPartnersCommand.php index 74e02d5b..1a09df6d 100644 --- a/src/Command/ImportPartnersCommand.php +++ b/src/Command/ImportPartnersCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; use DateTime; @@ -34,9 +34,9 @@ class ImportPartnersCommand extends Command protected $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/ImportSAPBatteryCommand.php b/src/Command/ImportSAPBatteryCommand.php index 8ea53a1d..9189a0e5 100644 --- a/src/Command/ImportSAPBatteryCommand.php +++ b/src/Command/ImportSAPBatteryCommand.php @@ -7,7 +7,8 @@ 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\Common\Persistence\ObjectManager; + +use Doctrine\ORM\EntityManagerInterface; use App\Entity\SAPBattery; use App\Entity\SAPBatteryBrand; @@ -22,7 +23,7 @@ class ImportSAPBatteryCommand extends Command private $batt_size_hash; private $batt_brand_hash; - public function __construct(ObjectManager $em) + public function __construct(EntityManagerInterface $em) { $this->em = $em; $this->initBatteryHash(); @@ -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) { @@ -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])) @@ -117,13 +132,19 @@ class ImportSAPBatteryCommand extends Command } else { - // TODO: different batteries but same SKU: WCHD23BL-CPN00-LX - // how to process? - error_log('Battery with that sku already exists.'); + $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); + } } protected function initBatteryHash() @@ -152,4 +173,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); + + } } diff --git a/src/Command/ImportVehicleBatteryCommand.php b/src/Command/ImportVehicleBatteryCommand.php index 93c0bd77..c3511330 100644 --- a/src/Command/ImportVehicleBatteryCommand.php +++ b/src/Command/ImportVehicleBatteryCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; use DateTime; @@ -35,9 +35,9 @@ class ImportVehicleBatteryCommand extends Command protected $batt_index; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; $this->vmfg_index = []; $this->v_index = []; $this->batt_index = []; diff --git a/src/Command/ImportVehicleCompatibilityCommand.php b/src/Command/ImportVehicleCompatibilityCommand.php index 29d74417..481579e1 100644 --- a/src/Command/ImportVehicleCompatibilityCommand.php +++ b/src/Command/ImportVehicleCompatibilityCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; use DateTime; @@ -28,9 +28,9 @@ class ImportVehicleCompatibilityCommand extends Command protected $bsize_index; protected $b_index; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; $this->vmfg_index = []; $this->v_index = []; $this->b_index = []; diff --git a/src/Command/MergeDuplicateVehiclesCommand.php b/src/Command/MergeDuplicateVehiclesCommand.php index a0b729cd..99bbbec4 100644 --- a/src/Command/MergeDuplicateVehiclesCommand.php +++ b/src/Command/MergeDuplicateVehiclesCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Vehicle; @@ -15,9 +15,9 @@ class MergeDuplicateVehiclesCommand extends Command { protected $em; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; parent::__construct(); } diff --git a/src/Command/ReportRiderTime.php b/src/Command/ReportRiderTime.php index 77d7f94d..e8825b5b 100644 --- a/src/Command/ReportRiderTime.php +++ b/src/Command/ReportRiderTime.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use DateTime; @@ -21,7 +21,7 @@ class ReportRiderTime extends Command protected $jo_index; protected $filtered_jo_index; - public function __construct(ObjectManager $em) + public function __construct(EntityManagerInterface $em) { $this->em = $em; diff --git a/src/Command/SetCustomerPrivacyPolicyCommand.php b/src/Command/SetCustomerPrivacyPolicyCommand.php index 4132fa91..e5d27617 100644 --- a/src/Command/SetCustomerPrivacyPolicyCommand.php +++ b/src/Command/SetCustomerPrivacyPolicyCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Customer; use App\Entity\PrivacyPolicy; @@ -22,10 +22,10 @@ class SetCustomerPrivacyPolicyCommand extends Command private $policy_third_party_id; private $policy_mobile_id; - public function __construct(ObjectManager $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; diff --git a/src/Command/TestRegAPNSCommand.php b/src/Command/TestRegAPNSCommand.php index d9615141..52ec7d76 100644 --- a/src/Command/TestRegAPNSCommand.php +++ b/src/Command/TestRegAPNSCommand.php @@ -7,8 +7,6 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; - use App\Service\APNSClient; use DateTime; diff --git a/src/Command/UpdateCustomerVehicleBatteryCommand.php b/src/Command/UpdateCustomerVehicleBatteryCommand.php index f7e09e30..57ad1246 100644 --- a/src/Command/UpdateCustomerVehicleBatteryCommand.php +++ b/src/Command/UpdateCustomerVehicleBatteryCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\JobOrder; @@ -18,9 +18,9 @@ class UpdateCustomerVehicleBatteryCommand extends Command protected $em; protected $custvehicle_hash; - public function __construct(ObjectManager $om) + public function __construct(EntityManagerInterface $em) { - $this->em = $om; + $this->em = $em; $this->custvehicle_hash = []; parent::__construct(); diff --git a/src/Command/UpdateCustomerVehicleWarrantyCommand.php b/src/Command/UpdateCustomerVehicleWarrantyCommand.php index 89b6e5e0..98fec1cb 100644 --- a/src/Command/UpdateCustomerVehicleWarrantyCommand.php +++ b/src/Command/UpdateCustomerVehicleWarrantyCommand.php @@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Warranty; use App\Entity\CustomerVehicle; @@ -19,7 +19,7 @@ class UpdateCustomerVehicleWarrantyCommand extends Command protected $em; protected $wh; - public function __construct(ObjectManager $em, WarrantyHandler $wh) + public function __construct(EntityManagerInterface $em, WarrantyHandler $wh) { $this->em = $em; $this->wh = $wh; diff --git a/src/Command/UploadCleanupCommand.php b/src/Command/UploadCleanupCommand.php index 94d22c6e..ffa1828b 100644 --- a/src/Command/UploadCleanupCommand.php +++ b/src/Command/UploadCleanupCommand.php @@ -7,7 +7,8 @@ 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\Common\Persistence\ObjectManager; + +use Doctrine\ORM\EntityManagerInterface; use App\Entity\Rider; use App\Entity\Battery; @@ -18,11 +19,11 @@ use DirectoryIterator; class UploadCleanupCommand extends Command { private $encoder_factory; - private $object_manager; + private $em; - public function __construct(ObjectManager $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']; diff --git a/src/Command/UserCreateCommand.php b/src/Command/UserCreateCommand.php index f0873dc1..3b10d771 100644 --- a/src/Command/UserCreateCommand.php +++ b/src/Command/UserCreateCommand.php @@ -8,7 +8,8 @@ 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\Common\Persistence\ObjectManager; + +use Doctrine\ORM\EntityManagerInterface; use App\Entity\User; use App\Entity\Role; @@ -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, ObjectManager $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) From 719cccf778503efb21c4094cbba0ee9a75ea0571 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 2 Apr 2020 03:33:02 +0000 Subject: [PATCH 05/40] Add API call to get warranties when given a list of serial numbers. #372 --- .../api-bundle/Command/TestAPICommand.php | 18 +++++++-- config/api_acl.yaml | 2 + config/routes/capi.yaml | 6 +++ src/Controller/CAPI/WarrantyController.php | 40 +++++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/catalyst/api-bundle/Command/TestAPICommand.php b/catalyst/api-bundle/Command/TestAPICommand.php index 7e959808..a8a2be2a 100644 --- a/catalyst/api-bundle/Command/TestAPICommand.php +++ b/catalyst/api-bundle/Command/TestAPICommand.php @@ -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,18 @@ 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', + ]; + + $params = [ + 'serial_list' => $serial_list, + ]; + + $api->post('/capi/warranties_list', $params); } } diff --git a/config/api_acl.yaml b/config/api_acl.yaml index 2ff18704..a7ad72d5 100644 --- a/config/api_acl.yaml +++ b/config/api_acl.yaml @@ -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: diff --git a/config/routes/capi.yaml b/config/routes/capi.yaml index ee3c8668..0c2e5ac1 100644 --- a/config/routes/capi.yaml +++ b/config/routes/capi.yaml @@ -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 diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index 83ecf74a..114f3c8c 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -502,6 +502,46 @@ 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 = []; + foreach ($serial_list as $serial) + { + $clean_serial = $this->cleanSerial($serial); + $warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $clean_serial]); + + if ($warr == null) + return new APIResponse(false, 'No warranty found with that serial number.', null, 404); + + $warranty_list[] = $this->generateWarrantyData($warr); + } + + + $data = [ + 'warranties' => $warranty_list, + ]; + + return new APIResponse(true, 'Warranties found.', $data); + } + protected function getCustomerFromMobile($em, $warranty) { $w_mobile = $warranty->getMobileNumber(); From 135ab10cd38c52d18a27765b6455de2f558b6e42 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 2 Apr 2020 03:58:21 +0000 Subject: [PATCH 06/40] Add to response the list of serials with no warranties. #372 --- catalyst/api-bundle/Command/TestAPICommand.php | 3 ++- src/Controller/CAPI/WarrantyController.php | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/catalyst/api-bundle/Command/TestAPICommand.php b/catalyst/api-bundle/Command/TestAPICommand.php index a8a2be2a..952b98b6 100644 --- a/catalyst/api-bundle/Command/TestAPICommand.php +++ b/catalyst/api-bundle/Command/TestAPICommand.php @@ -142,7 +142,8 @@ class TestAPICommand extends Command // get warranties given list of serial numbers $serial_list = [ 'AJ34LJADR12134LKJM4', - 'AJ34LJADR12134LKJL5', + 'AJ34LJADR12134LKJL5', + 'test', ]; $params = [ diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index 114f3c8c..affdb892 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -523,20 +523,22 @@ class WarrantyController extends APIController 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) - return new APIResponse(false, 'No warranty found with that serial number.', null, 404); - - $warranty_list[] = $this->generateWarrantyData($warr); + $warr_not_found_list[] = 'Warranty not found for ' . $clean_serial; + else + $warranty_list[] = $this->generateWarrantyData($warr); } $data = [ - 'warranties' => $warranty_list, + 'warranties_found' => $warranty_list, + 'warranties_not_found' => $warr_not_found_list, ]; return new APIResponse(true, 'Warranties found.', $data); From 1dac0c506e01fafe3007e31ef992e70142cc8c7d Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 2 Apr 2020 04:01:08 +0000 Subject: [PATCH 07/40] Remove message. #372 --- src/Controller/CAPI/WarrantyController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index affdb892..e5f5437e 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -530,7 +530,7 @@ class WarrantyController extends APIController $warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $clean_serial]); if ($warr == null) - $warr_not_found_list[] = 'Warranty not found for ' . $clean_serial; + $warr_not_found_list[] = $clean_serial; else $warranty_list[] = $this->generateWarrantyData($warr); } From 74ed1a72b67a9fd4ae0baf740f35016a9c8f69a8 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 3 Apr 2020 07:49:37 +0000 Subject: [PATCH 08/40] Made Resq default skin. #373 --- config/menu.yaml | 24 +++++++------ config/services.yaml | 67 ++++++++++++----------------------- translations/messages.en.yaml | 34 +++++++++--------- 3 files changed, 54 insertions(+), 71 deletions(-) diff --git a/config/menu.yaml b/config/menu.yaml index 9f28b315..b0096cf5 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -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 diff --git a/config/services.yaml b/config/services.yaml index 8fe325e4..1756cf98 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -157,62 +157,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: ~ diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index 3e12543b..c0fb8ca1 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -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 From 9a661763a00dc7045554b059d52aace6ddd9c7cc Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 6 Apr 2020 09:46:54 +0000 Subject: [PATCH 09/40] Add auto assign to controller. #374 --- config/acl.yaml | 2 + config/menu.yaml | 4 + config/routes/job_order.yaml | 9 + src/Controller/JobOrderController.php | 164 +- .../JobOrderHandler/ResqJobOrderHandler.php | 9 +- templates/job-order/autoassign.form.html.twig | 1774 +++++++++++++++++ 6 files changed, 1959 insertions(+), 3 deletions(-) create mode 100644 templates/job-order/autoassign.form.html.twig diff --git a/config/acl.yaml b/config/acl.yaml index c6ccc243..bfd6c6cc 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -264,6 +264,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 diff --git a/config/menu.yaml b/config/menu.yaml index b0096cf5..45ceab40 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -122,6 +122,10 @@ main_menu: acl: jo_all.list label: View All parent: joborder + - id: jo_autoassign + acl: jo_autoassign.test + label: Autoassign Test + parent: joborder - id: support acl: support.menu diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index d5cd8dfc..f239402d 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -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] diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 1d1d84c1..cdb2d665 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -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; @@ -96,7 +97,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->generateJobOrder($req, $id); + + $error_array = $result['error_array']; // check if any errors were found if (!empty($error_array)) { @@ -145,7 +148,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)) { @@ -1053,5 +1058,160 @@ 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) + { + $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); + + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + + } + + protected function autoAssignHubAndRider($jo, EntityManagerInterface $em, MapTools $map_tools) + { + // 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; + $nearest_hubs[] = $hub['hub']; + } + + // get battery sku + $invoice = $jo->getInvoice(); + if ($invoice != null) + { + $items = $invoice->getItems(); + $sku = ''; + foreach ($items as $item) + { + $sku = $item->getBattery()->getSAPCode(); + } + + // api call to check inventory + // pass the list of nearest hubs and the sku + // go through returned list of hubs for available riders + // for now, use all hubs + $hubs_with_inventory = $em->getRepository(Hub::class)->findAll(); + $nearest = []; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + // check rider availability + if (count($hub_with_inventory->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 ($hub_with_inventory->getID() == $nhd['hub']->getID()) + { + if (empty($nearest)) + { + $nearest = $nhd; + } + else + { + if ($nhd['distance'] < $nearest['distance']) + $nearest = $nhd; + } + } + } + } + } + + // return $nearest + error_log('Nearest Hub ' . $nearest['hub']->getID()); + error_log('With distance ' . $nearest['distance']); + + $jo->setHub($nearest['hub']); + + $hub_riders = $nearest['hub']->getAvailableRiders(); + $rider = null; + if (count($hub_riders) > 1) + { + // 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; + } } diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index a12e09d5..deeea114 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -405,7 +405,14 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } } - return $error_array; + $data['error_array'] = $error_array; + + if ($jo != null) + { + $data['job_order'] = $jo; + } + + return $data; } // dispatch job order diff --git a/templates/job-order/autoassign.form.html.twig b/templates/job-order/autoassign.form.html.twig new file mode 100644 index 00000000..bba70b39 --- /dev/null +++ b/templates/job-order/autoassign.form.html.twig @@ -0,0 +1,1774 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Job Order

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +

+ {% if mode == 'update-processing' %} + Dispatch + {{ obj.getID() }} + {% elseif mode == 'update-assigning' %} + Rider Assignment + {{ obj.getID() }} + {% elseif mode == 'update-reassign-hub' %} + Re-assign Hub + {{ obj.getID() }} + {% elseif mode == 'update-reassign-rider' %} + Re-assign Rider + {{ obj.getID() }} + {% elseif mode == 'update-all' %} + Viewing + {{ obj.getID() }} + {% else %} + Incoming + {% endif %} +

+
+
+
+
+ + + {% if mode in ['update-assigning', 'update-processing', 'update-reassign-hub', 'update-reassign-rider', 'update-all', 'open_edit'] %} + + {% endif %} +
+ + {% if ftags.vehicle_dropdown %} +
+
+
+ + + +
+ +
+
+
+
+
+ + + +
+
+
+ {% else %} + + {% endif %} + {% if obj.getReferenceJO %} +
+
+
+ + + +
+
+
+ {% endif %} + +
+
+

+ Customer Details +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+
+
+
+ + + +
+
+ + + +
+
+
+
+
+

+ Vehicle Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+
+
+

+ Battery Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+
+

+ Transaction Details +

+ + + +
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ +
+ + + + +
+ +
+
+ +
+ + + + +
+ +
+
+
+
+ + + +
+
+ + + +
+
+
+
+
+ + + +
+
+
+ + +
+
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+ +
+ + +
+
+
+
+
+ + + +
+
+
+ +
+
+
+
+

+ Location +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + + + +
+ + + + +
+
+
+
+
+
+
+
+

+ Invoice +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + {% if ftags.invoice_edit %} + + + {% else %} + + {% endif %} +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + + + + + + + + + + + {% if not obj.getInvoice or (obj.getInvoice and obj.getInvoice.getItems|length == 0) %} + + + + {% else %} + {% for item in obj.getInvoice.getItems %} + + + + + + + {% endfor %} + {% endif %} + +
ItemQuantityUnit PriceAmount
+ No items to display. +
{{ item.getTitle }}{{ item.getQuantity|number_format }}{{ item.getPrice|number_format(2) }}{{ (item.getPrice * item.getQuantity)|number_format(2) }}
+
+
+ {% if ftags.invoice_edit %} +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + +
+
+ {% endif %} +
+ + {% if mode in ['update-processing', 'update-reassign-hub'] %} +
+
+
+

+ Nearest Hubs +

+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + {% for hub in hubs %} + + + + + + + + + + {% endfor %} + +
HubBranchAvailable RidersJobs For AssignmentContact NumbersAction
+ No items to display. +
{{ hub.hub.getName }}{{ hub.hub.getBranch }}{{ hub.rider_count }}{{ hub.jo_count }}{{ hub.hub.getContactNumbers|replace({"\n": ', '}) }} + {% if hub.flag_rejected %} + + {% else %} + + {% endif %} +
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ {% endif %} + + {% if mode in ['update-assigning', 'update-fulfillment', 'update-reassign-rider', 'update-all'] %} +
+ {% if obj.getHub %} +
+
+

+ Hub Details +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+ {% endif %} + +
+ + {% if mode in ['update-assigning', 'update-reassign-rider'] %} +
+
+

+ Rider Assignment +

+
+
+
+ + +
+ + + + + + + + + + + + + {% set avail_riders = obj.getHub.getAvailableRiders|default([]) %} + + + + + {% if obj.getHub %} + {% for rider in avail_riders %} + + + + + + + + + {% endfor %} + {% endif %} + +
First NameLast NameContact No.Plate NumberStatus
+ No riders available. +
+
+
{{ rider.getFirstName }}{{ rider.getLastName }}{{ rider.getContactNumber }}{{ rider.getPlateNumber }}
+
+
+
+
+ {% endif %} + + {% if mode in ['update-fulfillment', 'update-all'] %} + {% if obj.getRider %} +
+
+

+ Rider Details +

+
+
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+
+
+
+ {% endif %} + {% endif %} + {% endif %} + + {% if mode == 'update-all' %} +
+ +
+
+

+ Timeline +

+
+
+
+
+
+ {% for event in obj.getEvents %} +
+ + {{ event.getDateHappen|date("M j, Y") }} +
{{ event.getDateHappen|date("h:i:s a") }}
+
+
+ +
+
+ {{ event.getTypeName }} by {{ event.getUser.getFullName|default('Application') }} {% if event.getRider %} - Rider - {{ event.getRider.getFullName }}{% endif %} +
+
+ {% endfor %} +
+
+
+
+
+ {% endif %} + + {% if ftags.ticket_table %} +
+ +
+
+

+ Tickets +

+
+
+
+
+
+
+
+ +
+
+ {% endif %} + +
+
+
+
+
+ {% if mode != 'update-all' %} + + {% endif %} + {% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %} + Cancel Job Order + {% endif %} + {% if mode != 'create' %} + Back + {% endif %} +
+
+
+
+
+
+
+
+
+ + {% if mode in ['update-processing', 'update-reassign-hub'] %} + + + {% endif %} +{% endblock %} + +{% block scripts %} +{{ include('map/' ~ map_js_file) }} + + + + +{% endblock %} + From 42abdd8097bb2b781d2a9d055a42e3ee369e7090 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Tue, 7 Apr 2020 11:24:23 +0800 Subject: [PATCH 10/40] Add z-index to dashboard map to allow for user and reports menu #364 --- templates/home.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/home.html.twig b/templates/home.html.twig index 19e99011..05fedfd9 100644 --- a/templates/home.html.twig +++ b/templates/home.html.twig @@ -5,7 +5,7 @@ {% endblock %} {% block body %} -
+
{% endblock %} From c62775c9909cbd75f618d2484e2e601ec346ac21 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 7 Apr 2020 03:27:39 +0000 Subject: [PATCH 11/40] Moved the autoAssign code into a service. #374 --- config/resq.services.yaml | 6 ++ config/services.yaml | 6 ++ src/Controller/JobOrderController.php | 108 +---------------------- src/Entity/Hub.php | 18 ++++ src/Service/InventoryManager.php | 122 ++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 105 deletions(-) create mode 100644 src/Service/InventoryManager.php diff --git a/config/resq.services.yaml b/config/resq.services.yaml index 1756cf98..f38949c5 100644 --- a/config/resq.services.yaml +++ b/config/resq.services.yaml @@ -226,3 +226,9 @@ services: $redis_prov: "@App\\Service\\RedisClientProvider" $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + + # inventory manager + App\Service\InventoryManager: + arguments: + $em: "@doctrine.orm.entity_manager" + $map_tools: "@App\\Service\\MapTools" diff --git a/config/services.yaml b/config/services.yaml index 1756cf98..f38949c5 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -226,3 +226,9 @@ services: $redis_prov: "@App\\Service\\RedisClientProvider" $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + + # inventory manager + App\Service\InventoryManager: + arguments: + $em: "@doctrine.orm.entity_manager" + $map_tools: "@App\\Service\\MapTools" diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index cdb2d665..97b49565 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -21,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; @@ -1078,7 +1079,7 @@ class JobOrderController extends Controller } public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler, - EntityManagerInterface $em, MapTools $map_tools) + InventoryManager $im) { $this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.'); @@ -1103,8 +1104,7 @@ class JobOrderController extends Controller if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) - $this->autoAssignHubAndRider($jo, $em, $map_tools); - + $im->autoAssignHubAndRider($jo); // return successful response return $this->json([ @@ -1112,106 +1112,4 @@ class JobOrderController extends Controller ]); } - - protected function autoAssignHubAndRider($jo, EntityManagerInterface $em, MapTools $map_tools) - { - // 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; - $nearest_hubs[] = $hub['hub']; - } - - // get battery sku - $invoice = $jo->getInvoice(); - if ($invoice != null) - { - $items = $invoice->getItems(); - $sku = ''; - foreach ($items as $item) - { - $sku = $item->getBattery()->getSAPCode(); - } - - // api call to check inventory - // pass the list of nearest hubs and the sku - // go through returned list of hubs for available riders - // for now, use all hubs - $hubs_with_inventory = $em->getRepository(Hub::class)->findAll(); - $nearest = []; - foreach ($hubs_with_inventory as $hub_with_inventory) - { - // check rider availability - if (count($hub_with_inventory->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 ($hub_with_inventory->getID() == $nhd['hub']->getID()) - { - if (empty($nearest)) - { - $nearest = $nhd; - } - else - { - if ($nhd['distance'] < $nearest['distance']) - $nearest = $nhd; - } - } - } - } - } - - // return $nearest - error_log('Nearest Hub ' . $nearest['hub']->getID()); - error_log('With distance ' . $nearest['distance']); - - $jo->setHub($nearest['hub']); - - $hub_riders = $nearest['hub']->getAvailableRiders(); - $rider = null; - if (count($hub_riders) > 1) - { - // 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; - } } diff --git a/src/Entity/Hub.php b/src/Entity/Hub.php index 840f6d8c..03e0b202 100644 --- a/src/Entity/Hub.php +++ b/src/Entity/Hub.php @@ -44,6 +44,12 @@ class Hub */ protected $outlets; + // branch code + /** + * @ORM\Column(type="string", length=80) + */ + protected $branch_code; + public function __construct() { $this->time_open = new DateTime(); @@ -114,4 +120,16 @@ class Hub { return $this->outlets; } + + public function setBranchCode($branch_code) + { + $this->branch_code = $branch_code; + return $this; + } + + public function getBranchCode() + { + return $this->branch_code; + } + } diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php new file mode 100644 index 00000000..6620e9ab --- /dev/null +++ b/src/Service/InventoryManager.php @@ -0,0 +1,122 @@ +em = $em; + $this->map_tools = $map_tools; + } + + public function autoAssignHubAndRider(JobOrder $jo) + { + // get the nearest 10 hubs + // TODO: move this snippet to a function + $hubs = $this->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 + //$nearest_hubs[] = $hub['hub']->getBranchCode(); + $nearest_hubs[] = $hub['hub']; + } + + // get battery sku + $invoice = $jo->getInvoice(); + if ($invoice != null) + { + $items = $invoice->getItems(); + $sku = ''; + foreach ($items as $item) + { + $sku = $item->getBattery()->getSAPCode(); + } + + // api call to check inventory + // pass the list of nearest hubs and the sku + // go through returned list of hubs for available riders + // for now, use all hubs + $hubs_with_inventory = $this->em->getRepository(Hub::class)->findAll(); + $nearest = []; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + // check rider availability + if (count($hub_with_inventory->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 ($hub_with_inventory->getID() == $nhd['hub']->getID()) + { + if (empty($nearest)) + { + $nearest = $nhd; + } + else + { + if ($nhd['distance'] < $nearest['distance']) + $nearest = $nhd; + } + } + } + } + } + + $jo->setHub($nearest['hub']); + + $hub_riders = $nearest['hub']->getAvailableRiders(); + $rider = null; + if (count($hub_riders) > 1) + { + // 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); + + $this->em->persist($jo); + $this->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; + } +} From eb5710b84686233d157a181ddd8a5055ef897eb0 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 7 Apr 2020 10:10:44 +0000 Subject: [PATCH 12/40] Create InventoryManager service to connect to API. #374 --- .env.dist | 6 ++ config/resq.services.yaml | 6 +- config/services.yaml | 6 +- src/Controller/JobOrderController.php | 125 +++++++++++++++++++++- src/Service/InventoryManager.php | 145 +++++++++----------------- 5 files changed, 186 insertions(+), 102 deletions(-) diff --git a/.env.dist b/.env.dist index 30f9a925..831c5f98 100644 --- a/.env.dist +++ b/.env.dist @@ -57,3 +57,9 @@ 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 diff --git a/config/resq.services.yaml b/config/resq.services.yaml index f38949c5..0c927f98 100644 --- a/config/resq.services.yaml +++ b/config/resq.services.yaml @@ -230,5 +230,7 @@ services: # inventory manager App\Service\InventoryManager: arguments: - $em: "@doctrine.orm.entity_manager" - $map_tools: "@App\\Service\\MapTools" + $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)%" diff --git a/config/services.yaml b/config/services.yaml index f38949c5..d3d6bd5a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -230,5 +230,7 @@ services: # inventory manager App\Service\InventoryManager: arguments: - $em: "@doctrine.orm.entity_manager" - $map_tools: "@App\\Service\\MapTools" + $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)%" diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 97b49565..26c9cb88 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1079,6 +1079,7 @@ class JobOrderController extends Controller } public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler, + EntityManagerInterface $em, MapTools $map_tools, InventoryManager $im) { $this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.'); @@ -1104,7 +1105,7 @@ class JobOrderController extends Controller if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) - $im->autoAssignHubAndRider($jo); + $this->autoAssignHubAndRider($jo, $em, $map_tools, $im); // return successful response return $this->json([ @@ -1112,4 +1113,126 @@ class JobOrderController extends Controller ]); } + + 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[] = $hub['hub']; + $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->getBranchInventory($nearest_branch_codes, $skus); + // TODO: check for empty result for now. + if (!empty($hubs_with_inventory)) + { + $nearest = []; + $flag_hub_found = false; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + error_log($hub_with_inventory['BranchCode']); + // 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; + } + } diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php index 6620e9ab..7a3250c5 100644 --- a/src/Service/InventoryManager.php +++ b/src/Service/InventoryManager.php @@ -2,121 +2,72 @@ namespace App\Service; -use Doctrine\ORM\EntityManagerInterface; - -use App\Entity\JobOrder; -use App\Entity\Hub; - -use App\Ramcar\JOStatus; - class InventoryManager { - protected $em; - protected $map_tools; + protected $api_url; + protected $api_ocp_key; + protected $api_auth_prefix; + protected $api_auth_token; - public function __construct(EntityManagerInterface $em, MapTools $map_tools) + public function __construct($api_url, $api_ocp_key, $api_auth_prefix, $api_auth_token) { - $this->em = $em; - $this->map_tools = $map_tools; + $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 autoAssignHubAndRider(JobOrder $jo) + public function getBranchInventory($nearest_branch_codes, $skus) { - // get the nearest 10 hubs - // TODO: move this snippet to a function - $hubs = $this->map_tools->getClosestHubs($jo->getCoordinates(), 10, date("H:i:s")); + // api call to check inventory + // pass the list of branch codes and the skus + $data = [ + "BranchCodes" => $nearest_branch_codes, + "Skus" => $skus, + ]; - $nearest_hubs = []; - $nearest_hubs_with_distance = []; + $json_data = json_encode($data); + error_log('JSON ' . $json_data); - foreach ($hubs as $hub) - { - $nearest_hubs_with_distance[] = $hub; - // TODO: uncomment this when we have branch codes in data - //$nearest_hubs[] = $hub['hub']->getBranchCode(); - $nearest_hubs[] = $hub['hub']; - } + // initializes a new cURL session + $curl = curl_init($this->api_url); - // get battery sku - $invoice = $jo->getInvoice(); - if ($invoice != null) - { - $items = $invoice->getItems(); - $sku = ''; - foreach ($items as $item) - { - $sku = $item->getBattery()->getSAPCode(); - } + // Set the CURLOPT_RETURNTRANSFER option to true + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - // api call to check inventory - // pass the list of nearest hubs and the sku - // go through returned list of hubs for available riders - // for now, use all hubs - $hubs_with_inventory = $this->em->getRepository(Hub::class)->findAll(); - $nearest = []; - foreach ($hubs_with_inventory as $hub_with_inventory) - { - // check rider availability - if (count($hub_with_inventory->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 ($hub_with_inventory->getID() == $nhd['hub']->getID()) - { - if (empty($nearest)) - { - $nearest = $nhd; - } - else - { - if ($nhd['distance'] < $nearest['distance']) - $nearest = $nhd; - } - } - } - } - } + // Set the CURLOPT_POST option to true for POST request + curl_setopt($curl, CURLOPT_POST, true); - $jo->setHub($nearest['hub']); + // Set the request data as JSON using json_encode function + curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data); - $hub_riders = $nearest['hub']->getAvailableRiders(); - $rider = null; - if (count($hub_riders) > 1) - { - // this will no longer be necessary when the contents - // of randomizeRider changes - $available_riders = []; - foreach ($hub_riders as $rider) - { - $available_riders[] = $rider; - } + // set timeout + curl_setopt($curl, CURLOPT_TIMEOUT, 300); - $rider = $this->randomizeRider($available_riders); - } - else - $rider = $hub_riders[0]; + $authorization = $this->api_auth_prefix . ' ' . $this->api_auth_token; + $ocp = $this->api_ocp_key; - $jo->setRider($rider); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Authorization: ' . $authorization, + 'Content-Type: application/json', + 'Ocp-Apim-Subscription-Key: ' . $ocp, + ]); - $jo->setStatus(JOStatus::ASSIGNED); + $response = curl_exec($curl); - $this->em->persist($jo); - $this->em->flush(); + // close cURL session + curl_close($curl); - } + // response is array of these + // { + // "BranchCode": "TestBranch1", + // "BranchName": "Test Branch", + // "SapCode": "WMGD31EL-CPNM0-L", + // "Quantity": 4 + // }, + $results = json_decode($response, true); + + return $results; } - 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; - } } From 6c02c303706049480119d5110d774c420be4e71e Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 Apr 2020 02:32:16 +0000 Subject: [PATCH 13/40] Update function name. Add checking for empty response in getBranchesInventory. #374 --- src/Controller/JobOrderController.php | 4 +--- src/Service/InventoryManager.php | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 26c9cb88..bee059bc 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1150,15 +1150,13 @@ class JobOrderController extends Controller // 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->getBranchInventory($nearest_branch_codes, $skus); - // TODO: check for empty result 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) { - error_log($hub_with_inventory['BranchCode']); // find hub according to branch code $found_hub = $em->getRepository(Hub::class)->findOneBy(['branch_code' => $hub_with_inventory['BranchCode']]); if ($found_hub != null) diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php index 7a3250c5..4dc5a8b1 100644 --- a/src/Service/InventoryManager.php +++ b/src/Service/InventoryManager.php @@ -17,7 +17,7 @@ class InventoryManager $this->api_auth_token = $api_auth_token; } - public function getBranchInventory($nearest_branch_codes, $skus) + public function getBranchesInventory($nearest_branch_codes, $skus) { // api call to check inventory // pass the list of branch codes and the skus @@ -60,12 +60,19 @@ class InventoryManager // response is array of these // { - // "BranchCode": "TestBranch1", - // "BranchName": "Test Branch", + // "Id": 37, + // "BranchCode": "WestAve", + // "BranchName": "West ave. Branch", + // "BranchRole": 0, + // "Name": "3SMF / GOLD ", // "SapCode": "WMGD31EL-CPNM0-L", - // "Quantity": 4 - // }, - $results = json_decode($response, true); + // "Quantity": 38 + // } + + // check if the response is empty + $results = []; + if (!empty($response)) + $results = json_decode($response, true); return $results; } From ab6ed4a185ded47ed677fb65775b6291d3c92b83 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 Apr 2020 07:34:28 +0000 Subject: [PATCH 14/40] Add auto assignment of hub and rider to APIController. #374 --- src/Controller/APIController.php | 126 +++++++++++++++++++++++++- src/Controller/JobOrderController.php | 1 - 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 9765ad8f..194c14be 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -29,6 +29,8 @@ 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\Entity\MobileSession; use App\Entity\Customer; @@ -45,6 +47,7 @@ use App\Entity\Service; use App\Entity\Partner; use App\Entity\Review; use App\Entity\PrivacyPolicy; +use App\Entity\Hub; use DateTime; use Exception; @@ -817,7 +820,8 @@ 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) { // check required parameters and api key $required_params = [ @@ -982,6 +986,42 @@ 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); + 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); + } + } + } + $em->persist($jo); $em->persist($invoice); @@ -2213,4 +2253,88 @@ class APIController extends Controller return $cust; } + protected function findNearestHubWithInventory($jo, Battery $batt, EntityManagerInterface $em, + MapTools $map_tools, InventoryManager $im) + { + // get the nearest 10 hubs + $selected_hub = null; + $hubs = $map_tools->getClosestHubs($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; + + // 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 + $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; + } + } diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index bee059bc..c92de36a 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1130,7 +1130,6 @@ class JobOrderController extends Controller // 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[] = $hub['hub']; $nearest_branch_codes = ['WestAve','jay_franchise']; } From 917459f228ce80ec8e49eb5bc90b357784751ddd Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 Apr 2020 09:31:28 +0000 Subject: [PATCH 15/40] Comment out call to inventory manager. #374 --- src/Controller/APIController.php | 36 +++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 194c14be..d0099e73 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -2265,15 +2265,36 @@ class APIController extends Controller foreach ($hubs as $hub) { $nearest_hubs_with_distance[] = $hub; - if (!empty($hub['hub']->getBranchCode())) - $nearest_branch_codes[] = $hub['hub']->getBranchCode(); + //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; + //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(); @@ -2281,7 +2302,8 @@ class APIController extends Controller // 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); + // bypass inventory check for now + // $hubs_with_inventory = $im->getBranchesInventory($nearest_branch_codes, $skus); if (!empty($hubs_with_inventory)) { $nearest = []; @@ -2320,8 +2342,8 @@ class APIController extends Controller } } $selected_hub = $nearest['hub']; - } - } + } + } */ return $selected_hub; } From 8619c493978dbaf71c9de36a9021859d21996d33 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 Apr 2020 09:39:42 +0000 Subject: [PATCH 16/40] Add the status_open field in Hub. #374 --- src/Entity/Hub.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Entity/Hub.php b/src/Entity/Hub.php index 03e0b202..f92a424e 100644 --- a/src/Entity/Hub.php +++ b/src/Entity/Hub.php @@ -50,12 +50,19 @@ class Hub */ 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() @@ -132,4 +139,15 @@ class Hub return $this->branch_code; } + public function setStatusOpen($status = true) + { + $this->status_open = $status; + return $this; + } + + public function isStatusOpen() + { + return $this->status_open; + } + } From e1b27dea9a75f0df0cd740010e55b88406041220 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 Apr 2020 10:11:43 +0000 Subject: [PATCH 17/40] Add branch_code and status_open to hub form. #374 --- src/Controller/HubController.php | 4 +++- templates/hub/form.html.twig | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Controller/HubController.php b/src/Controller/HubController.php index e1d41525..d6334c80 100644 --- a/src/Controller/HubController.php +++ b/src/Controller/HubController.php @@ -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) diff --git a/templates/hub/form.html.twig b/templates/hub/form.html.twig index df8a7190..aed63021 100644 --- a/templates/hub/form.html.twig +++ b/templates/hub/form.html.twig @@ -82,6 +82,24 @@ +
+
+ + + +
+
+ + + +
+