469 lines
14 KiB
PHP
469 lines
14 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 Symfony\Component\HttpKernel\KernelInterface;
|
|
use Symfony\Component\Filesystem\Filesystem;
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
use App\Entity\WarrantySerial;
|
|
use App\Entity\WarrantySerialQueue;
|
|
use App\Entity\WarrantySerialUploadLog;
|
|
use App\Entity\WarrantySerialLoadLog;
|
|
|
|
use App\Service\WarrantySerialUploadLogger;
|
|
use App\Service\WarrantySerialLoadLogger;
|
|
|
|
use PDO;
|
|
use DateTime;
|
|
|
|
class LoadWarrantySerialCommand extends Command
|
|
{
|
|
const FIELD_COUNT = 7;
|
|
const SERIAL_LENGTH = 20;
|
|
|
|
protected $em;
|
|
protected $upload_logger;
|
|
protected $load_logger;
|
|
protected $project_dir;
|
|
protected $callback_url;
|
|
protected $log_data;
|
|
protected $filesystem;
|
|
|
|
public function __construct(EntityManagerInterface $em, WarrantySerialUploadLogger $upload_logger,
|
|
WarrantySerialLoadLogger $load_logger, KernelInterface $kernel, $callback_url,
|
|
FileSystem $filesystem)
|
|
{
|
|
$this->em = $em;
|
|
$this->upload_logger = $upload_logger;
|
|
$this->load_logger = $load_logger;
|
|
$this->project_dir = $kernel->getProjectDir();
|
|
$this->callback_url = $callback_url;
|
|
$this->filesystem = $filesystem;
|
|
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function configure()
|
|
{
|
|
$this->setName('warrantyserial:load')
|
|
->setDescription('Load warranty serials from file.')
|
|
->setHelp('Load warranty serials from file.');
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$em = $this->em;
|
|
$this->log_data = [];
|
|
|
|
$status = 'pending';
|
|
|
|
// get the filenames from the queue table with status pending
|
|
$db = $em->getConnection();
|
|
|
|
$ws_query_sql = 'SELECT id, file_serial, file_id, api_user, orig_file_serial FROM warranty_serial_queue
|
|
WHERE status = :status ORDER BY id LIMIT 1';
|
|
|
|
$ws_query_stmt = $db->prepare($ws_query_sql);
|
|
$ws_query_stmt->bindValue('status', $status);
|
|
|
|
$ws_results = $ws_query_stmt->executeQuery();
|
|
|
|
$output_info = [];
|
|
while ($row = $ws_results->fetchAssociative())
|
|
{
|
|
$filename = $row['file_serial'];
|
|
$user_id = $row['api_user'];
|
|
$id = $row['id'];
|
|
$file_id = $row['file_id'];
|
|
$orig_filename = $row['orig_file_serial'];
|
|
|
|
$output_info[] = $this->processWarrantySerialFile($filename, $user_id, $file_id, $orig_filename);
|
|
|
|
// remove entry from queue table
|
|
$this->updateWarrantySerialQueue($id);
|
|
|
|
// delete the uploaded csv file and directory
|
|
$this->deleteDirectoryAndFile($file_id);
|
|
}
|
|
|
|
if (count($output_info) > 0)
|
|
{
|
|
// error_log(print_r($this->log_data, true));
|
|
// load log data into db
|
|
$this->load_logger->logWarrantySerialLoadInfo($this->log_data);
|
|
|
|
// send results back to third party
|
|
$this->sendResults($output_info);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
protected function processWarrantySerialFile($filename, $user_id, $file_id, $orig_filename)
|
|
{
|
|
$csv_file = $this->project_dir . '/public/warranty_serial_uploads/' . $filename;
|
|
|
|
$output_info = [];
|
|
|
|
// attempt to open file
|
|
try
|
|
{
|
|
$fh = fopen($csv_file, "r");
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
$error = 'The file ' . $csv_file . 'could not be read.';
|
|
$log_data = [
|
|
'user_id' => $user_id,
|
|
'is_uploaded' => false,
|
|
'error' => $error,
|
|
];
|
|
$this->upload_logger->logWarrantySerialUploadInfo($log_data);
|
|
|
|
$output_info = $this->setOutputInfo($filename, $file_id, true, $error, $data, $orig_filename);
|
|
|
|
return $output_info;
|
|
}
|
|
|
|
$data = [];
|
|
while(($row = fgetcsv($fh)) !== false)
|
|
{
|
|
$validation_result = $this->validateRow($row, $user_id);
|
|
if (!empty($validation_result))
|
|
{
|
|
$data[] = $validation_result;
|
|
continue;
|
|
}
|
|
|
|
// valid entry, we parse and insert
|
|
$serial = trim(strtoupper($row[0]));
|
|
|
|
// error_log('Processing ' . $serial);
|
|
|
|
$sku = trim(strtoupper($row[1]));
|
|
$dispatch_status = trim($row[2]);
|
|
$str_date_create = trim($row[3]);
|
|
$inventory_status = trim($row[4]);
|
|
$cat_id = trim($row[5]);
|
|
$cat_name = trim(strtoupper($row[6]));
|
|
|
|
// we are sure that this is a valid date at this point
|
|
$created_date = $this->convertDateCreate($str_date_create);
|
|
|
|
$meta_info = [
|
|
'dispatch_status' => $dispatch_status,
|
|
'inventory_status' => $inventory_status,
|
|
'category_id' => $cat_id,
|
|
'category_name' => $cat_name,
|
|
];
|
|
|
|
$info = json_encode($meta_info);
|
|
|
|
// prepare the data
|
|
$source = 'motiv';
|
|
if ($sku == 'N/A')
|
|
$sku = null;
|
|
|
|
// prepared statement
|
|
$db = $this->em->getConnection();
|
|
$insert_stmt = $db->prepare('INSERT INTO warranty_serial (id, sku, date_create, source, meta_info)
|
|
VALUES (:serial, :sku, :date_create, :source, :meta_info)');
|
|
|
|
$res = $insert_stmt->execute([
|
|
':serial' => $serial,
|
|
':sku' => $sku,
|
|
':date_create' => $created_date,
|
|
':source' => $source,
|
|
':meta_info' => $info,
|
|
]);
|
|
|
|
if (!$res)
|
|
{
|
|
// log the not successful insert
|
|
$err = $insert_stmt->errorInfo();
|
|
$error = $err[2];
|
|
$this->logLoadInfo($user_id, false, $serial, $error);
|
|
|
|
$data[] = [
|
|
'serial' => $serial,
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
}
|
|
else
|
|
{
|
|
// log the successful insert
|
|
$this->logLoadInfo($user_id, true, $serial, '');
|
|
|
|
$data[] = [
|
|
'serial' => $serial,
|
|
'status' => 'success',
|
|
'has_error' => false,
|
|
'error_message' => '',
|
|
];
|
|
}
|
|
}
|
|
|
|
// form what we output
|
|
$output_info = $this->setOutputInfo($filename, $file_id, false, '', $data, $orig_filename, $orig_filename);
|
|
|
|
return $output_info;
|
|
}
|
|
|
|
protected function validateRow($row, $user_id)
|
|
{
|
|
$data = [];
|
|
// possible lines:
|
|
// (1) header in csv file - ignore
|
|
// SerialNumber,Sku,DispatchStatus,CreatedDate,InventoryStatus,CategoryID,CategoryName
|
|
// (2) No available data - ignore
|
|
// (3) CH2000012071,WCHD23BL-CPN00-LX,0,2020-08-11 04:05:27.090,0,4,CHAMPION MF - valid
|
|
// (4) MG2000313690,N/A,1,2021-05-14T23:47:30.6430000+08:00,0,10,GOLD - valid
|
|
// (5) Empty line - ignore
|
|
// (6) empty sku - log
|
|
|
|
// check if empty line
|
|
if ($row == array(null))
|
|
{
|
|
// no need to log, but send back error
|
|
$error = 'Empty line';
|
|
$data = [
|
|
'serial' => '',
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// check the number of fields
|
|
if (count($row) != self::FIELD_COUNT)
|
|
{
|
|
$error = 'Invalid number of fields.';
|
|
$data = [
|
|
'serial' => '',
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// check if the line is a header
|
|
if ($row[0] == 'SerialNumber')
|
|
{
|
|
// no need to log, but send back error
|
|
$error = 'Invalid information.';
|
|
$data = [
|
|
'serial' => '',
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// check if empty serial
|
|
if (empty($row[0]))
|
|
{
|
|
// this one, we log
|
|
$error = 'Empty serial';
|
|
$this->logLoadInfo($user_id, false, '', $error);
|
|
|
|
$data = [
|
|
'serial' => '',
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// check length of serial
|
|
$serial = trim($row[0]);
|
|
if (strlen($serial) > SELF::SERIAL_LENGTH)
|
|
{
|
|
// log
|
|
$error = 'Serial length too long';
|
|
$this->logLoadInfo($user_id, false, $serial, $error);
|
|
|
|
$data = [
|
|
'serial' => $serial,
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// validate the date created
|
|
$str_date_create = trim($row[3]);
|
|
|
|
$date_create = $this->convertDateCreate($str_date_create);
|
|
if ($date_create == null)
|
|
{
|
|
// log
|
|
$error = 'Invalid date create.';
|
|
$this->logLoadInfo($user_id, false, $serial, $error);
|
|
|
|
$data = [
|
|
'serial' => $serial,
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// check if serial is a dupe
|
|
$existing_serial = $this->em->getRepository(WarrantySerial::class)->find($serial);
|
|
if ($existing_serial != null)
|
|
{
|
|
// log
|
|
$error = 'Serial already exists.';
|
|
$this->logLoadInfo($user_id, false, $serial, $error);
|
|
|
|
$data = [
|
|
'serial' => $serial,
|
|
'status' => 'error',
|
|
'has_error' => true,
|
|
'error_message' => $error,
|
|
];
|
|
|
|
return $data;
|
|
}
|
|
|
|
// valid entry, return empty
|
|
return $data;
|
|
}
|
|
|
|
protected function convertDateCreate($str_date_create)
|
|
{
|
|
// since some people cannot follow simple instructions...
|
|
// check the date format on the string
|
|
// try 2021-05-15T08:35:46+08:00 format on str_date_create
|
|
$date_create = DateTime::createFromFormat('Y-m-d\TH:i:sP', $str_date_create);
|
|
|
|
if ($date_create == false)
|
|
{
|
|
// try this format: 2021-05-15T08:47:20.3330000+08:00
|
|
// get the date, time and timezone from str_date_create
|
|
$str_date_time = substr($str_date_create, 0, 19);
|
|
$str_timezone = substr($str_date_create, 27);
|
|
$str_datetime_tz = $str_date_time . $str_timezone;
|
|
|
|
// create DateTime object
|
|
// sample: 2021-05-15T12:16:06+08:00
|
|
$date_create = DateTime::createFromFormat('Y-m-d\TH:i:sP', $str_datetime_tz);
|
|
|
|
// check if datetime object was created
|
|
// if not, someone f*cked up and we have no date create
|
|
if ($date_create == false)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// if you reach this part, then date string is valid. Since we'll be using
|
|
// sql to insert the entries, we return the string
|
|
$created_date = $date_create->format('Y-m-d H:i:s');
|
|
// $created_date = DateTime::createFromFormat('Y-m-d H:i:s', $str_created_date);
|
|
|
|
return $created_date;
|
|
}
|
|
|
|
protected function logLoadInfo($user_id, $is_loaded, $serial, $error)
|
|
{
|
|
$date_create = new DateTime();
|
|
$str_date_create = $date_create->format('Y-m-d H:i:s');
|
|
|
|
$this->log_data[] = [
|
|
$str_date_create,
|
|
$user_id,
|
|
$serial,
|
|
$is_loaded,
|
|
$error,
|
|
];
|
|
}
|
|
|
|
protected function updateWarrantySerialQueue($id)
|
|
{
|
|
// prepared statement
|
|
$db = $this->em->getConnection();
|
|
|
|
// lock the warranty serial queue table
|
|
$db->exec('LOCK TABLES warranty_serial_queue WRITE;');
|
|
|
|
$delete_stmt = $db->prepare('DELETE FROM warranty_serial_queue
|
|
WHERE id = :id');
|
|
|
|
$res = $delete_stmt->execute([
|
|
':id' => $id,
|
|
]);
|
|
|
|
$db->exec('UNLOCK TABLES;');
|
|
}
|
|
|
|
protected function deleteDirectoryAndFile($filedir)
|
|
{
|
|
$csv_filedir = $this->project_dir . '/public/warranty_serial_uploads/' . $filedir;
|
|
|
|
$this->filesystem->remove($csv_filedir);
|
|
}
|
|
|
|
protected function setOutputInfo($filename, $file_id, $has_error, $error_message, $entries, $orig_filename)
|
|
{
|
|
$info = [
|
|
'id' => $file_id,
|
|
'filename' => $orig_filename,
|
|
'has_error' => $has_error,
|
|
'error_message' => $error_message,
|
|
'data' => $entries,
|
|
];
|
|
|
|
return $info;
|
|
}
|
|
|
|
protected function sendResults($output_info)
|
|
{
|
|
$body = json_encode($output_info);
|
|
|
|
// error_log(print_r($body, true));
|
|
|
|
// error_log('Sending json output to ' . $this->callback_url);
|
|
|
|
$curl = curl_init();
|
|
|
|
$options = [
|
|
CURLOPT_URL => $this->callback_url,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POSTFIELDS => $body,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
],
|
|
];
|
|
|
|
curl_setopt_array($curl, $options);
|
|
$res = curl_exec($curl);
|
|
|
|
curl_close($curl);
|
|
|
|
// check result
|
|
error_log('Result ' . $res);
|
|
}
|
|
|
|
}
|