em = $em; $this->loadCustomerTags(); parent::__construct(); } protected function configure() { $this->setName('customer:importcarclubhub') ->setDescription('Import assigned hubs for customers for car club.') ->setHelp('Import assigned hubs for customers for car club.') ->addArgument('promo_tag', InputArgument::REQUIRED, 'Promo customer tag ID to use.') ->addArgument('input_file', InputArgument::REQUIRED, 'Path to the input CSV file with the customer and hub info.') ->addArgument('output_file', InputArgument::REQUIRED, 'Output filename'); } 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->outputCarClubCustomerHubInfo($output_file, $output_info); fclose($fh); return 0; } protected function processRow($fields, $promo_tag) { $contact_number = trim($fields[SELF::F_CONTACT_NUMBER]); $car_club = trim($fields[self::F_CAR_CLUB]); if (empty($contact_number)) { // add info to output array return $this->setOutputInfo($fields, 'NOT ADDED', 'No mobile number', ''); } $hub_name = trim($fields[SELF::F_HUB_NAME]); // find hub using name $hub = $this->findHubByName($hub_name); if ($hub == null) { // add info to output array return $this->setOutputInfo($fields, 'NOT ADDED', 'No hub found', ''); } // clean up contact number $valid_contact_numbers = $this->getValidContactNumbers($contact_number); // check customer tag $cust_tag = $this->findCustomerTag($car_club); $cust_id = ''; // get first customer that matches any of the numbers $customer = $this->findCustomerByNumbers($valid_contact_numbers); // if no customer found, create one and add the hub if ($customer == null) { error_log('Creating customer...'); // 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(); // create the carclubcustomerhub $this->createCarClubCustomerHub($fields, $new_cust, $hub); // add info to output array return $this->setOutputInfo($fields, 'CUSTOMER CREATED AND CUSTOMER HUB ADDED', '', $cust_id); } //customer exists, we just need to add the hub and the promo tag // NOTE: for now, we add the promo tag and the hub // to the first customer found with the mobile number $customer->addCustomerTag($promo_tag) ->addCustomerTag($cust_tag); // create the carclubcustomerhub $this->createCarClubCustomerHub($fields, $customer, $hub); return $this->setOutputInfo($fields, 'CUSTOMER HUB ADDED', '', $customer->getID()); } protected function createCarClubCustomerHub($fields, $cust, $hub) { $car_club_cust_hub = new CarClubCustomerHub(); $car_club_cust_hub->setHub($hub); $cust->setCarClubCustomerHub($car_club_cust_hub); $this->em->persist($car_club_cust_hub); $this->em->flush(); } protected function createNewCustomer($fields, $contact_numbers, $cust_tag, $promo_tag) { $fname = trim($fields[self::F_FIRST_NAME]); $lname = trim($fields[self::F_LAST_NAME]); if (count($contact_numbers) > 0) $clean_number = $contact_numbers[0]; else $clean_number = ''; // create new customer $new_cust = new Customer(); $new_cust->setFirstName($fname) ->setLastName($lname) ->setPhoneMobile($clean_number) ->setCreateSource('car_club_file') ->addCustomerTag($cust_tag) ->addCustomerTag($promo_tag); $this->em->persist($new_cust); $this->em->flush(); return $new_cust; } protected function setOutputInfo($fields, $status, $reason, $cust_id) { $hub_name = trim($fields[SELF::F_HUB_NAME]); $hub_address = trim($fields[SELF::F_HUB_ADDRESS]); $car_club_name = trim($fields[SELF::F_CAR_CLUB]); $first_name = trim($fields[self::F_FIRST_NAME]); $last_name = trim($fields[self::F_LAST_NAME]); $contact_number = trim($fields[SELF::F_CONTACT_NUMBER]); $battery_size = trim($fields[SELF::F_BATT_SIZE]); $serial = trim($fields[SELF::F_SERIAL]); return [ $hub_name, $hub_address, $car_club_name, $first_name, $last_name, $contact_number, $battery_size, $serial, $status, $reason, $cust_id ]; } protected function outputCarClubCustomerHubInfo($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, [ 'Hub Name', 'Hub Address', 'Car Club Name', 'First Name', 'Last Name', 'Contact Number', 'Battery Size', 'Serial', 'Status', 'Reason', 'Customer ID', ]); foreach($entries as $row) { fputcsv($fh, $row); } fclose($fh); } protected function findCustomerByNumbers($numbers) { error_log(print_r($numbers, true)); $customer = $this->em->getRepository(Customer::class)->findOneBy(['phone_mobile' => $numbers]); return $customer; } protected function findHubByName($hub_name) { $hname = strtoupper($hub_name); $hub = $this->em->getRepository(Hub::class)->findOneBy(['name' => $hname]); return $hub; } 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 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; } // collect 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 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 ""; } 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; } }