diff --git a/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php new file mode 100644 index 00000000..1599eef3 --- /dev/null +++ b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php @@ -0,0 +1,463 @@ +em = $em; + $this->vmfg_index = []; + $this->v_index = []; + $this->batt_index = []; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('yokohamavehicle:import') + ->setDescription('Import Yokohama data CSV file with vehicles and batteries.') + ->setHelp('Creates vehicles and batteries based on imported Yokohama CSV.') + ->addArgument('input_file', InputArgument::REQUIRED, 'Path to the CSV file.') + ->addArgument('output_file', InputArgument::REQUIRED, 'Path to output file.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $csv_file = $input->getArgument('input_file'); + $output_file = $input->getArgument('output_file'); + + $this->populateVehicleManufacturerIndex(); + $this->populateVehicleIndex(); + $this->populateBatteryIndex(); + + // attempt to open file + try + { + $fh = fopen($csv_file, "r"); + } + catch (Exception $e) + { + throw new Exception('The file "' . $csv_file . '" could be read.'); + } + + // get entity manager + $em = $this->em; + + $vbrands = []; + $output_info = []; + + // loop through rows + $row_num = 1; + $prem_mf_name = ''; + $prem_lm_name = ''; + $super_prem_mf_name = ''; + $supreme_mf_name = ''; + $platinum_mf_name = ''; + while (($fields = fgetcsv($fh)) !== false) + { + $output->writeln("Parsing row " . $row_num . "..."); + + // alternate brands are not in file, so we just comment out + // get the alternate battery brand header names + /* + if ($row_num == 2) + { + $prem_mf_name = $this->normalizeName($fields[SELF::F_B_ALT_PREM_MF]); + $prem_lm_name = $this->normalizeName($fields[SELF::F_B_ALT_PREM_LM]); + $super_prem_mf_name = $this->normalizeName($fields[SELF::F_B_ALT_SUPER_PREM_MF]); + $supreme_mf_name = $this->normalizeName($fields[SELF::F_B_ALT_SUPREME_MF]); + $platinum_mf_name = $this->normalizeName($fields[SELF::F_B_ALT_PLATINUM_MF]); + } + */ + + // process row + $output_info[] = $this->processRow($fields, $vbrands, $row_num, $prem_mf_name, $prem_lm_name, + $super_prem_mf_name, $supreme_mf_name, $platinum_mf_name); + + $row_num++; + } + + // save to db the valid ones + foreach ($vbrands as $brand_name => $vbrand) + { + // vehicles + foreach ($vbrand['vehicles'] as $row_num => $vdata) + { + $model = $vdata['model']; + if ($model == 'NONE') + { + $m_year_from = 0; + $m_year_to = 0; + } + else + { + $ex_model = explode('-', $model); + $m_year_from = trim($ex_model[0]); + + if (isset($ex_model[1])) + $m_year_to = trim($ex_model[1]); + else + $m_year_to = 0; + } + + $vehicle = $this->v_index[$brand_name][$vdata['make'] . '|' . intval($m_year_from) . '|' . intval($m_year_to)]; + + // recommended battery + $vdata['battery']->addVehicle($vehicle); + + // alt_batteries + // alternate brands are not in file, so we just comment out + /* + if (isset($vdata['alt_battery_prem_mf'])) + $vdata['alt_battery_prem_mf']->addVehicle($vehicle); + if (isset($vdata['alt_battery_prem_lm'])) + $vdata['alt_battery_prem_lm']->addVehicle($vehicle); + if (isset($vdata['alt_battery_super_prem_mf'])) + $vdata['alt_battery_super_prem_mf']->addVehicle($vehicle); + if (isset($vdata['alt_battery_supreme_mf'])) + $vdata['alt_battery_supreme_mf']->addVehicle($vehicle); + if (isset($vdata['alt_battery_platinum_mf'])) + $vdata['alt_battery_platinum_mf']->addVehicle($vehicle); + */ + } + } + + $em->flush(); + + // write to output file + // error_log(print_r($output_info, true)); + $this->outputVehicleBatteryInfo($output_file, $output_info); + + fclose($fh); + + return 0; + } + + protected function processRow($fields, &$vbrands, $row_num, $prem_mf_name, $prem_lm_name, + $super_prem_mf_name, $supreme_mf_name, $platinum_mf_nam) + { + $output_info = []; + $brand = $this->normalizeName($fields[0]); + $make = $this->normalizeName($fields[1]); + $model = trim($fields[2]); + $bsize = $this->normalizeName($fields[self::F_B_SIZE]); + $bmodel = $this->normalizeName($fields[self::F_B_MODEL]); + + // checking for valid vehicles and batteries should be done here so that only valid entries + // go into the vbrands array + $output_info = $this->validateManufacturerVehicle($fields, $brand, $make, $model, $bsize, $bmodel); + + if (!empty($output_info)) + return $output_info; + + if (!isset($vbrands[$brand])) + { + // build array + $vbrands[$brand] = [ + 'vehicles' => [], + ]; + } + + if (empty($model)) + $model = 'NONE'; + + $vbrands[$brand]['vehicles'][$row_num] = [ + 'make' => $make, + 'model' => $model, + ]; + + // at this point we are sure we have battery + $batt_key = $this->getBatteryKey($bsize, $bmodel); + $vbrands[$brand]['vehicles'][$row_num]['battery'] = $this->batt_index[$batt_key]; + + // alternate brands are not in file, so we just comment out + // need to check alternate brands if battery exists + // go through the alternate fields, look for 'P'. Not kidding. It's what is in the csv file. + /* + if ($this->normalizeName($fields[SELF::F_B_ALT_PREM_MF]) == 'P') + { + // check if we have battery for name + size combo + $alt_batt_key = $this->getBatteryKey($field_bsize, $prem_mf_name); + if (isset($this->batt_index[$alt_batt_key])) + { + $vbrands[$brand]['vehicles'][$row_num]['alt_battery_prem_mf'] = $this->batt_index[$alt_batt_key]; + } + } + if ($this->normalizeName($fields[SELF::F_B_ALT_PREM_LM]) == 'P') + { + // check if we have battery for name + size combo + $alt_batt_key = $this->getBatteryKey($field_bsize, $prem_lm_name); + if (isset($this->batt_index[$alt_batt_key])) + { + $vbrands[$brand]['vehicles'][$row_num]['alt_battery_prem_lm'] = $this->batt_index[$alt_batt_key]; + } + } + if ($this->normalizeName($fields[SELF::F_B_ALT_SUPER_PREM_MF]) == 'P') + { + // check if we have battery for name + size combo + $alt_batt_key = $this->getBatteryKey($field_bsize, $super_prem_mf_name); + if (isset($this->batt_index[$alt_batt_key])) + { + $vbrands[$brand]['vehicles'][$row_num]['alt_battery_super_prem_mf'] = $this->batt_index[$alt_batt_key]; + } + } + if ($this->normalizeName($fields[SELF::F_B_ALT_SUPREME_MF]) == 'P') + { + // check if we have battery for name + size combo + $alt_batt_key = $this->getBatteryKey($field_bsize, $supreme_mf_name); + if (isset($this->batt_index[$alt_batt_key])) + { + $vbrands[$brand]['vehicles'][$row_num]['alt_battery_supreme_mf'] = $this->batt_index[$alt_batt_key]; + } + } + if ($this->normalizeName($fields[SELF::F_B_ALT_PLATINUM_MF]) == 'P') + { + // check if we have battery for name + size combo + $alt_batt_key = $this->getBatteryKey($field_bsize, $platinum_mf_name); + if (isset($this->batt_index[$alt_batt_key])) + { + $vbrands[$brand]['vehicles'][$row_num]['alt_battery_platinum_mf'] = $this->batt_index[$alt_batt_key]; + } + } + */ + } + + protected function validateManufacturerVehicle($fields, $brand, $make, $model, $bsize, $bmodel) + { + $output_info = []; + + // check if manufacturer is blank + if (empty($brand)) + { + $message = 'No manufacturer provided.'; + $output_info = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $output_info; + } + + // check if make is blank + if (empty($make)) + { + $message = 'No make provided.'; + $output_info = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $output_info; + } + + // process model year data + if ($model == 'NONE') + { + $m_year_from = 0; + $m_year_to = 0; + } + else + { + $ex_model = explode('-', $model); + $m_year_from = trim($ex_model[0]); + + if (isset($ex_model[1])) + $m_year_to = trim($ex_model[1]); + else + $m_year_to = 0; + } + + // get manufacturer or make one + if (!isset($this->vmfg_index[$brand])) + { + // manufacturer + $mfg = new VehicleManufacturer(); + $mfg->setName($brand); + $this->em->persist($mfg); + } + else + { + $mfg = $this->vmfg_index[$brand]; + } + + if (!isset($this->v_index[$brand][$make . '|' . intval($m_year_from) . '|' . intval($m_year_to)])) + { + // vehicle + $vehicle = new Vehicle(); + $vehicle->setManufacturer($mfg) + ->setMake($make) + ->setModelYearFrom($m_year_from) + ->setModelYearTo($m_year_to); + $this->em->persist($vehicle); + } + else + { + $vehicle = $this->v_index[$brand][$make . '|' . intval($m_year_from) . '|' . intval($m_year_to)]; + } + + // save to db new manufacturer and vehicle + $this->em->flush(); + + // add the vehicle manufacturer to hash + $this->vmfg_index[$brand] = $mfg; + + // add the new vehicle to hash + $this->v_index[$brand][$make . '|' . $m_year_from . '|' . $m_year_to] = $vehicle; + + // recommended battery + $batt_key = $this->getBatteryKey($bsize, $bmodel); + if (!isset($this->batt_index[$batt_key])) + { + $message = 'Could not find battery - ' . $bsize . ' - ' . $bmodel; + $output_info = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $output_info; + } + + return $output_info; + } + + protected function setOutputInfo($fields, $status, $reason) + { + $mfg_name = trim($fields[SELF::F_V_BRAND]); + $model_name = trim($fields[SELF::F_V_MAKE]); + $model_year = trim($fields[SELF::F_V_MODEL_YEAR]); + $bsize = trim($fields[SELF::F_B_SIZE]); + $bmodel = trim($fields[SELF::F_B_MODEL]); + // alternate brands are not in file, so we just comment out + /* + $alt_prem_mf = trim($fields[SELF::F_B_ALT_PREM_MF]); + $alt_prem_lm = trim($fields[SELF::F_B_ALT_PREM_LM]); + $alt_super_prem_mf = trim($fields[SELF::F_B_ALT_SUPER_PREM_MF]); + $alt_supreme_mf = trim($fields[SELF::F_B_ALT_SUPREME_MF]); + $alt_platinum_mf = trim($fields[SELF::F_B_ALT_PLATINUM_MF]); + */ + + return [ + $mfg_name, + $model_name, + $model_year, + $bsize, + $bmodel, + $status, + $reason + ]; + } + + protected function outputVehicleBatteryInfo($output_file, $entries) + { + try + { + $fh = fopen($output_file, "w"); + } + catch (Exception $e) + { + throw new Exception('The file "' . $report_file . '" could be opened.'); + } + + // write the headers + fputcsv($fh, [ + 'Manufacturer', + 'Vehicle Model', + 'Year Model', + 'Battery Size', + 'Battery Model', + 'Status', + 'Reason', + ]); + + foreach($entries as $row) + { + if ($row != null) + fputcsv($fh, $row); + } + + fclose($fh); + } + + protected function populateVehicleManufacturerIndex() + { + $vmfgs = $this->em->getRepository(VehicleManufacturer::class)->findAll(); + + $this->vmfg_index = []; + + foreach ($vmfgs as $vmfg) + { + $mfg_name = $this->normalizeName($vmfg->getName()); + $this->vmfg_index[$mfg_name] = $vmfg; + } + } + + protected function populateVehicleIndex() + { + $vs = $this->em->getRepository(Vehicle::class)->findAll(); + + $this->v_index = []; + foreach ($vs as $v) + { + $mfg_name = $this->normalizeName($v->getManufacturer()->getName()); + if (!isset($this->v_index[$mfg_name])) + $this->v_index[$mfg_name] = []; + + $this->v_index[$mfg_name][$this->normalizeName($v->getMake()) . '|' . $v->getModelYearFrom() . '|' . $v->getModelYearTo()] = $v; + } + } + + protected function populateBatteryIndex() + { + $bs = $this->em->getRepository(Battery::class)->findAll(); + + $this->batt_index = []; + foreach ($bs as $b) + { + // get the battery size + $bsize = $b->getSize()->getName(); + + $key = $this->getBatteryKey($bsize, $b->getModel()->getName()); + + $this->batt_index[$key] = $b; + } + } + + protected function getBatteryKey($size_name, $model_name) + { + return $this->normalizeName(str_replace(' ', '', $size_name)) . + '|' . + $this->normalizeName(str_replace(' ', '', $model_name)); + } + + protected function normalizeName($name) + { + $normalized_key = trim(strtoupper($name)); + + return $normalized_key; + } + +} diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 4c23cb17..f1721149 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -249,7 +249,7 @@ class APIController extends Controller implements LoggedController $rt->sendSMS($phone_number, $translator->trans('message.battery_brand_allcaps'), $message); } - public function confirmNumber(RisingTideGateway $rt, Request $req) + public function confirmNumber(RisingTideGateway $rt, Request $req, TranslatorInterface $translator) { // check parameters $required_params = [ @@ -306,7 +306,7 @@ class APIController extends Controller implements LoggedController if ($otp_mode != 'test') { // send sms to number - $this->sendConfirmationCode($rt, $phone_number, $code); + $this->sendConfirmationCode($rt, $phone_number, $code, $translator); } // response @@ -630,8 +630,8 @@ class APIController extends Controller implements LoggedController ->setPlateNumber($req->request->get('plate_num')) ->setModelYear($req->request->get('model_year')) ->setColor($req->request->get('color')) - ->setFuelType($req->request->get('fuel_type')) - ->setStatusCondition($req->request->get('condition')); + ->setFuelType($this->normalizeString($req->request->get('fuel_type'))) + ->setStatusCondition($this->normalizeString($req->request->get('condition'))); // set warranty code and expiration // TODO: check warranty requirements @@ -4695,4 +4695,9 @@ class APIController extends Controller implements LoggedController return $jo_data; } + + protected function normalizeString($string) + { + return trim(strtolower($string)); + } } diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index fbab3cb2..f847a842 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -506,13 +506,13 @@ class JobOrderController extends Controller * @Menu(selected="jo_open") */ public function openHubForm(HubSelector $hub_selector, $id, JobOrderHandlerInterface $jo_handler, - GISManagerInterface $gis) + GISManagerInterface $gis, MotivConnector $motiv) { $this->denyAccessUnlessGranted('jo_open.list', null, 'No access.'); try { - $params = $jo_handler->initializeHubForm($id, $hub_selector); + $params = $jo_handler->initializeHubForm($id, $hub_selector, $motiv); } catch (NotFoundHttpException $e) { diff --git a/src/Controller/TicketController.php b/src/Controller/TicketController.php index 303b34a6..0f9f3cd9 100644 --- a/src/Controller/TicketController.php +++ b/src/Controller/TicketController.php @@ -4,6 +4,8 @@ namespace App\Controller; use App\Ramcar\TicketType; use App\Ramcar\TicketStatus; +use App\Ramcar\SourceOfAwareness; + use App\Entity\Ticket; use App\Entity\Customer; use App\Entity\JobOrder; @@ -172,6 +174,7 @@ class TicketController extends Controller $params['statuses'] = TicketStatus::getCollection(); $params['other_ticket_type'] = TicketType::OTHER; $params['redirect_url'] = $this->generateUrl('ticket_list'); + $params['soa_types'] = SourceOfAwareness::getCollection(); // set redirect url if ($customer) @@ -240,6 +243,12 @@ class TicketController extends Controller $other_ticket_type = $req->request->get('other_ticket_type'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + // set and save values $obj->setFirstName($first_name) ->setLastName($last_name) @@ -250,7 +259,9 @@ class TicketController extends Controller ->setDetails($req->request->get('details')) ->setPlateNumber($req->request->get('plate_number')) ->setDateCreate(new DateTime()) - ->setCreatedBy($this->getUser()); + ->setCreatedBy($this->getUser()) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // if assigned to customer, set association if ($customer_id) { @@ -326,6 +337,7 @@ class TicketController extends Controller $params['statuses'] = TicketStatus::getCollection(); $params['other_ticket_type'] = TicketType::OTHER; $params['redirect_url'] = $this->generateUrl('ticket_list'); + $params['soa_types'] = SourceOfAwareness::getCollection(); // set redirect url if ($customer) @@ -423,6 +435,12 @@ class TicketController extends Controller $other_ticket_type = $req->request->get('other_ticket_type'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + // set and save values $obj->setFirstName($first_name) ->setLastName($last_name) @@ -431,7 +449,9 @@ class TicketController extends Controller ->setTicketType($ticket_type) ->setOtherTicketType($other_ticket_type) ->setDetails($req->request->get('details')) - ->setPlateNumber($req->request->get('plate_number')); + ->setPlateNumber($req->request->get('plate_number')) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // initialize error list $error_array = []; diff --git a/src/Entity/JobOrder.php b/src/Entity/JobOrder.php index 591a982e..67f317ca 100644 --- a/src/Entity/JobOrder.php +++ b/src/Entity/JobOrder.php @@ -372,6 +372,18 @@ class JobOrder */ protected $rating; + // source of awareness + /** + * @ORM\Column(type="string", length=80, nullable=true) + */ + protected $source_of_awareness; + + // remarks related to source of awareness + /** + * @ORM\Column(type="text", nullable=true) + */ + protected $remarks; + public function __construct() { $this->date_create = new DateTime(); @@ -1061,4 +1073,26 @@ class JobOrder { return $this->rating; } + + public function setSourceOfAwareness($source_of_awareness) + { + $this->source_of_awareness = $source_of_awareness; + return $this; + } + + public function getSourceOfAwareness() + { + return $this->source_of_awareness; + } + + public function setRemarks($remarks) + { + $this->remarks = $remarks; + return $this; + } + + public function getRemarks() + { + return $this->remarks; + } } diff --git a/src/Entity/Ticket.php b/src/Entity/Ticket.php index 35882075..a3218c47 100644 --- a/src/Entity/Ticket.php +++ b/src/Entity/Ticket.php @@ -108,6 +108,18 @@ class Ticket */ protected $job_order; + // source of awareness + /** + * @ORM\Column(type="string", length=80, nullable=true) + */ + protected $source_of_awareness; + + // remarks related to source of awareness + /** + * @ORM\Column(type="text", nullable=true) + */ + protected $remarks; + public function __construct() { $this->date_create = new DateTime(); @@ -265,4 +277,27 @@ class Ticket { return $this->job_order; } + + public function setSourceOfAwareness($source_of_awareness) + { + $this->source_of_awareness = $source_of_awareness; + return $this; + } + + public function getSourceOfAwareness() + { + return $this->source_of_awareness; + } + + public function setRemarks($remarks) + { + $this->remarks = $remarks; + return $this; + } + + public function getRemarks() + { + return $this->remarks; + } + } diff --git a/src/Entity/Vehicle.php b/src/Entity/Vehicle.php index a93bed4e..61fdcec9 100644 --- a/src/Entity/Vehicle.php +++ b/src/Entity/Vehicle.php @@ -36,7 +36,7 @@ class Vehicle // make /** - * @ORM\Column(type="string", length=80) + * @ORM\Column(type="string", length=110) * @Assert\NotBlank() */ protected $make; diff --git a/src/Ramcar/SourceOfAwareness.php b/src/Ramcar/SourceOfAwareness.php new file mode 100644 index 00000000..656b1725 --- /dev/null +++ b/src/Ramcar/SourceOfAwareness.php @@ -0,0 +1,27 @@ + 'Facebook', + 'instagram' => 'Instagram', + 'radio_ads' => 'Radio Ads', + 'tarp_ads' => 'Tarp Ads', + 'flyers' => 'Flyers', + 'word_of_mouth' => 'Word of Mouth', + 'referral' => 'Referral', + 'other' => 'Other', + ]; +} + diff --git a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php index bc6f2d67..a79f3f5c 100644 --- a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php @@ -36,7 +36,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface const OTHER_SERVICES_FEE = 200; const COOLANT_FEE = 1600; const REFUEL_FEE_GAS = 320; - const REFUEL_FEE_DIESEL = 280; + const REFUEL_FEE_DIESEL = 340; private $security; protected $em; diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 1dc1e735..24933e8f 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -1873,7 +1873,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface } // initialize hub form - public function initializeHubForm($id, $map_tools) + public function initializeHubForm($id, $map_tools, $motiv) { $em = $this->em; diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index a5ce340a..4480c473 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -44,6 +44,7 @@ use App\Ramcar\WillingToWaitContent; use App\Ramcar\WarrantySource; use App\Ramcar\HubCriteria; use App\Ramcar\DeliveryStatus; +use App\Ramcar\SourceOfAwareness; use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; @@ -396,6 +397,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + // TODO: check status before saving since JO might already // have a status that needs to be retained @@ -427,7 +434,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) - ->setNoTradeInReason($no_trade_in_reason); + ->setNoTradeInReason($no_trade_in_reason) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // check if user is null, meaning call to create came from API if ($user != null) @@ -622,6 +631,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + if (empty($error_array)) { // get current user @@ -648,7 +663,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) - ->setNoTradeInReason($no_trade_in_reason); + ->setNoTradeInReason($no_trade_in_reason) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // did they change invoice? $invoice_items = $req->request->get('invoice_items', []); @@ -794,6 +811,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $more_reason = $req->request->get('not_wait_notes'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + if (empty($error_array)) { // coordinates @@ -817,7 +840,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setLandmark($req->request->get('landmark')) ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) - ->setNotWaitingNotes($more_reason); + ->setNotWaitingNotes($more_reason) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // validate $errors = $this->validator->validate($obj); @@ -909,6 +934,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $more_reason = $req->request->get('not_wait_notes'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + // get current user $user = $this->security->getUser(); @@ -934,7 +965,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) - ->setDeliveryStatus(DeliveryStatus::RIDER_ASSIGN); + ->setDeliveryStatus(DeliveryStatus::RIDER_ASSIGN) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); if ($user != null) { @@ -1015,6 +1048,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $more_reason = $req->request->get('not_wait_notes'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + if (empty($error_array)) { // coordinates $point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat')); @@ -1034,7 +1073,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) - ->setDeliveryStatus(DeliveryStatus::FULFILLED); + ->setDeliveryStatus(DeliveryStatus::FULFILLED) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks); // validate $errors = $this->validator->validate($obj); @@ -1235,6 +1276,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $more_reason = $req->request->get('not_wait_notes'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + // get previously assigned hub, if any $old_hub = $obj->getHub(); @@ -1269,6 +1316,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks) ->clearRider(); if ($user != null) @@ -1465,6 +1514,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $more_reason = $req->request->get('not_wait_notes'); } + // get source of awareness if any + $soa_type = $req->request->get('source_of_awareness'); + + // get remarks + $remarks = $req->request->get('remarks', ''); + if (empty($error_array)) { // rider mqtt event // NOTE: need to send this before saving because rider will be cleared @@ -1505,6 +1560,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ->setWillWait($req->request->get('flag_willing_to_wait')) ->setReasonNotWait($reason) ->setNotWaitingNotes($more_reason) + ->setSourceOfAwareness($soa_type) + ->setRemarks($remarks) ->setDeliveryStatus(DeliveryStatus::RIDER_ASSIGN); if ($user != null) @@ -2315,7 +2372,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } // initialize hub form - public function initializeHubForm($id, HubSelector $hub_selector) + public function initializeHubForm($id, HubSelector $hub_selector, $motiv) { $em = $this->em; @@ -2445,9 +2502,51 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } } - $params['hubs'][] = $hub; + // handle inventory data + $bcode = $hub['hub']->getBranchCode(); + $hub['inventory'] = 0; + if ($bcode != '') + { + $branch_codes[] = $bcode; + $inv_data[$bcode] = [ + 'hub_id' => $hub_id, + 'branch_code' => $bcode, + 'inventory' => 0, + ]; + } + + $params['hubs'][$hub_id] = $hub; } + // get battery (if any) + $skus = []; + $invoice = $obj->getInvoice(); + $inv_items = $invoice->getItems(); + foreach ($inv_items as $inv_item) + { + $batt = $inv_item->getBattery(); + if ($batt == null) + continue; + + $skus[] = $batt->getSapCode(); + } + + // get inventory + $mres = $motiv->getInventory($branch_codes, $skus); + foreach ($mres as $mres_item) + { + $bcode = $mres_item['BranchCode']; + $inv_count = $mres_item['Quantity']; + if (isset($inv_data[$bcode])) + { + $hub_id = $inv_data[$bcode]['hub_id']; + + $params['hubs'][$hub_id]['inventory'] = $inv_count; + } + } + + error_log(print_r($mres, true)); + $params['obj'] = $obj; // get template to display $params['template'] = $this->getTwigTemplate('jo_open_hub_form'); @@ -2969,6 +3068,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $params['willing_to_wait_content'] = WillingToWaitContent::getCollection(); $params['no_wait_reasons'] = CustomerNotWaitReason::getCollection(); $params['no_trade_in_reasons'] = NoTradeInReason::getCollection(); + $params['soa_types'] = SourceOfAwareness::getCollection(); } protected function initFormTags(&$params) diff --git a/src/Service/JobOrderHandlerInterface.php b/src/Service/JobOrderHandlerInterface.php index cff06242..644db54a 100644 --- a/src/Service/JobOrderHandlerInterface.php +++ b/src/Service/JobOrderHandlerInterface.php @@ -77,7 +77,7 @@ interface JobOrderHandlerInterface public function initializeFulfillmentForm(int $id); // initialize hub form - public function initializeHubForm(int $id, HubSelector $hub_selector); + public function initializeHubForm(int $id, HubSelector $hub_selector, $motiv); // initialize rider form public function initializeRiderForm(int $id); diff --git a/src/Service/RisingTideGateway.php b/src/Service/RisingTideGateway.php index acd7d4d5..0681edd4 100644 --- a/src/Service/RisingTideGateway.php +++ b/src/Service/RisingTideGateway.php @@ -32,6 +32,16 @@ class RisingTideGateway public function sendSMS($mobile_num, $mask, $message) { + // make sure number is acceptable to RT + // at this point, assume that mobile is numeric and valid mobile number + $clean_num = $this->cleanPhoneNumber($mobile_num); + + if ($clean_num === false) + { + error_log('Invalid mobile number provided. Cannot send SMS message to ' . $mobile_num); + return; + } + $headers = [ 'Content-Type: application/vnd.net.wyrls.Document-v3+json' ]; @@ -39,7 +49,7 @@ class RisingTideGateway $sms = new SMSMessage(); $sms->setFrom($this->shortcode) ->setFromAlias($mask) - ->setTo($mobile_num) + ->setTo($clean_num) ->setMessage($message) ->setStatus('sent'); @@ -54,7 +64,7 @@ class RisingTideGateway 'id' => $sms->getID(), 'from' => $this->shortcode, 'from_alias' => $mask, - 'to' => $mobile_num, + 'to' => $clean_num, 'content_type' => 'text/plain', 'body' => $message, 'date' => $date_string, @@ -67,21 +77,21 @@ class RisingTideGateway $userpwd = $this->user . ':' . $this->pass; - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, self::SERVER_URL); - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_VERBOSE, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $data_json); - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); - curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_setopt($curl, CURLOPT_USERPWD, $userpwd); - $result = curl_exec($curl); - error_log('error_no - ' . curl_errno($curl)); - $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE); - error_log($http_code); - curl_close($curl); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, self::SERVER_URL); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_VERBOSE, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($curl, CURLOPT_USERPWD, $userpwd); + $result = curl_exec($curl); + error_log('error_no - ' . curl_errno($curl)); + $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + error_log($http_code); + curl_close($curl); - error_log($result); + error_log($result); } public function validatePhoneNumber($mobile) @@ -107,4 +117,41 @@ class RisingTideGateway return true; } + + protected function cleanPhoneNumber($mobile) + { + // remove any non digit character from string + $clean_number = preg_replace('~\D~', '', $mobile); + error_log('cleaned ' . $clean_number); + + // does it fit our 09XXXXXXXXX pattern? + if (preg_match('/^09[0-9]{9}$/', $clean_number)) + { + // remove first '0' + $clean_number = substr($clean_number, 1); + + // prepend 63 + $clean_number = '63' . $clean_number; + + error_log("CONVERTED TO $clean_number"); + return $clean_number; + } + // does it fit our 63XXXXXXXXXX pattern? + else if (preg_match('/^63[0-9]{10}$/', $clean_number)) + { + // leave alone + return $clean_number; + } + // does it fit our 9XXXXXXXXX pattern? + else if (preg_match('/^9[0-9]{9}$/', $clean_number)) + { + // prepend 63 + $clean_number = '63' . $clean_number; + + error_log("CONVERT TO $clean_number"); + return $clean_number; + } + + return false; + } } diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 4fff73e0..2d510c36 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -449,6 +449,23 @@
+ +
+
+ + + +
+
+ + + +