From 6cc9cddf1f9682e6212bbf0938bbe823eb73e3af Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 6 Apr 2022 11:01:27 +0000 Subject: [PATCH 1/2] Add command to import vehicle battery compatibility for Yokohama. #655 --- ...hamaVehicleBatteryCompatibilityCommand.php | 425 ++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php diff --git a/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php new file mode 100644 index 00000000..ba45414d --- /dev/null +++ b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php @@ -0,0 +1,425 @@ +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->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 . "..."); + + // 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++; + } + // print_r($b_models); + // print_r($batteries); + // save to db + + 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 + 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 + $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); + + error_log(count($output_info)); + + 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]; + + // 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 = []; + // 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; + } + + if (!isset($this->v_index[$brand][$make . '|' . intval($m_year_from) . '|' . intval($m_year_to)])) + { + $message = 'Invalid vehicle'; + $output_info = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $output_info; + } + + // 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]); + $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, + $alt_prem_mf, + $alt_prem_lm, + $alt_super_prem_mf, + $alt_supreme_mf, + $alt_platinum_mf, + $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) + { + fputcsv($fh, $row); + } + + fclose($fh); + } + + protected function populateVehicleIndex() + { + $vs = $this->em->getRepository(Vehicle::class)->findAll(); + + $this->v_index = []; + $this->vmfg_index = []; + foreach ($vs as $v) + { + $mfg_name = $this->normalizeName($v->getManufacturer()->getName()); + $this->vmfg_index[$mfg_name] = $v->getManufacturer(); + if (!isset($this->v_index[$mfg_name])) + $this->v_index[$mfg_name] = []; + + error_log('vehicle keys ' . $mfg_name . ' ' . $this->normalizeName($v->getMake()) . '|' . $v->getModelYearFrom() . '|' . $v->getModelYearTo()); + + $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(); + + error_log($bsize); + + // check if size has / + $bsizes = []; + $pos = stripos($bsize, '/'); + if ($pos == false) + { + // no '/' in size + $bsizes[] = $this->normalizeName($bsize); + } + else + { + // if yes, we need to split it. + $sizes = explode('/', $bsize); + foreach ($sizes as $size) + { + $bsizes[] = $this->normalizeName($size); + } + } + + foreach ($bsizes as $battery_size) + { + error_log('Adding ' . $battery_size . ' to key'); + $key = $this->getBatteryKey($battery_size, $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; + } + +} From bc1c6110e82e140728e109ba9cf4047a15ec5e94 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 8 Apr 2022 09:06:55 +0000 Subject: [PATCH 2/2] Fix issues found during testing. #655 --- ...hamaVehicleBatteryCompatibilityCommand.php | 67 +++++++------------ 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php index ba45414d..50296cad 100644 --- a/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php +++ b/src/Command/ImportYokohamaVehicleBatteryCompatibilityCommand.php @@ -26,11 +26,11 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command const F_V_MODEL_YEAR = 2; const F_B_SIZE = 7; const F_B_MODEL = 8; - const F_B_ALT_PREM_MF = 10; - const F_B_ALT_PREM_LM = 11; - const F_B_ALT_SUPER_PREM_MF = 12; - const F_B_ALT_SUPREME_MF = 13; - const F_B_ALT_PLATINUM_MF = 14; + //const F_B_ALT_PREM_MF = 10; + //const F_B_ALT_PREM_LM = 11; + //const F_B_ALT_SUPER_PREM_MF = 12; + //const F_B_ALT_SUPREME_MF = 13; + //const F_B_ALT_PLATINUM_MF = 14; // the rest of the fields are irrelevant protected $em; @@ -92,7 +92,9 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command { $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]); @@ -101,6 +103,7 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $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, @@ -108,10 +111,8 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $row_num++; } - // print_r($b_models); - // print_r($batteries); - // save to db + // save to db the valid ones foreach ($vbrands as $brand_name => $vbrand) { // vehicles @@ -140,6 +141,8 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $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'])) @@ -150,12 +153,14 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $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); @@ -177,8 +182,6 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command // go into the vbrands array $output_info = $this->validateManufacturerVehicle($fields, $brand, $make, $model, $bsize, $bmodel); - error_log(count($output_info)); - if (!empty($output_info)) return $output_info; @@ -202,8 +205,10 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $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 @@ -249,6 +254,7 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $vbrands[$brand]['vehicles'][$row_num]['alt_battery_platinum_mf'] = $this->batt_index[$alt_batt_key]; } } + */ } protected function validateManufacturerVehicle($fields, $brand, $make, $model, $bsize, $bmodel) @@ -297,11 +303,14 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $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, @@ -309,11 +318,6 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command $model_year, $bsize, $bmodel, - $alt_prem_mf, - $alt_prem_lm, - $alt_super_prem_mf, - $alt_supreme_mf, - $alt_platinum_mf, $status, $reason ]; @@ -343,7 +347,8 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command foreach($entries as $row) { - fputcsv($fh, $row); + if ($row != null) + fputcsv($fh, $row); } fclose($fh); @@ -362,8 +367,6 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command if (!isset($this->v_index[$mfg_name])) $this->v_index[$mfg_name] = []; - error_log('vehicle keys ' . $mfg_name . ' ' . $this->normalizeName($v->getMake()) . '|' . $v->getModelYearFrom() . '|' . $v->getModelYearTo()); - $this->v_index[$mfg_name][$this->normalizeName($v->getMake()) . '|' . $v->getModelYearFrom() . '|' . $v->getModelYearTo()] = $v; } } @@ -378,33 +381,9 @@ class ImportYokohamaVehicleBatteryCompatibilityCommand extends Command // get the battery size $bsize = $b->getSize()->getName(); - error_log($bsize); + $key = $this->getBatteryKey($bsize, $b->getModel()->getName()); - // check if size has / - $bsizes = []; - $pos = stripos($bsize, '/'); - if ($pos == false) - { - // no '/' in size - $bsizes[] = $this->normalizeName($bsize); - } - else - { - // if yes, we need to split it. - $sizes = explode('/', $bsize); - foreach ($sizes as $size) - { - $bsizes[] = $this->normalizeName($size); - } - } - - foreach ($bsizes as $battery_size) - { - error_log('Adding ' . $battery_size . ' to key'); - $key = $this->getBatteryKey($battery_size, $b->getModel()->getName()); - - $this->batt_index[$key] = $b; - } + $this->batt_index[$key] = $b; } }