From ecff27524a52acde72ee924550168aa398eea4ed Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 5 May 2022 11:27:35 +0000 Subject: [PATCH] Create test command for bulk warranty upload optimization. #660 --- src/Command/TestWarrantyUploadCommand.php | 413 ++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 src/Command/TestWarrantyUploadCommand.php diff --git a/src/Command/TestWarrantyUploadCommand.php b/src/Command/TestWarrantyUploadCommand.php new file mode 100644 index 00000000..e8b976dc --- /dev/null +++ b/src/Command/TestWarrantyUploadCommand.php @@ -0,0 +1,413 @@ +em = $em; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('testwarranty:upload') + ->setDescription('Test bulk warranty upload.') + ->setHelp('Test bulk warranty upload.') + ->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'); + + // attempt to open file + try + { + $fh = fopen($csv_file, "r"); + } + catch (Exception $e) + { + throw new Exception('The file "' . $csv_file . '" could be read.'); + } + + $output_info = []; + + // loop through rows + // ignore first row since that's header data + $row_num = 1; + + $sql_values = ''; + while (($fields = fgetcsv($fh)) !== false) + { + // process row + $output_info[] = $this->processRow($fields, $sql_values); + + $row_num++; + } + + // check if we have values to insert + if (strlen($sql_values) > 0) + { + $sql_statement = 'INSERT INTO `warranty` (bty_model_id,bty_size_id,serial,warranty_class,plate_number,status,date_create,date_purchase,date_expire,sap_code,first_name,last_name,mobile_number,flag_activated,create_source,vehicle_id,customer_id, create_source) VALUES ' . $sql_values . ';' . "\n"; + $conn = $this->em->getConnection(); + $stmt = $conn->prepare($sql_statement); + $stmt->execute(); + } + + // write to output file + $this->outputWarrantyInfo($output_file, $output_info); + + fclose($fh); + + return 0; + } + + protected function processRow($fields, &$sql_values) + { + // hash the battery table using sap_code as index + $this->populateBatteryIndex(); + + $output_info = []; + + // get necessary fields + $fname = trim($fields[self::F_FNAME]); + $lname = trim($fields[self::F_LNAME]); + $mobile = trim($fields[self::F_MOBILE]); + $serial = trim($fields[self::F_SERIAL]); + $date_purchase = trim($fields[self::F_DATE_PURCHASE]); + $sap_code = trim($fields[self::F_BATT_ID]); + $plate_number = $this->cleanPlateNumber($fields[self::F_PLATE_NUMBER]); + + // validate the necessary fields + $output_info = $this->validateFields($fields); + if (!empty($output_info)) + return $output_info; + + // see if we can get customer id and vehicle id, given the plate number. + // this is not required so if we can't find customer and/or vehicle, + // we still create the warranty + $conn = $this->em->getConnection(); + + // NOTE: what happens if there's more than one result? + // for now, get the first one + $sql = 'SELECT c.id AS c_id, v.id FROM customer_vehicle cv, customer c, vehicle v + WHERE cv.customer_id = c.id AND cv.vehicle_id = v.id AND cv.plate_number = :plate_number LIMIT 1'; + $stmt = $conn->prepare($sql); + $stmt->execute(['plate_number' => $plate_number]); + + $cv_results = $stmt->fetch(); + + $cust_id = null; + $vehicle_id = null; + if (!empty($cv_results)) + { + $cust_id = $cv_results[0]; + $vehicle_id = $cv_results[1]; + } + + // get battery info from hash (battery model id, battery size id, warranty periods (needed for expiration date) + $batt_info = $this->batt_hash[$sap_code]; + $b_id = $batt_info['id']; + $model_id = $batt_info['model_id']; + $size_id = $batt_info['size_id']; + $warr_private = $batt_info['warr_private']; + $warr_commercial = $batt_info['warr_commercial']; + $warr_tnv = $batt_info['warr_tnv']; + + // format purchase date to DateTime and then change the format to Y-m-d + $purchase_date = DateTime::createFromFormat('m/d/y', $date_purchase); + $p_date = $purchase_date->format('Y-m-d'); + + // need to manually create the created date + $date_create = date('Y-m-d H:i:s'); + + // compute expiration date + // TODO: might need checking for what kind of warranty for the warranty period + // by default, we use private + $date_expire = $this->computeDateExpire($p_date, $warr_private); + + $first_name = addslashes($fname); + $last_name = addslashes($lname); + $mobile_number = addslashes($mobile); + + // populate the values string for the values to be inserted into warranty + $value_string = '(' . $model_id . ',' . $size_id . ',\'' . $serial . ',\'' . $warranty_class . '\',\'' + . $plate_number . '\',\'' . WarrantyStatus::ACTIVE . '\',\'' . $date_create . '\',\'' . $p_date + . '\',\'' . $date_expire . ',\'' . $sap_code . ',\'' . $first_name . '\',\'' . $last_name . '\',\'' . $mobile_number . '\',' . 1 . ',' . $vehicle_id . ',' . $cust_id . ',' . WarrantySource::BULK_UPLOAD . '\')'; + + $sql_values = $sql_values . ',' . $value_string; + + // TODO: remove this later, this is for debugging + echo $sql_values; + + return $output_info; + } + + protected function validateFields($fields) + { + $errors = []; + + $serial = trim($fields[self::F_SERIAL]); + $date_purchase = trim($fields[self::F_DATE_PURCHASE]); + $sap_code = trim($fields[self::F_BATT_ID]); + $plate_number = trim($fields[self::F_PLATE_NUMBER]); + + // clean the plate number + $clean_plate = $this->cleanPlateNumber($plate_number); + + // validate the plate number + // (1) plate number should not be empty + if (empty($clean_plate)) + { + $message = 'No plate number.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + // validate date purchase + // (1) date purchase should not be empty + // (2) date purchase should be of format: m/d/y + if (empty($date_purchase)) + { + $message = 'No date purchase.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + + $purchase_date = DateTime::createFromFormat('m/d/y', $date_purchase); + if ($purchase_date === false) + { + $message = 'Invalid date format. Date format should be: mm/dd/yy'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + // validate serial + // (1) should not be empty + if (empty($serial)) + { + $message = 'No battery serial number.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + // validate battery + // (1) should not be empty + // (2) should find battery using sap_code. + if ($empty($sap_code)) + { + $message = 'No battery ID.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + + if (!(isset($this->batt_hash[$sap_code]))) + { + $message = 'Battery not found.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + + // check if warranty exists using serial + plate number + $conn = $this->em->getConnection(); + + // find warranties + $sql = 'SELECT w.id FROM warranty w WHERE w.serial = :serial AND w.plate_number = :plate_number'; + $stmt = $conn->prepare($sql); + $stmt->execute([ + 'serial' => $serial, + 'plate_number' => $plate_number, + ]); + + $warr_results = $stmt->fetchAll(); + + if (!empty($warr_results)) + { + $message = 'Warranty already exists for serial and plate number.'; + $errors = $this->setOutputInfo($fields, 'NOT ADDED', $message); + return $errors; + } + + return $errors; + } + + protected function computeDateExpire($date_create, $warranty_period) + { + $expire_date = clone $date_create; + $expire_date->add(new DateInterval('P'.$warranty_period.'M')); + return $expire_date; + } + + protected function setOutputInfo($fields, $status, $message) + { + $encoder = trim($fields[self::F_ENCODER]); + $date_encoded = trim($fields[self::F_DATE_ENCODED]); + $fname = trim($fields[self::F_FNAME]); + $lname = trim($fields[self::F_LNAME]); + $email = trim($fields[self::F_EMAIL]); + $address = trim($fields[self::F_ADDRESS]); + $mobile = trim($fields[self::F_MOBILE]); + $telephone = trim($fields[self::F_TELEPHONE]); + $vmake = trim($fields[self::F_VMAKE]); + $vmodel = trim($fields[self::F_VMODEL]); + $year = trim($fields[self::F_MYEAR]); + $serial = trim($fields[self::F_SERIAL]); + $invoice_number = trim($fields[self::F_INVOICE_NUM]); + $date_purchase = trim($fields[self::F_DATE_PURCHASE]); + $dist_name = trim($fields[self::F_DIST_NAME]); + $dist_address = trim($fields[self::F_DIST_ADDRESS]); + $app_type_id = trim($fields[self::F_APP_TYPE_ID]); + $sap_code = trim($fields[self::F_BATT_ID]); + $plate_number = trim($fields[self::F_PLATE_NUMBER]); + $owner_type = trim($fields[self::F_OWNER_TYPE]); + + return [ + $encoder, + $date_encoded, + $fname, + $lname, + $email, + $address, + $mobile, + $telephone, + $vmake, + $vmodel, + $year, + $plate_number, + $serial, + $invoice_number, + $date_purchase, + $dist_name, + $dist_address, + $app_type_id, + $sap_code, + $owner_type, + $status, + $reason, + ]; + } + + protected function outputWarrantyInfo($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, [ + 'Encoded By', + 'Date of Encoded', + 'Owner First Name', + 'Owner Last Name', + 'Owner Email', + 'Owner Address', + 'Owner Mobile', + 'Owner Telephone', + 'Vehicle Make', + 'Vehicle Model', + 'Vehicle Year', + 'Vehicle Plate No.', + 'Battery Serial No.', + 'Battery Sales Invoice No.', + 'Battery Date of Purchase', + 'Distributor Name', + 'Distributor Address', + 'Application Type ID', + 'Battery ID', + 'Ownership Type', + 'Status', + 'Reason', + ]); + + foreach($entries as $row) + { + if ($row != null) + fputcsv($fh, $row); + } + + fclose($fh); + } + + + protected function populateBatteryIndex() + { + $conn = $this->em->getConnection(); + + // get all the batteries + $sql = 'SELECT b.id, b.model_id, b.size_id, b.sap_code, b.warr_private, b.warr_commercial, b.warr_tnv + FROM battery b'; + $stmt = $conn->prepare($sql); + $stmt->execute(); + + // go through the rows + while ($row = $stmt->fetchAll()) + { + // breaking this down for clarity + $battery_id = $row[0]; + $model_id = $row[1]; + $size_id = $row[2]; + $sap_code = $row[3]; + $warr_private = $row[4]; + $warr_commercial = $row[5]; + $warr_tnv = $row[6]; + + $this->batt_hash[$sap_code] = [ + 'id' => $battery_id, + 'model_id' => $model_id, + 'size_id' => $size_id, + 'warr_private' => $warr_private, + 'warr_commercial' => $warr_commercial, + 'warr_tnv' => $warr_tnv, + ]; + } + } + + protected function cleanPlateNumber($plate) + { + return strtoupper(str_replace(' ', '', $plate)); + } + +}