resq/src/Command/MigrateCMBLegacyJobOrderCommand.php
2020-09-04 08:07:31 +00:00

560 lines
18 KiB
PHP

<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\CMBLegacyJobOrderRow;
use App\Entity\CMBLegacyJobOrder;
use App\Entity\VehicleManufacturer;
use App\Entity\Vehicle;
use App\Entity\BatteryManufacturer;
use App\Entity\BatteryModel;
use App\Entity\BatterySize;
use App\Entity\Battery;
use App\Entity\Customer;
use App\Entity\CustomerVehicle;
use App\Ramcar\CMBServiceType;
use App\Ramcar\JOStatus;
use App\Ramcar\FuelType;
use App\Ramcar\VehicleStatusCondition;
use DateTime;
class MigrateCMBLegacyJobOrderCommand extends Command
{
/*
id = 'entry_num'
trans_date = 'created_date'
case_number = 'case_number'
insurer = 'insurer'
plate_number = 'vehicle_number'
car_brand and car_make = split the 'car_model'
nature_of_call = nature_of_call
trans_type = 'service_needed'
address = 'location'
address = 'state'
driver = 'driver'
truck = 'truck'
workshop_arrival_time => 'workshop_arrival_time'
status = 'status'
cust_name = 'customer_name'
cust_mobile = 'customer_phone_number'
reference = 'reference'
odometer = 'odometer'
batt_model = 'batt_model'
batt_size = 'batt_size'
is_trade_in = 'batt_trade_in'
replaced_by = 'replaced_by'
remarks = 'remark'
satisfaction => 'satisfaction'
*/
protected $em;
protected $bmanu_hash;
protected $bmodel_hash;
protected $bsize_hash;
protected $batt_hash;
protected $vmanu_hash;
protected $vmake_hash;
protected $cv_hash;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
// load existing battery data
$this->loadBatteryManufacturers();
$this->loadBatteryModels();
$this->loadBatterySizes();
$this->loadBatteries();
// load existing vehicle data
$this->loadVehicleManufacturers();
$this->loadVehicleMakes();
// load existing customer vehicle data
$this->loadCustomerVehicles();
parent::__construct();
}
public function configure()
{
$this->setName('cmblegacyjoborderdata:migrate')
->setDescription('Retrieve database cmb legacy job orders and insert into job order.')
->setHelp('Creates job orders based on data from imported CSV.')
->addArgument('output_file', InputArgument::REQUIRED, 'Path to the output CSV file of the entries not added.');
}
public function execute(InputInterface $input, OutputInterface $output)
{
$csv_file = $input->getArgument('output_file');
// attempt to open file
try
{
$fh = fopen($csv_file, "w");
}
catch (Exception $e)
{
throw new Exception('The file "' . $csv_file . '" could be opened.');
}
// get all legacy job orders
$query = $this->em->createQuery('SELECT legacy_jo_row FROM App\Entity\CMBLegacyJobOrderRow legacy_jo_row');
$result = $query->iterate();
$invalid_entries = [];
$added_entries = 0;
$total_entries = 0;
$total_inv_entries = 0;
foreach ($result as $row)
{
$entry = $row[0];
$jo_entry = $entry->getData();
$total_entries++;
// get the entry information
$entry_num = $jo_entry['entry_num'];
$date_create = $jo_entry['created_date'];
$case_number = $jo_entry['case_number'];
$insurer = $jo_entry['insurer'];
$plate_number = $this->cleanPlateNumber($jo_entry['vehicle_number']);
$car_model = $this->normalizeName($jo_entry['car_model']);
$nature_of_call = $jo_entry['nature_of_call'];
$service_needed = $jo_entry['service_needed'];
$location = $jo_entry['location'];
$state = $jo_entry['state'];
$driver = $jo_entry['driver'];
$truck = $jo_entry['truck'];
$workshop_arrival_time = $jo_entry['workshop_arrival_time'];
$status = $jo_entry['status'];
$customer_name = $jo_entry['customer_name'];
$customer_mobile = $jo_entry['customer_phone_number'];
$reference = $jo_entry['reference'];
$odometer = $jo_entry['odometer'];
$batt_model = $this->normalizeName($jo_entry['batt_model']);
$batt_size = $this->normalizeName($jo_entry['batt_size']);
$batt_trade_in = $jo_entry['batt_trade_in'];
$replaced_by = $jo_entry['replaced_by'];
$remark = $jo_entry['remark'];
$satisfaction = $jo_entry['satisfaction'];
// check vehicle info if valid
$v_status = $this->processVehicleInfo($car_model);
if ($v_status != null)
{
//error_log($v_status . ' ' . $car_model);
$invalid_entries[] = $this->addInvalidEntry($entry_num, $date_create, $case_number, $insurer, $plate_number, $car_model,
$nature_of_call, $service_needed, $location, $state, $driver, $truck, $workshop_arrival_time,
$status, $customer_name, $customer_mobile, $reference, $odometer, $batt_model, $batt_size,
$batt_trade_in, $replaced_by, $remark, $satisfaction, $v_status);
$total_inv_entries++;
// move to next entry
continue;
}
// check battery info if valid
$batt_status = $this->processBatteryInfo($batt_model, $batt_size);
if ($batt_status != null)
{
//error_log($batt_status . ' ' . $batt_model . ' ' . $batt_size);
$invalid_entries[] = $this->addInvalidEntry($entry_num, $date_create, $case_number, $insurer, $plate_number, $car_model,
$nature_of_call, $service_needed, $location, $state, $driver, $truck, $workshop_arrival_time,
$status, $customer_name, $customer_mobile, $reference, $odometer, $batt_model, $batt_size,
$batt_trade_in, $replaced_by, $remark, $satisfaction, $batt_status);
$total_inv_entries++;
// move to next entry
continue;
}
// check if mobile phone number has letters or spaces or special characters
if (!(preg_match('/^\d+$/', $customer_mobile)))
{
// not a valid mobile number
//error_log('invalid number ' . $customer_mobile);
$invalid_entries[] = $this->addInvalidEntry($entry_num, $date_create, $case_number, $insurer, $plate_number, $car_model,
$nature_of_call, $service_needed, $location, $state, $driver, $truck, $workshop_arrival_time,
$status, $customer_name, $customer_mobile, $reference, $odometer, $batt_model, $batt_size,
$batt_trade_in, $replaced_by, $remark, $satisfaction, 'Invalid mobile number');
$total_inv_entries++;
// move to next entry
continue;
}
// create job order
$cmb_legacy_jo = new CMBLegacyJobOrder();
// date_create
$created_date = DateTime::createFromFormat("d-m-Y H:i", $date_create);
$cmb_legacy_jo->setTransDate($created_date);
// parse vehicle info
// get vehicle from hash
$v_array = explode(' ', $car_model);
// manufacturer
$v_manufacturer = trim($v_array[0]);
// get model
$model_info = '';
$v_model = '';
for ($i = 1; $i < count($v_array); $i++)
{
$model_info = $model_info . ' ' . trim($v_array[$i]);
}
$v_model = trim($model_info);
// delivery address = location + state
$delivery_address = $location . ', ' . $state;
// check if trade in
$trade_in = false;
if (strtolower($batt_trade_in) == 'yes')
$trade_in = true;
$cmb_legacy_jo->setCaseNumber($case_number)
->setInsurer($insurer)
->setNatureOfCall($nature_of_call)
->setTransType($service_needed)
->setCarBrand(strtoupper($v_manufacturer))
->setCarMake(strtoupper($v_model))
->setCustName($customer_name)
->setCustMobile($customer_mobile)
->setAddress($delivery_address)
->setDriver($driver)
->setTruck($truck)
->setWorkshopArrivalTime($workshop_arrival_time)
->setPlateNumber($plate_number)
->setStatus($status)
->setReference($reference)
->setOdometer($odometer)
->setBatteryModel(strtoupper($batt_model))
->setBatterySize(strtoupper($batt_size))
->setIsTradeIn($trade_in)
->setReplacedBy($replaced_by)
->setSatisfaction($satisfaction);
// plate number == vehicle_number. Use as key to cv_hash
// check if plate number has been added
if (!isset($this->cv_hash[$plate_number]))
{
$cust = $this->addCustomer($customer_name, $customer_mobile);
$cv = $this->addCustomerVehicle($plate_number, $car_model, $cust);
}
$this->em->persist($cmb_legacy_jo);
$this->em->detach($row[0]);
$added_entries++;
}
$this->em->flush();
$this->em->clear();
// output the entries that were not added
if (count($invalid_entries) > 0)
{
fputcsv($fh, [
'Entry Num',
'Created Date',
'Case Number',
'Insurer',
'Vehicle Number',
'Car Model',
'Nature of Call',
'Service Needed',
'Location',
'State',
'Driver',
'Truck',
'Workshop Arrival Time',
'Status',
'Customer Name',
'Customer Phone Number',
'Reference',
'Odometer',
'Batt Model',
'Batt Size',
'Batt Trade In',
'Replaced By',
'Remark',
'Satisfaction',
'Reason',
]);
foreach($invalid_entries as $row)
{
fputcsv($fh, $row);
}
}
fclose($fh);
error_log('Processed ' . $total_entries . ' entries.');
error_log('Added ' . $added_entries . ' entries.');
error_log('Did not add ' . $total_inv_entries . ' entries.');
return 0;
}
protected function processVehicleInfo($car_model)
{
// vehicle manufacturer is the first entry
// vehicle model is the 2nd entry + whatever follows
$v_array = explode(' ', $car_model);
// manufacturer
$v_manufacturer = trim($v_array[0]);
// get model
$model_info = '';
$v_model = '';
for ($i = 1; $i < count($v_array); $i++)
{
$model_info = $model_info . ' ' . trim($v_array[$i]);
}
$v_model = trim($model_info);
//error_log($v_manufacturer . ' ' . $v_model);
// check if manufacturer is in hash
if (!isset($this->vmanu_hash[$v_manufacturer]))
{
//error_log($v_manufacturer . ' invalid.');
return 'Vehicle manufacturer not in system.';
}
// check if manufacturer and make is in hash
if (!isset($this->vmake_hash[$v_manufacturer][$v_model]))
{
//error_log($v_model . ' invalid.');
return 'Vehicle model not in system.';
}
// car model info valid
return null;
}
protected function processBatteryInfo($batt_model, $batt_size)
{
// check if battery model is in hash
if (!isset($this->bmodel_hash[$batt_model]))
return 'Battery model not in system.';
// check if battery size is in hash
if (!isset($this->bsize_hash[$batt_size]))
return 'Battery size not in system.';
// battery info valid
return null;
}
protected function addInvalidEntry($entry_num, $date_create, $case_number, $insurer, $plate_number, $car_model,
$nature_of_call, $service_needed, $location, $state, $driver, $truck, $workshop_arrival_time,
$status, $customer_name, $customer_mobile, $reference, $odometer, $batt_model, $batt_size,
$batt_trade_in, $replaced_by, $remark, $satisfaction, $v_status)
{
$inv_entry = [
'number' => $entry_num,
'created_date' => $date_create,
'case_number' => $case_number,
'insurer' => $insurer,
'vehicle_number' => $plate_number,
'car_model' => $car_model,
'nature_of_call' => $nature_of_call,
'service_needed' => $service_needed,
'location' => $location,
'state' => $state,
'driver' => $driver,
'truck' => $truck,
'workshop_arrival_time' => $workshop_arrival_time,
'status' => $status,
'customer_name' => $customer_name,
'customer_phone_number' => $customer_mobile,
'reference' => $reference,
'odometer' => $odometer,
'batt_model' => $batt_model,
'batt_size' => $batt_size,
'batt_trade_in' => $batt_trade_in,
'replaced_by' => $replaced_by,
'remark' => $remark,
'satisfaction' => $satisfaction,
'reason' => $v_status,
];
return $inv_entry;
}
protected function addCustomer($name, $mobile)
{
$new_cust = new Customer();
$new_cust->setFirstName($name)
->setLastName('')
->setPhoneMobile($mobile);
$this->em->persist($new_cust);
return $new_cust;
}
protected function addCustomerVehicle($plate_num, $car_model, $customer)
{
$new_cv = new CustomerVehicle();
// get vehicle from hash
$v_array = explode(' ', $car_model);
// manufacturer
$v_manufacturer = trim($v_array[0]);
// get model
$model_info = '';
$v_model = '';
for ($i = 1; $i < count($v_array); $i++)
{
$model_info = $model_info . ' ' . trim($v_array[$i]);
}
$v_model = trim($model_info);
$vehicle = $this->vmake_hash[$v_manufacturer][$v_model];
$new_cv->setCustomer($customer)
->setPlateNumber($plate_num)
->setStatusCondition(VehicleStatusCondition::BRAND_NEW)
->setModelYear('')
->setColor('')
->setFuelType(FuelType::GAS)
->setHasMotoliteBattery(true)
->setVehicle($vehicle);
$this->em->persist($new_cv);
// add customer vehicle to cv_hash
$this->cv_hash[$plate_num] = $new_cv;
return $new_cv;
}
protected function loadBatteryManufacturers()
{
$this->bmanu_hash = [];
$batt_manufacturers = $this->em->getRepository(BatteryManufacturer::class)->findAll();
foreach ($batt_manufacturers as $batt_manu)
{
$name = $this->normalizeName($batt_manu->getName());
$this->bmanu_hash[$name] = $batt_manu;
}
}
protected function loadBatteryModels()
{
$this->bmodel_hash = [];
$batt_models = $this->em->getRepository(BatteryModel::class)->findAll();
foreach ($batt_models as $batt_model)
{
$name = $this->normalizeName($batt_model->getName());
$this->bmodel_hash[$name] = $batt_model;
}
}
protected function loadBatterySizes()
{
$this->bsize_hash = [];
$batt_sizes = $this->em->getRepository(BatterySize::class)->findAll();
foreach ($batt_sizes as $batt_size)
{
$name = $this->normalizeName($batt_size->getName());
$this->bsize_hash[$name] = $batt_size;
}
}
protected function loadBatteries()
{
$this->batt_hash = [];
$batts = $this->em->getRepository(Battery::class)->findAll();
foreach ($batts as $batt)
{
$brand = $this->normalizeName($batt->getManufacturer()->getName());
$model = $this->normalizeName($batt->getModel()->getName());
$size = $this->normalizeName($batt->getSize()->getName());
$this->batt_hash[$brand][$model][$size] = $batt;
}
}
protected function loadVehicleManufacturers()
{
$this->vmanu_hash = [];
$vmanus = $this->em->getRepository(VehicleManufacturer::class)->findAll();
foreach ($vmanus as $vmanu)
{
$name = $this->normalizeName($vmanu->getName());
$this->vmanu_hash[$name] = $vmanu;
}
}
protected function loadVehicleMakes()
{
$this->vmake_hash = [];
$vmakes = $this->em->getRepository(Vehicle::class)->findAll();
foreach ($vmakes as $vmake)
{
$manufacturer = $this->normalizeName($vmake->getManufacturer()->getName());
$make = $this->normalizeName($vmake->getMake());
$this->vmake_hash[$manufacturer][$make] = $vmake;
}
}
protected function loadCustomerVehicles()
{
$this->cv_hash = [];
$cvs = $this->em->getRepository(CustomerVehicle::class)->findAll();
foreach ($cvs as $cv)
{
$plate_number = $this->cleanPlateNumber($cv->getPlateNumber());
$this->cv_hash[$plate_number] = $cv;
}
}
protected function normalizeName($name)
{
$normalized_key = trim(strtolower($name));
return $normalized_key;
}
protected function cleanPlateNumber($plate_number)
{
// remove spaces and make upper case
$clean_plate_number = strtoupper(str_replace(' ' , '', $plate_number));
return $clean_plate_number;
}
}