529 lines
16 KiB
PHP
529 lines
16 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\JobOrder;
|
|
use App\Entity\JOEvent;
|
|
use App\Entity\User;
|
|
use App\Entity\Warranty;
|
|
use App\Entity\SAPBattery;
|
|
|
|
use App\Ramcar\JOStatus;
|
|
use App\Ramcar\JOEventType;
|
|
use App\Ramcar\DeliveryStatus;
|
|
use App\Ramcar\WarrantyClass;
|
|
use App\Ramcar\ServiceType;
|
|
use App\Ramcar\WarrantySource;
|
|
use App\Ramcar\WarrantyStatus;
|
|
|
|
use DateTime;
|
|
use DateInterval;
|
|
|
|
class FulfillOpenJobOrderCommand extends Command
|
|
{
|
|
const DEFAULT_SAP_WARRANTY = 12;
|
|
const JO_BATCH_CTR = 200;
|
|
|
|
protected $em;
|
|
protected $batt_hash;
|
|
protected $sap_batt_hash;
|
|
|
|
public function __construct(EntityManagerInterface $em)
|
|
{
|
|
$this->em = $em;
|
|
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function configure()
|
|
{
|
|
$this->setName('joborder:fulfillopenjosnosms')
|
|
->setDescription('Fulfill open job orders without sending an SMS message.')
|
|
->setHelp('Mark open job orders as fulfilled and should not send a SMS message. Date format: YYYY-MM-DD')
|
|
->addArgument('end_date', InputArgument::REQUIRED, 'End date. Format: YYYY-MM-DD');
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
// load batteries into hash
|
|
$this->populateBatteryIndex();
|
|
|
|
// load sap batteries into hash
|
|
$this->populateSAPBatteryIndex();
|
|
|
|
// get the input date
|
|
$str_date_end = $input->getArgument('end_date');
|
|
|
|
// append the 23:59:59 to end date
|
|
$str_date_end = $str_date_end . ' ' . '23:59:59';
|
|
|
|
// starting time to count is date schedule
|
|
$date_end = new DateTime($str_date_end);
|
|
|
|
// get current date and convert to string
|
|
$current_date = new DateTime();
|
|
$str_current_date = $current_date->format('Y-m-d H:i:s');
|
|
|
|
// find all open job orders starting from input date and before
|
|
// need to get customer id, customer vehicle id, service type, warranty class
|
|
$conn = $this->em->getConnection();
|
|
|
|
$jo_sql = 'SELECT jo.id AS jo_id, c.id AS c_id, cv.id AS cv_id,
|
|
jo.service_type, jo.warranty_class, jo.rider_id, jo.date_schedule
|
|
FROM job_order jo, customer c, customer_vehicle cv
|
|
WHERE jo.customer_id = c.id AND jo.cvehicle_id = cv.id
|
|
AND jo.status IN (\'pending\', \'rider_assign\', \'assigned\', \'in_transit\', \'in_progress\')
|
|
AND jo.date_schedule <= :date_end';
|
|
$stmt = $conn->prepare($jo_sql);
|
|
$stmt->execute([
|
|
'date_end' => $str_date_end]);
|
|
|
|
$jo_results = $stmt->fetchAll();
|
|
|
|
error_log('JOs found ' . count($jo_results));
|
|
|
|
$total_jos = count($jo_results);
|
|
|
|
$jo_ctr = 0;
|
|
$update_jo_ctr = 0;
|
|
$update_wheres = [];
|
|
$w_data = [];
|
|
$jo_evt_data = [];
|
|
|
|
foreach ($jo_results as $jo_row)
|
|
{
|
|
// get the data first
|
|
$jo_id = $jo_row['jo_id'];
|
|
$cust_id = $jo_row['c_id'];
|
|
$cv_id = $jo_row['cv_id'];
|
|
$service_type = $jo_row['service_type'];
|
|
$warranty_class = $jo_row['warranty_class'];
|
|
$rider_id = $jo_row['rider_id'];
|
|
$str_date_schedule = $jo_row['date_schedule'];
|
|
|
|
$jo_ctr++;
|
|
|
|
// fulfill JO
|
|
$this->fulfillJO($conn, $jo_id, $update_jo_ctr, $update_wheres, $jo_ctr, $total_jos);
|
|
|
|
// create JO event
|
|
$jo_evt_data[] = $this->createJOEvent($conn, $jo_id, $str_current_date, $rider_id);
|
|
|
|
// error_log($jo_ctr . ' Processing JO ' . $jo_id);
|
|
|
|
// check service type
|
|
if ($service_type == ServiceType::BATTERY_REPLACEMENT_NEW)
|
|
{
|
|
// new battery so we need to create warranty so we need to get battery id from invoice
|
|
$batt_id = $this->getBatteryInformation($conn, $jo_id);
|
|
|
|
if (($batt_id != null) && (isset($this->batt_hash[$batt_id])))
|
|
$w_data[] = $this->createWarrantyForJO($conn, $current_date, $str_date_schedule, $cust_id, $cv_id, $warranty_class, $batt_id);
|
|
}
|
|
}
|
|
|
|
// load data file for jo event
|
|
$this->createLoadDataFileForJOEvent($jo_evt_data);
|
|
|
|
// load data file for warranty
|
|
$this->createLoadDataFileForWarranty($w_data);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
protected function fulfillJO($conn, $jo_id, &$update_jo_ctr, &$update_wheres, $jo_ctr, $total_jos)
|
|
{
|
|
$update_wheres[] = 'id = ' . $jo_id;
|
|
|
|
// update db when we reach max # of JOs or when we reach total number of jos
|
|
if (($update_jo_ctr == self::JO_BATCH_CTR) ||
|
|
($jo_ctr == $total_jos))
|
|
{
|
|
error_log('Processing ' . $update_jo_ctr . ' job orders...');
|
|
|
|
$update_where_string = implode(' OR ' , $update_wheres);
|
|
|
|
// update job order
|
|
$fulfill_jo_sql = 'UPDATE job_order SET status = :fulfilled, delivery_status = :del_fulfilled WHERE ' . $update_where_string;
|
|
|
|
// error_log($fulfill_jo_sql);
|
|
|
|
$fulfill_jo_stmt = $conn->prepare($fulfill_jo_sql);
|
|
$fulfill_jo_stmt->execute([
|
|
'fulfilled' => JOStatus::FULFILLED,
|
|
'del_fulfilled' => DeliveryStatus::FULFILLED,
|
|
]);
|
|
|
|
// reset the wheres string
|
|
$update_wheres = [];
|
|
|
|
// reset the update jo counter
|
|
$update_jo_ctr = 0;
|
|
}
|
|
else
|
|
$update_jo_ctr++;
|
|
}
|
|
|
|
protected function createJOEvent($conn, $jo_id, $str_current_date, $rider_id)
|
|
{
|
|
// create jo event
|
|
// set user to admin that has id of 1
|
|
$user_id = 1;
|
|
|
|
$r_id = '\N';
|
|
// check if rider is null
|
|
if ($rider_id != NULL)
|
|
$r_id = $rider_id;
|
|
|
|
// create array for the jo event
|
|
$data = [
|
|
$user_id,
|
|
$jo_id,
|
|
$str_current_date,
|
|
$str_current_date,
|
|
JOEventType::FULFILL,
|
|
$r_id,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
protected function getBatteryInformation($conn, $jo_id)
|
|
{
|
|
// break this down into two sql calls
|
|
// get the invoice for job order
|
|
$i_sql = 'SELECT i.id FROM invoice i
|
|
WHERE i.job_order_id = :jo_id';
|
|
$i_stmt = $conn->prepare($i_sql);
|
|
$i_stmt->execute([
|
|
'jo_id' => $jo_id,
|
|
]);
|
|
|
|
$i_result = $i_stmt->fetch();
|
|
|
|
// check if invoice exists
|
|
if (empty($i_result))
|
|
return null;
|
|
|
|
$invoice_id = $i_result['id'];
|
|
|
|
// get the battery id from invoice item
|
|
$ii_sql = 'SELECT ii.battery_id FROM invoice_item ii
|
|
WHERE ii.invoice_id = :invoice_id
|
|
AND ii.battery_id IS NOT NULL';
|
|
$ii_stmt = $conn->prepare($ii_sql);
|
|
$ii_stmt->execute([
|
|
'invoice_id' => $invoice_id,
|
|
]);
|
|
|
|
$ii_result = $ii_stmt->fetch();
|
|
|
|
// checking for result
|
|
if (empty($ii_result))
|
|
return null;
|
|
|
|
$batt_id = $ii_result['battery_id'];
|
|
|
|
return $batt_id;
|
|
}
|
|
|
|
protected function createWarrantyForJO($conn, $current_date, $str_date_schedule, $cust_id, $cv_id, $warranty_class, $batt_id)
|
|
{
|
|
// convert current date to string since we use this for date_create
|
|
$str_current_date = $current_date->format('Y-m-d H:i:s');
|
|
|
|
// get the warranty period based on warranty class from battery hash
|
|
$warranty_period = $this->getWarrantyPeriod($batt_id, $warranty_class);
|
|
|
|
// compute date expiry.
|
|
// convert to DateTime date schedule
|
|
$date_schedule = DateTime::createFromFormat('Y-m-d H:i:s', $str_date_schedule);
|
|
$date_expire = $this->computeDateExpire($date_schedule, $warranty_period);
|
|
|
|
// convert to string the expiry date
|
|
$str_date_expire = $date_expire->format('Y-m-d');
|
|
|
|
// convert date schedule to just date
|
|
$str_date_purchase = $date_schedule->format('Y-m-d');
|
|
|
|
// check if date_expire is after or equal to the current date
|
|
// if so, set warranty status to active
|
|
$warranty_status = WarrantyStatus::EXPIRED;
|
|
if ($date_expire >= $current_date)
|
|
$warranty_status = WarrantyStatus::ACTIVE;
|
|
|
|
// get customer
|
|
$cust_info = $this->getCustomerInfo($conn, $cust_id);
|
|
|
|
// get customer vehicle
|
|
$cv_info = $this->getCustomerVehicleInfo($conn, $cv_id);
|
|
|
|
// customer info
|
|
$first_name = addslashes($cust_info['first_name']);
|
|
$last_name = addslashes($cust_info['last_name']);
|
|
$mobile = addslashes($cust_info['mobile']);
|
|
|
|
// customer vehicle info
|
|
$plate_number = $cv_info['plate_number'];
|
|
$vehicle_id = $cv_info['vehicle_id'];
|
|
|
|
// battery info
|
|
$model_id = $this->batt_hash[$batt_id]['model_id'];
|
|
$size_id = $this->batt_hash[$batt_id]['size_id'];
|
|
// need to confirm that sap_code exists in sap_battery
|
|
if (isset($this->sap_batt_hash['sap_code']))
|
|
$sap_code = $this->batt_hash[$batt_id]['sap_code'];
|
|
else
|
|
$sap_code = '\N';
|
|
|
|
// set flag_activated to false since that's the default in Warranty's constructor
|
|
$flag_activated = false;
|
|
|
|
// create array for the infile
|
|
$warranty_data = [
|
|
$model_id,
|
|
$size_id,
|
|
$sap_code,
|
|
$warranty_class,
|
|
$plate_number,
|
|
$warranty_status,
|
|
$str_current_date,
|
|
$str_date_purchase,
|
|
$str_date_expire,
|
|
$first_name,
|
|
$last_name,
|
|
$mobile,
|
|
$flag_activated,
|
|
$vehicle_id,
|
|
$cust_id,
|
|
WarrantySource::ADMIN_PANEL,
|
|
];
|
|
|
|
return $warranty_data;
|
|
}
|
|
|
|
protected function createLoadDataFileForWarranty($warranty_data)
|
|
{
|
|
// cache directory
|
|
$cache_dir = __DIR__ . '/../../var/cache';
|
|
|
|
$file = $cache_dir . '/warranty_data.tab';
|
|
error_log('opening file for warranty - ' . $file);
|
|
|
|
$fp = fopen($file, 'w');
|
|
if ($fp === false)
|
|
{
|
|
error_log('could not open file for load data infile - ' . $file);
|
|
}
|
|
else
|
|
{
|
|
foreach ($warranty_data as $key => $data)
|
|
{
|
|
$line = implode('|', $data) . "\r\n";
|
|
fwrite($fp, $line);
|
|
}
|
|
}
|
|
|
|
fclose($fp);
|
|
|
|
error_log('Loading warranty data');
|
|
$conn = $this->em->getConnection();
|
|
$stmt = $conn->prepare('LOAD DATA LOCAL INFILE \'' . $file . '\' INTO TABLE warranty FIELDS TERMINATED BY \'|\' LINES TERMINATED BY \'\\r\\n\' (bty_model_id,bty_size_id,sap_bty_id,warranty_class,plate_number,status,date_create,date_purchase,date_expire,first_name,last_name,mobile_number,flag_activated,vehicle_id,customer_id, create_source)');
|
|
$result = $stmt->execute();
|
|
if (!$result)
|
|
error_log('Failed loading data.');
|
|
|
|
// TODO: delete file?
|
|
}
|
|
|
|
protected function createLoadDataFileForJOEvent($jo_evt_data)
|
|
{
|
|
// cache directory
|
|
$cache_dir = __DIR__ . '/../../var/cache';
|
|
|
|
$file = $cache_dir . '/jo_event_data.tab';
|
|
error_log('opening file for jo_event - ' . $file);
|
|
|
|
$fp = fopen($file, 'w');
|
|
if ($fp === false)
|
|
{
|
|
error_log('could not open file for load data infile - ' . $file);
|
|
}
|
|
else
|
|
{
|
|
foreach ($jo_evt_data as $key => $data)
|
|
{
|
|
$line = implode('|', $data) . "\r\n";
|
|
fwrite($fp, $line);
|
|
}
|
|
}
|
|
|
|
fclose($fp);
|
|
|
|
error_log('Loading jo event data');
|
|
$conn = $this->em->getConnection();
|
|
$stmt = $conn->prepare('LOAD DATA LOCAL INFILE \'' . $file . '\' INTO TABLE jo_event FIELDS TERMINATED BY \'|\' LINES TERMINATED BY \'\\r\\n\' (create_user_id, job_order_id, date_create, date_happen, type_id, rider_id)');
|
|
$result = $stmt->execute();
|
|
if (!$result)
|
|
error_log('Failed loading data.');
|
|
|
|
// TODO: delete file?
|
|
}
|
|
|
|
protected function getCustomerInfo($conn, $id)
|
|
{
|
|
$cust_info = [];
|
|
|
|
$cust_sql = 'SELECT c.first_name, c.last_name, c.phone_mobile
|
|
FROM customer c
|
|
WHERE c.id = :id';
|
|
$cust_stmt = $conn->prepare($cust_sql);
|
|
$cust_stmt->execute([
|
|
'id' => $id,
|
|
]);
|
|
|
|
$cust_result = $cust_stmt->fetch();
|
|
|
|
$cust_info = [
|
|
'first_name' => $cust_result['first_name'],
|
|
'last_name' => $cust_result['last_name'],
|
|
'mobile' => $cust_result['phone_mobile'],
|
|
];
|
|
|
|
return $cust_info;
|
|
}
|
|
|
|
protected function getCustomerVehicleInfo($conn, $id)
|
|
{
|
|
$cv_info = [];
|
|
|
|
$cv_sql = 'SELECT cv.plate_number, cv.vehicle_id
|
|
FROM customer_vehicle cv
|
|
WHERE cv.id = :id';
|
|
$cv_stmt = $conn->prepare($cv_sql);
|
|
$cv_stmt->execute([
|
|
'id' => $id,
|
|
]);
|
|
|
|
$cv_result = $cv_stmt->fetch();
|
|
|
|
$plate_number = $cv_result['plate_number'];
|
|
|
|
$clean_plate = $this->cleanPlateNumber($plate_number);
|
|
|
|
$cv_info = [
|
|
'plate_number' => $clean_plate,
|
|
'vehicle_id' => $cv_result['vehicle_id'],
|
|
];
|
|
|
|
return $cv_info;
|
|
}
|
|
|
|
protected function getWarrantyPeriod($batt_id, $warranty_class)
|
|
{
|
|
// set default period to that of private
|
|
$period = $this->batt_hash[$batt_id]['warr_private'];
|
|
|
|
if ($warranty_class == WarrantyClass::WTY_PRIVATE)
|
|
{
|
|
$period = $this->batt_hash[$batt_id]['warr_private'];
|
|
return $period;
|
|
}
|
|
if ($warranty_class == WarrantyClass::WTY_COMMERCIAL)
|
|
{
|
|
$period = $this->batt_hash[$batt_id]['warr_commercial'];
|
|
return $period;
|
|
}
|
|
if ($warranty_class == WarrantyClass::WTY_TNV)
|
|
{
|
|
$period = $this->batt_hash[$batt_id]['warr_tnv'];
|
|
return $period;
|
|
}
|
|
|
|
return $period;
|
|
}
|
|
|
|
protected function computeDateExpire($purchase_date, $warranty_period)
|
|
{
|
|
$expire_date = clone $purchase_date;
|
|
$expire_date->add(new DateInterval('P'.$warranty_period.'M'));
|
|
return $expire_date;
|
|
}
|
|
|
|
protected function cleanPlateNumber($plate)
|
|
{
|
|
// trim plate number down to 20 characters
|
|
$trim_plate = str_replace(' ','', $plate);
|
|
|
|
// truncate plate number down to 20 (max length)
|
|
$trunc_plate = substr($trim_plate, 0, 20);
|
|
|
|
return strtoupper($trunc_plate);
|
|
}
|
|
|
|
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();
|
|
|
|
$results = $stmt->fetchAll();
|
|
|
|
// go through the rows
|
|
foreach ($results as $row)
|
|
{
|
|
// breaking this down for clarity
|
|
$battery_id = $row['id'];
|
|
$model_id = $row['model_id'];
|
|
$size_id = $row['size_id'];
|
|
$sap_code = trim($row['sap_code']);
|
|
$warr_private = $row['warr_private'];
|
|
$warr_commercial = $row['warr_commercial'];
|
|
$warr_tnv = $row['warr_tnv'];
|
|
|
|
$this->batt_hash[$battery_id] = [
|
|
'sap_code' => $sap_code,
|
|
'model_id' => $model_id,
|
|
'size_id' => $size_id,
|
|
'warr_private' => $warr_private,
|
|
'warr_commercial' => $warr_commercial,
|
|
'warr_tnv' => $warr_tnv,
|
|
];
|
|
}
|
|
}
|
|
|
|
protected function populateSAPBatteryIndex()
|
|
{
|
|
$conn = $this->em->getConnection();
|
|
|
|
// get all the sap batteries
|
|
$sql = 'SELECT sap.id, sap.brand_id, sap.size_id FROM sap_battery sap';
|
|
$stmt = $conn->prepare($sql);
|
|
$stmt->execute();
|
|
|
|
$results = $stmt->fetchAll();
|
|
|
|
// go through the rows
|
|
foreach ($results as $row)
|
|
{
|
|
// set warranty period to default warranty period for SAP batteries
|
|
$this->sap_batt_hash[$row['id']] = [
|
|
'sap_brand' => $row['brand_id'],
|
|
'sap_size' => $row['size_id'],
|
|
'warranty' => self::DEFAULT_SAP_WARRANTY,
|
|
];
|
|
}
|
|
}
|
|
}
|