From 079c8a033ab95dbf3e0eed9469c4a537bd49377f Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 28 May 2021 10:06:18 +0000 Subject: [PATCH 1/7] Add command to create customer from car club file. #572 --- .../ImportCarClubCustomerDataCommand.php | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/Command/ImportCarClubCustomerDataCommand.php diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php new file mode 100644 index 00000000..2d5f5ac2 --- /dev/null +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -0,0 +1,156 @@ +em = $em; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('customer:createfromcarclub') + ->setDescription('Create customers from car club file.') + ->setHelp('Creates customers from car club file.') + ->addArgument('file', InputArgument::REQUIRED, 'Path to the output CSV file with the car club info.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $csv_file = $input->getArgument('file'); + + // attempt to open file + try + { + $fh = fopen($csv_file, "w"); + } + catch (Exception $e) + { + throw new Exception('The file "' . $csv_file . '" could be opened.'); + } + + $row_num = 1; + while (($fields = fgetcsv($fh)) !== false) + { + // ignore first row + if ($row_num == 1) + { + $row_num++; + continue; + } + + $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]); + + // check in case of multiple numbers + // check contact number if mobile or not + // check for spaces, slash, and forward slash + // mobile has length 10 if no 63, 12 if has 63 + // landline has 8 if no area code, 10 if with area code + $contact_num_array = []; + if (preg_match('/[\\\s\/]/', $contact_number)) + { + $contact_num_array = preg_split('/[\\\s\/]/', $contact_number); + } + else + { + // only one mobile number + $contact_number_array[] = $contact_number; + } + + foreach ($contact_num_array as $contact_num) + { + $c_num = trim($contact_num); + + if (empty($c_num)) + continue; + + // does it fit our 09XXXXXXXXX pattern? + if (preg_match('/^09[0-9]{9}$/', $c_num)) + { + // remove first '0' + $c_num = substr($c_num, 1); + error_log("CONVERTED TO $c_num"); + } + + // does it fit our 9XXXXXXXXX pattern? + if (!preg_match('/^9[0-9]{9}$/', $c_num)) + continue; + + $customers = $this->findCustomerByNumber($c_num); + + if (empty($customers)) + { + // 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($c_num) + ->setDpaConsent($is_dpa) + ->setCreateSource('car_club_file'); + + $this->em->persist($new_cust); + } + } + + $this->em->flush(); + $this->em->clear(); + + $row_num++; + } + fclose($fh); + return 0; + } + + protected function findCustomerByNumber($number) + { + $customers = $this->em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]); + return $customers; + } +} From be48ecdb82d5524cc7cb144d3bec1d7d2ceb77c7 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 31 May 2021 05:39:20 +0000 Subject: [PATCH 2/7] Added cleaning of contact numbers. #572 --- .../ImportCarClubCustomerDataCommand.php | 133 +++++++++++++++--- 1 file changed, 112 insertions(+), 21 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index 2d5f5ac2..87ff2b75 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -18,7 +18,7 @@ class ImportCarClubCustomerDataCommand extends Command // field index in csv file const F_TIMESTAMP = 0; const F_DPA = 1; - const F_FIRST_NAM = 2; + const F_FIRST_NAME = 2; const F_MIDDLE_NAME = 3; const F_LAST_NAME = 4; const F_BIRTHDATE = 5; @@ -31,11 +31,13 @@ class ImportCarClubCustomerDataCommand extends Command const F_VEHICLE = 12; const F_VEHICLE_EXCEL = 13; const F_BATT_SIZE = 14; - const F_CONTACT_NUM = 15; - const F_BWI_LOCATION = 16; - const F_SAP_CODE = 17; - const F_SKU = 18; - const F_QTY = 19; + const F_REPLACE_SKED = 15; + const F_DEALER_VISIT = 16; + const F_CONTACT_NUM = 17; + const F_BWI_LOCATION = 18; + const F_SAP_CODE = 19; + const F_SKU = 20; + const F_QTY = 21; protected $em; @@ -51,17 +53,19 @@ class ImportCarClubCustomerDataCommand extends Command $this->setName('customer:createfromcarclub') ->setDescription('Create customers from car club file.') ->setHelp('Creates customers from car club file.') - ->addArgument('file', InputArgument::REQUIRED, 'Path to the output CSV file with the car club info.'); + ->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 execute(InputInterface $input, OutputInterface $output) { - $csv_file = $input->getArgument('file'); + $csv_file = $input->getArgument('input_file'); + $output_file = $input->getArgument('output_file'); // attempt to open file try { - $fh = fopen($csv_file, "w"); + $fh = fopen($csv_file, "r"); } catch (Exception $e) { @@ -69,6 +73,7 @@ class ImportCarClubCustomerDataCommand extends Command } $row_num = 1; + $output_info = []; while (($fields = fgetcsv($fh)) !== false) { // ignore first row @@ -78,6 +83,24 @@ class ImportCarClubCustomerDataCommand extends Command continue; } + $timestamp = trim($fields[self::F_TIMESTAMP]); + $mname = trim($fields[self::F_MIDDLE_NAME]); + $birthdate = trim($fields[self::F_BIRTHDATE]); + $address = trim($fields[self::F_ADDRESS]); + $city = trim($fields[self::F_CITY]); + $region = trim($fields[self::F_REGION]); + $car_club = trim($fields[self::F_CAR_CLUB]); + $position = trim($fields[self::F_POSITION]); + $member_number = trim($fields[self::F_MEMBER_NUM]); + $vehicle = trim($fields[self::F_VEHICLE]); + $vehicle_excel = trim($fields[self::F_VEHICLE_EXCEL]); + $batt_size = trim($fields[self::F_BATT_SIZE]); + $replace_sked = trim($fields[self::F_REPLACE_SKED]); + $dealer_visit = trim($fields[self::F_DEALER_VISIT]); + $bwi_location = trim($fields[self::F_BWI_LOCATION]); + $sap_code = trim($fields[self::F_SAP_CODE]); + $sku = trim($fields[self::F_SKU]); + $qty = trim($fields[self::F_QTY]); $fname = trim($fields[self::F_FIRST_NAME]); $lname = trim($fields[self::F_LAST_NAME]); $dpa = trim($fields[self::F_DPA]); @@ -86,9 +109,8 @@ class ImportCarClubCustomerDataCommand extends Command // check in case of multiple numbers // check contact number if mobile or not // check for spaces, slash, and forward slash - // mobile has length 10 if no 63, 12 if has 63 - // landline has 8 if no area code, 10 if with area code $contact_num_array = []; + $cust_id = ''; if (preg_match('/[\\\s\/]/', $contact_number)) { $contact_num_array = preg_split('/[\\\s\/]/', $contact_number); @@ -96,7 +118,7 @@ class ImportCarClubCustomerDataCommand extends Command else { // only one mobile number - $contact_number_array[] = $contact_number; + $contact_num_array[] = $contact_number; } foreach ($contact_num_array as $contact_num) @@ -104,19 +126,41 @@ class ImportCarClubCustomerDataCommand extends Command $c_num = trim($contact_num); if (empty($c_num)) + { + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED', 'Missing contact number', $cust_id); continue; + } + + // 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}$/', $c_num)) + if (preg_match('/^09[0-9]{9}$/', $clean_number)) { // remove first '0' - $c_num = substr($c_num, 1); - error_log("CONVERTED TO $c_num"); + $clean_number = substr($clean_number, 1); + error_log("CONVERTED TO $clean_number"); + } + + // does it fit our 63XXXXXXXXXX pattern? + if (preg_match('/^63[0-9]{10}$/', $clean_number)) + { + // remove the 63 + $clean_number = substr($clean_number, 2); + error_log("CONVERTED TO $clean_number"); } // does it fit our 9XXXXXXXXX pattern? - if (!preg_match('/^9[0-9]{9}$/', $c_num)) - continue; + if (!preg_match('/^9[0-9]{9}$/', $clean_number)) + { + error_log('not a mobile number'); + // set clean_number to blank since we don't save a non-mobile number + $clean_number = ''; + } $customers = $this->findCustomerByNumber($c_num); @@ -131,17 +175,24 @@ class ImportCarClubCustomerDataCommand extends Command $new_cust = new Customer(); $new_cust->setFirstName($fname) ->setLastName($lname) - ->setPhoneMobile($c_num) + ->setPhoneMobile($clean_number) ->setDpaConsent($is_dpa) ->setCreateSource('car_club_file'); $this->em->persist($new_cust); + $this->em->flush(); + // get customer id of new customer here + $cust_id = $new_cust->getId(); + $this->em->clear(); + + // output to file + } + else + { + // update customer } } - $this->em->flush(); - $this->em->clear(); - $row_num++; } fclose($fh); @@ -153,4 +204,44 @@ class ImportCarClubCustomerDataCommand extends Command $customers = $this->em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]); return $customers; } + + protected function outputCustomerInfo($output_file) + { + try + { + $fh = fopen($output_file, "w"); + } + catch (Exception $e) + { + throw new Exception('The file "' . $report_file . '" could be opened.'); + } + + // write the headers + fputcsv($fh, [ + 'Timestamp', + 'I have read and understood and agreed to the confidentiality of this form request', + 'First Name', + 'Middle Name', + 'Last Name', + 'Birth date', + 'Address', + 'City', + 'Region', + 'Car Club/Organization', + 'Position in the organization', + 'Official Member Number (type NA if not applicable)', + 'Vehicles you own? Year - Make -Model - Plate/Conduction number (ex 2017 NISSAN NAVARA ABC 1234) you can indicate all your vehicles', + 'If your were given a chance to EXperience the New Motolite Excel, Choose 1 vehicle and it\'s plate/conduction number', + 'What is the Battery size of the vehicle you with to EXperience the New Motolite Excel', + 'Given a specific date, when can you schedule your replacement?', + 'Will you be able to visit our dealer that we will assign nearest to you?', + 'Contact Number', + 'BWI LOCATION', + 'SAP CODE', + 'SKU', + 'QTY', + ]); + + fclose($fh); + } } From 7d99eab2ccfa03afabfec73d0002da546b0025fb Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 31 May 2021 09:44:42 +0000 Subject: [PATCH 3/7] Add writing to file actions done. #572 --- .../ImportCarClubCustomerDataCommand.php | 147 +++++++++++++++++- src/Entity/Customer.php | 10 +- src/Entity/CustomerTag.php | 4 +- 3 files changed, 154 insertions(+), 7 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index 87ff2b75..9e623057 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -12,6 +12,7 @@ use Doctrine\ORM\EntityManagerInterface; use DateTime; use App\Entity\Customer; +use App\Entity\CustomerTag; class ImportCarClubCustomerDataCommand extends Command { @@ -40,10 +41,12 @@ class ImportCarClubCustomerDataCommand extends Command const F_QTY = 21; protected $em; + protected $cust_tag_hash; public function __construct(EntityManagerInterface $em) { $this->em = $em; + $this->loadCustomerTags(); parent::__construct(); } @@ -106,6 +109,32 @@ class ImportCarClubCustomerDataCommand extends Command $dpa = trim($fields[self::F_DPA]); $contact_number = trim($fields[SELF::F_CONTACT_NUM]); + // check customer tag + // find the customer tag for club + $tag_name = $this->normalizeClubName($car_club); + error_log($tag_name); + $cust_tag = null; + if (isset($this->cust_tag_hash[$tag_name])) + { + error_log('customer tag in hash'); + $cust_tag = $this->cust_tag_hash[$tag_name]; + } + else + { + // 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); + // add to hash + $this->cust_tag_hash[$tag_name] = $new_cust_tag; + + $this->em->persist($new_cust_tag); + + $cust_tag = $new_cust_tag; + } + // check in case of multiple numbers // check contact number if mobile or not // check for spaces, slash, and forward slash @@ -166,6 +195,8 @@ class ImportCarClubCustomerDataCommand extends Command if (empty($customers)) { + error_log('Creating customer...'); + error_log('cust tag id ' . $cust_tag->getID()); // check dpa $is_dpa = false; if (strtoupper($dpa) == 'YES') @@ -177,7 +208,8 @@ class ImportCarClubCustomerDataCommand extends Command ->setLastName($lname) ->setPhoneMobile($clean_number) ->setDpaConsent($is_dpa) - ->setCreateSource('car_club_file'); + ->setCreateSource('car_club_file') + ->addCustomerTag($cust_tag); $this->em->persist($new_cust); $this->em->flush(); @@ -185,16 +217,48 @@ class ImportCarClubCustomerDataCommand extends Command $cust_id = $new_cust->getId(); $this->em->clear(); - // output to file + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'CREATED', '', $cust_id); } else { - // update customer + error_log('Updating customer...'); + // add customer tag to existing customer + foreach ($customers as $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); + + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'UPDATED', '', $cust_id); + } + else + { + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED/UPDATED', 'CUSTOMER AND TAG ALREADY EXIST', $cust_id); + } + } + $this->em->flush(); + $this->em->clear(); } } $row_num++; } + + // write to output file + $this->outputCustomerInfo($output_file, $output_info); + fclose($fh); return 0; } @@ -205,7 +269,42 @@ class ImportCarClubCustomerDataCommand extends Command return $customers; } - protected function outputCustomerInfo($output_file) + protected function addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, $status, $reason, $cust_id) + { + $output_entry = [ + $timestamp, + $dpa, + $fname, + $mname, + $lname, + $birthdate, + $address, + $city, + $region, + $car_club, + $position, + $member_number, + $vehicle, + $vehicle_excel, + $batt_size, + $replace_sked, + $dealer_visit, + $contact_number, + $bwi_location, + $sap_code, + $sku, + $qty, + $status, + $reason, + $cust_id + ]; + + return $output_entry; + } + + protected function outputCustomerInfo($output_file, $entries) { try { @@ -240,8 +339,48 @@ class ImportCarClubCustomerDataCommand extends Command 'SAP CODE', 'SKU', 'QTY', + '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; + } } diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index 2f593e00..2257bfb2 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -210,7 +210,7 @@ class Customer // customer tags /** - * @ORM\ManyToMany(targetEntity="CustomerTag", inversedBy="customers") + * @ORM\ManyToMany(targetEntity="CustomerTag", inversedBy="customers", indexBy="id") * @ORM\JoinTable(name="customer_customer_tags") */ protected $customer_tags; @@ -643,6 +643,14 @@ class Customer return $this->customer_tags; } + public function getCustomerTag($id) + { + if (isset($this->customer_tags[$id])) + return $this->customer_tags[$id]; + + return null; + } + public function removeCustomerTag(CustomerTag $customer_tag) { $this->customer_tags->removeElement($customer_tag); diff --git a/src/Entity/CustomerTag.php b/src/Entity/CustomerTag.php index 4ce840ab..57d9a22f 100644 --- a/src/Entity/CustomerTag.php +++ b/src/Entity/CustomerTag.php @@ -15,14 +15,14 @@ class CustomerTag { /** * @ORM\Id - * @ORM\Column(type="string", length=80, nullable=false, unique=true) + * @ORM\Column(type="string", length=200, nullable=false, unique=true) * @Assert\NotBlank() */ protected $id; // name of tag /** - * @ORM\Column(type="string", length=80) + * @ORM\Column(type="string", length=200) * @Assert\NotBlank() */ protected $name; From 6a075bd46ba7c178a649ea334e2e0a823457422b Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 31 May 2021 10:36:45 +0000 Subject: [PATCH 4/7] Fix issues found. #572 --- .../ImportCarClubCustomerDataCommand.php | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index 9e623057..c86948bb 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -114,26 +114,24 @@ class ImportCarClubCustomerDataCommand extends Command $tag_name = $this->normalizeClubName($car_club); error_log($tag_name); $cust_tag = null; - if (isset($this->cust_tag_hash[$tag_name])) - { - error_log('customer tag in hash'); - $cust_tag = $this->cust_tag_hash[$tag_name]; - } - else + if (!isset($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); - // add to hash - $this->cust_tag_hash[$tag_name] = $new_cust_tag; - $this->em->persist($new_cust_tag); - $cust_tag = $new_cust_tag; + // need to flush before adding to hash + $this->em->flush(); + + $this->cust_tag_hash[$tag_name] = $new_cust_tag; + } + $cust_tag = $this->cust_tag_hash[$tag_name]; // check in case of multiple numbers // check contact number if mobile or not @@ -202,6 +200,9 @@ class ImportCarClubCustomerDataCommand extends Command if (strtoupper($dpa) == 'YES') $is_dpa = true; + // get the customer tag? + $c_tag = $this->em->getRepository(CustomerTag::class)->find($cust_tag->getID()); + // create new customer $new_cust = new Customer(); $new_cust->setFirstName($fname) @@ -209,7 +210,7 @@ class ImportCarClubCustomerDataCommand extends Command ->setPhoneMobile($clean_number) ->setDpaConsent($is_dpa) ->setCreateSource('car_club_file') - ->addCustomerTag($cust_tag); + ->addCustomerTag($c_tag); $this->em->persist($new_cust); $this->em->flush(); From 5830ad0c09c87cd7a2992f67e54e964d7a95661e Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Mon, 31 May 2021 20:43:21 +0800 Subject: [PATCH 5/7] Fix issue by removing entity manager clear #572 --- .../ImportCarClubCustomerDataCommand.php | 99 ++++++++++--------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index c86948bb..8265be5f 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -110,30 +110,8 @@ class ImportCarClubCustomerDataCommand extends Command $contact_number = trim($fields[SELF::F_CONTACT_NUM]); // check customer tag - // find the customer tag for club - $tag_name = $this->normalizeClubName($car_club); - error_log($tag_name); - $cust_tag = null; - if (!isset($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); + $cust_tag = $this->findCustomerTag($car_club); - // need to flush before adding to hash - $this->em->flush(); - - $this->cust_tag_hash[$tag_name] = $new_cust_tag; - - } - $cust_tag = $this->cust_tag_hash[$tag_name]; - - // check in case of multiple numbers // check contact number if mobile or not // check for spaces, slash, and forward slash $contact_num_array = []; @@ -189,9 +167,10 @@ class ImportCarClubCustomerDataCommand extends Command $clean_number = ''; } - $customers = $this->findCustomerByNumber($c_num); + $customer = $this->findCustomerByNumber($c_num); - if (empty($customers)) + // if no customer found, create one + if ($customer == null) { error_log('Creating customer...'); error_log('cust tag id ' . $cust_tag->getID()); @@ -216,7 +195,6 @@ class ImportCarClubCustomerDataCommand extends Command $this->em->flush(); // get customer id of new customer here $cust_id = $new_cust->getId(); - $this->em->clear(); // add info to output array $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, @@ -227,30 +205,28 @@ class ImportCarClubCustomerDataCommand extends Command { error_log('Updating customer...'); // add customer tag to existing customer - foreach ($customers as $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); - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'UPDATED', '', $cust_id); - } - else - { - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED/UPDATED', 'CUSTOMER AND TAG ALREADY EXIST', $cust_id); - } + $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); + + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'UPDATED', '', $cust_id); } + else + { + // add info to output array + $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, + $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, + $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED/UPDATED', 'CUSTOMER AND TAG ALREADY EXIST', $cust_id); + } + $this->em->flush(); - $this->em->clear(); } } @@ -266,8 +242,8 @@ class ImportCarClubCustomerDataCommand extends Command protected function findCustomerByNumber($number) { - $customers = $this->em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]); - return $customers; + $customer = $this->em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $number]); + return $customer; } protected function addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, @@ -384,4 +360,29 @@ class ImportCarClubCustomerDataCommand extends Command 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; + } } From bfc86abd6aceb8e4e0d7b705b3f51f4e4d2e4e09 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Tue, 1 Jun 2021 01:10:38 +0800 Subject: [PATCH 6/7] Refactor entire car club import command #572 --- .../ImportCarClubCustomerDataCommand.php | 351 ++++++++++-------- 1 file changed, 197 insertions(+), 154 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index 8265be5f..7cda2676 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -10,6 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Doctrine\ORM\EntityManagerInterface; use DateTime; +use Exception; use App\Entity\Customer; use App\Entity\CustomerTag; @@ -56,14 +57,84 @@ class ImportCarClubCustomerDataCommand extends Command $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); + + // remove any non digit character from string + $clean_number = preg_replace('~\D~', '', $c_num); + error_log('cleaned ' . $clean_number); + + // QUESTION: why are these all ifs and not else ifs? + + // 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"); + } + + // does it fit our 63XXXXXXXXXX pattern? + if (preg_match('/^63[0-9]{10}$/', $clean_number)) + { + // remove the 63 + $clean_number = substr($clean_number, 2); + error_log("CONVERTED TO $clean_number"); + } + + // does it fit our 9XXXXXXXXX pattern? + if (!preg_match('/^9[0-9]{9}$/', $clean_number)) + { + error_log('not a mobile number'); + // set clean_number to blank since we don't save a non-mobile number + $clean_number = ''; + } + + // not a blank, save it + if ($clean_number != '') + { + $clean_nums[] = $clean_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 @@ -85,150 +156,9 @@ class ImportCarClubCustomerDataCommand extends Command $row_num++; continue; } - - $timestamp = trim($fields[self::F_TIMESTAMP]); - $mname = trim($fields[self::F_MIDDLE_NAME]); - $birthdate = trim($fields[self::F_BIRTHDATE]); - $address = trim($fields[self::F_ADDRESS]); - $city = trim($fields[self::F_CITY]); - $region = trim($fields[self::F_REGION]); - $car_club = trim($fields[self::F_CAR_CLUB]); - $position = trim($fields[self::F_POSITION]); - $member_number = trim($fields[self::F_MEMBER_NUM]); - $vehicle = trim($fields[self::F_VEHICLE]); - $vehicle_excel = trim($fields[self::F_VEHICLE_EXCEL]); - $batt_size = trim($fields[self::F_BATT_SIZE]); - $replace_sked = trim($fields[self::F_REPLACE_SKED]); - $dealer_visit = trim($fields[self::F_DEALER_VISIT]); - $bwi_location = trim($fields[self::F_BWI_LOCATION]); - $sap_code = trim($fields[self::F_SAP_CODE]); - $sku = trim($fields[self::F_SKU]); - $qty = trim($fields[self::F_QTY]); - $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]); - - // check customer tag - $cust_tag = $this->findCustomerTag($car_club); - - // check contact number if mobile or not - // check for spaces, slash, and forward slash - $contact_num_array = []; - $cust_id = ''; - if (preg_match('/[\\\s\/]/', $contact_number)) - { - $contact_num_array = preg_split('/[\\\s\/]/', $contact_number); - } - else - { - // only one mobile number - $contact_num_array[] = $contact_number; - } - - foreach ($contact_num_array as $contact_num) - { - $c_num = trim($contact_num); - - if (empty($c_num)) - { - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED', 'Missing contact number', $cust_id); - continue; - } - - // 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"); - } - - // does it fit our 63XXXXXXXXXX pattern? - if (preg_match('/^63[0-9]{10}$/', $clean_number)) - { - // remove the 63 - $clean_number = substr($clean_number, 2); - error_log("CONVERTED TO $clean_number"); - } - - // does it fit our 9XXXXXXXXX pattern? - if (!preg_match('/^9[0-9]{9}$/', $clean_number)) - { - error_log('not a mobile number'); - // set clean_number to blank since we don't save a non-mobile number - $clean_number = ''; - } - - $customer = $this->findCustomerByNumber($c_num); - - // if no customer found, create one - if ($customer == null) - { - error_log('Creating customer...'); - error_log('cust tag id ' . $cust_tag->getID()); - // check dpa - $is_dpa = false; - if (strtoupper($dpa) == 'YES') - $is_dpa = true; - - // get the customer tag? - $c_tag = $this->em->getRepository(CustomerTag::class)->find($cust_tag->getID()); - - // create new customer - $new_cust = new Customer(); - $new_cust->setFirstName($fname) - ->setLastName($lname) - ->setPhoneMobile($clean_number) - ->setDpaConsent($is_dpa) - ->setCreateSource('car_club_file') - ->addCustomerTag($c_tag); - - $this->em->persist($new_cust); - $this->em->flush(); - // get customer id of new customer here - $cust_id = $new_cust->getId(); - - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'CREATED', '', $cust_id); - } - else - { - 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); - - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'UPDATED', '', $cust_id); - } - else - { - // add info to output array - $output_info[] = $this->addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, 'NOT CREATED/UPDATED', 'CUSTOMER AND TAG ALREADY EXIST', $cust_id); - } - - $this->em->flush(); - } - } + + // process row + $output_info[] = $this->processRow($fields, $promo_tag); $row_num++; } @@ -240,17 +170,32 @@ class ImportCarClubCustomerDataCommand extends Command return 0; } - protected function findCustomerByNumber($number) + protected function setOutputInfo($fields, $status, $reason, $cust_id) { - $customer = $this->em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $number]); - return $customer; - } + $timestamp = trim($fields[self::F_TIMESTAMP]); + $mname = trim($fields[self::F_MIDDLE_NAME]); + $birthdate = trim($fields[self::F_BIRTHDATE]); + $address = trim($fields[self::F_ADDRESS]); + $city = trim($fields[self::F_CITY]); + $region = trim($fields[self::F_REGION]); + $car_club = trim($fields[self::F_CAR_CLUB]); + $position = trim($fields[self::F_POSITION]); + $member_number = trim($fields[self::F_MEMBER_NUM]); + $vehicle = trim($fields[self::F_VEHICLE]); + $vehicle_excel = trim($fields[self::F_VEHICLE_EXCEL]); + $batt_size = trim($fields[self::F_BATT_SIZE]); + $replace_sked = trim($fields[self::F_REPLACE_SKED]); + $dealer_visit = trim($fields[self::F_DEALER_VISIT]); + $bwi_location = trim($fields[self::F_BWI_LOCATION]); + $sap_code = trim($fields[self::F_SAP_CODE]); + $sku = trim($fields[self::F_SKU]); + $qty = trim($fields[self::F_QTY]); + $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]); - protected function addCustomerInfoEntry($timestamp, $dpa, $fname, $mname, $lname, $birthdate, $address, $city, - $region, $car_club, $position, $member_number, $vehicle, $vehicle_excel, $batt_size, $replace_sked, - $dealer_visit, $contact_number, $bwi_location, $sap_code, $sku, $qty, $status, $reason, $cust_id) - { - $output_entry = [ + return [ $timestamp, $dpa, $fname, @@ -277,8 +222,106 @@ class ImportCarClubCustomerDataCommand extends Command $reason, $cust_id ]; + } - return $output_entry; + 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); + + // NOTE: commenting this out because we want to add customers without mobile number + /* + // QUESTION: do we need this? + // QUESTION: why are we not adding those without contact numbers? Add customer, leave contact number blank was what was agreed, right? + if (count($valid_contact_numbers) <= 0) + { + // add info to output array + return $this->setOutputInfo($fields, 'NOT CREATED', 'Missing contact number', 0); + } + */ + + // 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) From 3d89199fd88342646bd2b8260b85ce5ede266b6d Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 1 Jun 2021 03:06:30 +0000 Subject: [PATCH 7/7] Improve flow for cleaning contact numbers. #572 --- .../ImportCarClubCustomerDataCommand.php | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/Command/ImportCarClubCustomerDataCommand.php b/src/Command/ImportCarClubCustomerDataCommand.php index 7cda2676..49ef7679 100644 --- a/src/Command/ImportCarClubCustomerDataCommand.php +++ b/src/Command/ImportCarClubCustomerDataCommand.php @@ -83,40 +83,13 @@ class ImportCarClubCustomerDataCommand extends Command { $c_num = trim($contact_num); - // remove any non digit character from string - $clean_number = preg_replace('~\D~', '', $c_num); - error_log('cleaned ' . $clean_number); - - // QUESTION: why are these all ifs and not else ifs? - - // 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"); - } - - // does it fit our 63XXXXXXXXXX pattern? - if (preg_match('/^63[0-9]{10}$/', $clean_number)) - { - // remove the 63 - $clean_number = substr($clean_number, 2); - error_log("CONVERTED TO $clean_number"); - } - - // does it fit our 9XXXXXXXXX pattern? - if (!preg_match('/^9[0-9]{9}$/', $clean_number)) - { - error_log('not a mobile number'); - // set clean_number to blank since we don't save a non-mobile number - $clean_number = ''; - } + // clean the numbers + $cleaned_number = $this->normalizeContactNumber($c_num); // not a blank, save it - if ($clean_number != '') + if ($cleaned_number != '') { - $clean_nums[] = $clean_number; + $clean_nums[] = $cleaned_number; } } @@ -428,4 +401,36 @@ class ImportCarClubCustomerDataCommand extends Command 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 ""; + } }