resq/src/Command/ImportCarClubCustomerDataCommand.php
2021-06-11 06:45:09 +00:00

357 lines
10 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 DateTime;
use Exception;
use App\Entity\Customer;
use App\Entity\CustomerTag;
class ImportCarClubCustomerDataCommand extends Command
{
// field index in csv file
const F_DPA = 0;
const F_FIRST_NAME = 1;
const F_LAST_NAME = 2;
const F_CAR_CLUB = 3;
const F_CONTACT_NUM = 4;
protected $em;
protected $cust_tag_hash;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->loadCustomerTags();
parent::__construct();
}
protected function configure()
{
$this->setName('customer:createfromcarclub')
->setDescription('Create customers from car club file.')
->setHelp('Creates customers from car club file.')
->addArgument('promo_tag', InputArgument::REQUIRED, 'Promo customer tag ID to use.')
->addArgument('input_file', InputArgument::REQUIRED, 'Path to the output CSV file with the car club info.')
->addArgument('output_file', InputArgument::REQUIRED, 'Output filename');
}
protected function getValidContactNumbers($contact_number)
{
// check contact number if mobile or not
// check for spaces, slash, and forward slash
$contact_num_array = [];
if (preg_match('/[\\\s\/]/', $contact_number))
{
$contact_num_array = preg_split('/[\\\s\/]/', $contact_number);
}
else
{
// only one mobile number
$contact_num_array[] = $contact_number;
}
// collet clean numbers
$clean_nums = [];
foreach ($contact_num_array as $contact_num)
{
$c_num = trim($contact_num);
// clean the numbers
$cleaned_number = $this->normalizeContactNumber($c_num);
// not a blank, save it
if ($cleaned_number != '')
{
$clean_nums[] = $cleaned_number;
}
}
return $clean_nums;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$csv_file = $input->getArgument('input_file');
$output_file = $input->getArgument('output_file');
$promo_tag_id = $input->getArgument('promo_tag');
// fetch promo tag
$promo_tag = $this->em->getRepository(CustomerTag::class)->find($promo_tag_id);
if ($promo_tag == null)
{
throw new Exception('Could not find promo tag - ' . $promo_tag_id);
}
// attempt to open file
try
{
$fh = fopen($csv_file, "r");
}
catch (Exception $e)
{
throw new Exception('The file "' . $csv_file . '" could be opened.');
}
$row_num = 1;
$output_info = [];
while (($fields = fgetcsv($fh)) !== false)
{
// ignore first row
if ($row_num == 1)
{
$row_num++;
continue;
}
// process row
$output_info[] = $this->processRow($fields, $promo_tag);
$row_num++;
}
// write to output file
$this->outputCustomerInfo($output_file, $output_info);
fclose($fh);
return 0;
}
protected function setOutputInfo($fields, $status, $reason, $cust_id)
{
$car_club = trim($fields[self::F_CAR_CLUB]);
$fname = trim($fields[self::F_FIRST_NAME]);
$lname = trim($fields[self::F_LAST_NAME]);
$dpa = trim($fields[self::F_DPA]);
$contact_number = trim($fields[SELF::F_CONTACT_NUM]);
return [
$dpa,
$fname,
$lname,
$car_club,
$contact_number,
$status,
$reason,
$cust_id
];
}
protected function createNewCustomer($fields, $contact_numbers, $cust_tag, $promo_tag)
{
$fname = trim($fields[self::F_FIRST_NAME]);
$lname = trim($fields[self::F_LAST_NAME]);
$dpa = trim($fields[self::F_DPA]);
if (count($contact_numbers) > 0)
$clean_number = $contact_numbers[0];
else
$clean_number = '';
// check dpa
$is_dpa = false;
if (strtoupper($dpa) == 'YES')
$is_dpa = true;
// create new customer
$new_cust = new Customer();
$new_cust->setFirstName($fname)
->setLastName($lname)
->setPhoneMobile($clean_number)
->setDpaConsent($is_dpa)
->setCreateSource('car_club_file')
->addCustomerTag($cust_tag)
->addCustomerTag($promo_tag);
$this->em->persist($new_cust);
$this->em->flush();
return $new_cust;
}
protected function processRow($fields, $promo_tag)
{
$contact_number = trim($fields[SELF::F_CONTACT_NUM]);
$car_club = trim($fields[self::F_CAR_CLUB]);
// clean up contact number
$valid_contact_numbers = $this->getValidContactNumbers($contact_number);
// check customer tag
$cust_tag = $this->findCustomerTag($car_club);
$cust_id = '';
// give me first customer that matches any of the numbers
$customer = $this->findCustomerByNumbers($valid_contact_numbers);
// if no customer found, create one
if ($customer == null)
{
error_log('Creating customer...');
error_log('cust tag id ' . $cust_tag->getID());
// create new customer
$new_cust = $this->createNewCustomer($fields, $valid_contact_numbers, $cust_tag, $promo_tag);
// get customer id of new customer here
$cust_id = $new_cust->getID();
// add info to output array
return $this->setOutputInfo($fields, 'CREATED', '', $cust_id);
}
error_log('Updating customer...');
// add customer tag to existing customer
$cust_id = $customer->getID();
// need to check if customer tag already exists for customer
$tag_exists = $customer->getCustomerTag($cust_tag->getID());
if ($tag_exists == null)
{
$customer->addCustomerTag($cust_tag)
->addCustomerTag($promo_tag);
$this->em->flush();
// add info to output array
return $this->setOutputInfo($fields, 'UPDATED', '', $cust_id);
}
return $this->setOutputInfo($fields, 'NOT CREATED/UPDATED', 'Customer and tag already exist', $cust_id);
}
protected function findCustomerByNumbers($numbers)
{
error_log(print_r($numbers, true));
$customer = $this->em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $numbers]);
return $customer;
}
protected function outputCustomerInfo($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, [
'I have read and understood and agreed to the confidentiality of this form request',
'First Name',
'Last Name',
'Car Club/Organization',
'Contact Number',
'Status',
'Reason',
'Customer ID',
]);
foreach($entries as $row)
{
fputcsv($fh, $row);
}
fclose($fh);
}
protected function loadCustomerTags()
{
$this->cust_tag_hash = [];
$cust_tags = $this->em->getRepository(CustomerTag::class)->findAll();
foreach ($cust_tags as $cust_tag)
{
$tag_id = $cust_tag->getID();
$this->cust_tag_hash[$tag_id] = $cust_tag;
}
}
protected function normalizeClubName($name)
{
// uppercase the name
$clean_name = trim(strtoupper($name));
// remove apostrophes
$clean_name = str_replace("'", '', $clean_name);
// replace all special characters except ampersand (&) with whitespace
$clean_name = trim(preg_replace('/[^A-Za-z0-9&]/', ' ', $clean_name));
// replace spaces with underscore (_)
$clean_name = preg_replace('/\s+/', '_', $clean_name);
// prepend 'TAG_'
$tag_name = 'TAG_' . $clean_name;
return $tag_name;
}
protected function findCustomerTag($car_club)
{
// find the customer tag for club
$tag_name = $this->normalizeClubName($car_club);
error_log($tag_name);
if (isset($this->cust_tag_hash[$tag_name]))
return $this->cust_tag_hash[$tag_name];
error_log('customer tag not in hash...');
// create the customer tag
$new_cust_tag = new CustomerTag();
$tag_details = json_decode('{"type":"car club"}', true);
$new_cust_tag->setID($tag_name)
->setName(strtoupper($car_club))
->setTagDetails($tag_details);
$this->em->persist($new_cust_tag);
// need to flush before adding to hash
$this->em->flush();
$this->cust_tag_hash[$tag_name] = $new_cust_tag;
return $new_cust_tag;
}
protected function normalizeContactNumber($c_num)
{
// remove any non digit character from string
$clean_number = preg_replace('~\D~', '', $c_num);
error_log('cleaned ' . $clean_number);
// does it fit our 09XXXXXXXXX pattern?
if (preg_match('/^09[0-9]{9}$/', $clean_number))
{
// remove first '0'
$clean_number = substr($clean_number, 1);
error_log("CONVERTED TO $clean_number");
return $clean_number;
}
// does it fit our 63XXXXXXXXXX pattern?
else if (preg_match('/^63[0-9]{10}$/', $clean_number))
{
// remove the 63
$clean_number = substr($clean_number, 2);
error_log("CONVERTED TO $clean_number");
return $clean_number;
}
// does it fit our 9XXXXXXXXX pattern?
else if (preg_match('/^9[0-9]{9}$/', $clean_number))
{
error_log("already cleaned $clean_number");
return $clean_number;
}
return "";
}
}