diff --git a/.env.dist b/.env.dist index ca93d2d2..f170c3c9 100644 --- a/.env.dist +++ b/.env.dist @@ -45,3 +45,8 @@ OTP_MODE=settotestorrandom # geofence GEOFENCE_ENABLE=settotrueorfalse + +# unknown manufacturer and vehicle ids +CVU_MFG_ID=insertmfgidforunknownvehicles +CVU_BRAND_ID=insertbrandidforunknownvehicles + diff --git a/composer.json b/composer.json index 6c67a564..e118abfc 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "catalyst/menu-bundle": "dev-master", "creof/doctrine2-spatial": "^1.2", "data-dog/audit-bundle": "^0.1.10", + "edwinhoksberg/php-fcm": "^1.0", "guzzlehttp/guzzle": "^6.3", "predis/predis": "^1.1", "sensio/framework-extra-bundle": "^5.1", diff --git a/composer.lock b/composer.lock index 54f7abba..b3630199 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "ef9a215401e1fec51336e1d6a9df52d9", + "content-hash": "4873ae3fd18db755bc9bf395bbbfb141", "packages": [ { "name": "catalyst/auth-bundle", @@ -1564,6 +1564,55 @@ ], "time": "2018-06-14T14:45:07+00:00" }, + { + "name": "edwinhoksberg/php-fcm", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/EdwinHoksberg/php-fcm.git", + "reference": "7be637139fe54ec23f37c8dba519bafa7543e336" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/EdwinHoksberg/php-fcm/zipball/7be637139fe54ec23f37c8dba519bafa7543e336", + "reference": "7be637139fe54ec23f37c8dba519bafa7543e336", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.3", + "php": ">= 7.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fcm\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Edwin Hoksberg", + "email": "mail@edwinhoksberg.nl" + } + ], + "description": "A library for sending Firebase cloud messages and managing user topic subscriptions, device groups and devices.", + "homepage": "https://github.com/EdwinHoksberg/php-fcm", + "keywords": [ + "FCM", + "Firebase Cloud Messaging", + "firebase", + "google", + "notifications" + ], + "time": "2018-04-09T19:32:41+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", diff --git a/src/Command/CreateCustomerFromWarrantyCommand.php b/src/Command/CreateCustomerFromWarrantyCommand.php new file mode 100644 index 00000000..9d24fc03 --- /dev/null +++ b/src/Command/CreateCustomerFromWarrantyCommand.php @@ -0,0 +1,464 @@ +em = $em; + + // get the default ids from .env + // TODO: DO NOT USE $_ENV + $dotenv = new Dotenv(); + $dotenv->loadEnv(__DIR__.'/../../.env'); + + $this->cvu_mfg_id = $_ENV['CVU_MFG_ID']; + $this->cvu_brand_id = $_ENV['CVU_BRAND_ID']; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('customer:createfromwarranty') + ->setDescription('Create customers from existing warranties.') + ->setHelp('Creates customers from existing warranties.') + ->addArgument('file', InputArgument::REQUIRED, 'Path to the output CSV file with the warranties.'); + } + + 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.'); + } + + // counters for warranties, customers, customer vehicles + $total_warr = 0; + $total_inv_warr = 0; + $total_cust_added = 0; + $total_cv_added = 0; + + + /* + // load all customers + $output->writeln('Loading customer data...'); + $this->loadCustomers($output); + */ + + + // get all warranties + error_log('Getting warranties...'); + $warr_q = $this->em->createQuery('select w from App\Entity\Warranty w where w.mobile_number is not null'); + $warranties = $warr_q->iterate(); + // $warranties = $warr_q->getResult(); + // $warranties = $this->em->getRepository(Warranty::class)->findAll(); + + //$invalid_warranties = []; + // $warr_count = count($warranties); + $created_objs = []; + $output->writeln("Processing warranties... "); + foreach($warranties as $row) + { + $warr = $row[0]; + + $total_warr++; + // check if warranty mobile already exists in customer + $w_mobile = $warr->getMobileNumber(); + if (empty($w_mobile)) + { + // TODO: for now, if warranty mobile number is empty, add to list of invalid entries + //$invalid_warranties[] = $this->processInvalidEntries($warr); + continue; + } + + // parse warranty mobile in case of multiple numbers + // check for spaces, slash, and forward slash + $w_mobile_array = []; + if (preg_match('/[\\\s\/]/', $w_mobile)) + { + $w_mobile_array = preg_split('/[\\\s\/]/', $w_mobile); + } + else + { + // only one mobile number + $w_mobile_array[] = $w_mobile; + } + + // set values for new customer vehicle + $w_plate_number = $this->cleanPlateNumber($warr->getPlateNumber()); + + $cust_found = false; + foreach ($w_mobile_array as $w_mobile_num) + { + $w_mobile_num = trim($w_mobile_num); + + // empty mobile num + if (empty($w_mobile_num)) + continue; + + // does it fit our 09XXXXXXXXX pattern? + if (preg_match('/^09[0-9]{9}$/', $w_mobile_num)) + { + // remove first '0' + $w_mobile_num = substr($w_mobile_num, 1); + error_log("CONVERTED TO $w_mobile_num"); + } + + // does it fit our 9XXXXXXXXX pattern? + if (!preg_match('/^9[0-9]{9}$/', $w_mobile_num)) + continue; + + /* + // min length 2 + // TODO: we need to check proper phone number format + // format should be '9XXXXXXXXX' + // TODO: if format doesn't fit and there's a 0 or 63 prefix, we should be able to detect and convert + if (strlen($w_mobile_num <= 2)) + continue; + */ + + error_log(''); + error_log("($total_warr) processing $w_mobile_num from warranty..."); + + $customers = $this->findCustomerByNumber($w_mobile_num); + + if (!empty($customers)) + { + error_log('found customer for ' . $w_mobile_num); + foreach ($customers as $customer) + { + // get customer vehicles for customer + $c_vehicles = $customer->getVehicles(); + + $cv_found = false; + if (!empty($c_vehicles)) + { + // check if plate number of customer vehicle matches warranty plate number + foreach ($c_vehicles as $c_vehicle) + { + $clean_cv_plate = $this->cleanPlateNumber($c_vehicle->getPlateNumber()); + + // check if it's already there + if ($clean_cv_plate == $w_plate_number) + { + // customer and customer vehicle already exists + $cv_found = true; + break; + } + } + + } + + // if there was a customer vehicle matched + if ($cv_found) + { + // vehicle found, do nothing. + error_log('vehicle found - ' . $w_plate_number); + $created_objs[] = $this->createReportData($warr, self::CV_FOUND); + } + else + { + // customer exists but not customer vehicle + // add customer vehicle to existing customer with unknown manufacturer and make + error_log('new vehicle - ' . $w_plate_number); + $this->createCustomerVehicle($customer, $this->getDefaultVehicle(), $w_plate_number); + $created_objs[] = $this->createReportData($warr, self::CV_NEW); + $total_cv_added++; + } + } + } + // customer not found + else + { + error_log('NEW customer and vehicle - ' . $w_plate_number); + // customer not found, add customer and customer vehicle + // get warranty first name, last name + $w_first_name = $warr->getFirstName(); + $w_last_name = $warr->getLastName(); + + //$output->writeln($w_first_name); + //$output->writeln($w_last_name); + //$output->writeln($w_plate_number); + + $new_cust = new Customer(); + $new_cust->setFirstName($w_first_name) + ->setLastName($w_last_name) + ->setPhoneMobile($w_mobile_num); + + $this->em->persist($new_cust); + + $this->createCustomerVehicle($new_cust, $this->getDefaultVehicle(), $w_plate_number); + + $created_objs[] = $this->createReportData($warr, self::CUST_NEW); + + // add latest customer to hash + //$this->cust_index[$w_mobile_num][] = $new_cust; + + $total_cust_added++; + $total_cv_added++; + } + } + $this->em->flush(); + $this->em->clear(); + } + + /* + // process invalid warranties, if any + if (count($invalid_warranties) > 0) + { + fputcsv($fh, [ + 'ID', + 'Serial', + 'Warranty Class', + 'Last Name', + 'First Name', + 'Mobile Number', + 'Plate Number', + 'Battery Model', + 'Battery Size', + 'SAP Battery', + 'Status', + 'Date Created', + 'Date Purchased', + 'Expiry Date', + 'Date Claimed', + 'Claimed From', + 'Privacy Policy', + ]); + + foreach($invalid_warranties as $row) + { + $total_inv_warr++; + fputcsv($fh, $row); + } + } + */ + + // process the report data + if (count($created_objs) > 0) + { + fputcsv($fh, [ + 'ID', + 'Mobile Number', + 'Plate Number', + 'Action Done', + ]); + + foreach($created_objs as $row) + { + fputcsv($fh, $row); + } + } + + fclose($fh); + + $output->writeln(''); + $output->writeln('Total warranties: ' . $total_warr); + //$output->writeln('Total warranties with no mobile number: ' . $total_inv_warr); + $output->writeln('Total customers added: ' . $total_cust_added); + $output->writeln('Total customer vehicles added: ' . $total_cv_added); + } + + protected function getDefaultVehicle() + { + // get default vehicle + $default_vehicle = $this->em->getRepository(Vehicle::class)->find($this->cvu_brand_id); + if ($default_vehicle == null) + { + $output->writeln("Need to add vehicle with default values."); + return null; + } + + return $default_vehicle; + } + + protected function findCustomerByNumber($number) + { + $customers = $this->em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]); + return $customers; + } + + protected function loadCustomers() + { + error_log('starting query...'); + // get all customers + $customers = $this->em->getRepository(Customer::class)->findAll(); + $cust_q = $this->em->createQuery('select c from App\Entity\Customer c'); + $cust_iter = $q->iterate(); + + error_log('looping through query...'); + $this->cust_index = []; + foreach ($cust_iter as $customer) + { + error_log('here'); + $mobile = trim($customer->getPhoneMobile()); + if (!empty($mobile)) + { + $mobile_array = []; + // need to check if multiple numbers in mobile + if (preg_match('/[\\\s\/]/', $mobile)) + { + $mobile_array = preg_split('/[\\\s\/]/', $mobile); + } + else + { + // only one mobile number + $mobile_array[] = $mobile; + } + + foreach($mobile_array as $number) + { + if (!(empty($number))) + { + if (!isset($this->cust_index[$number])) + $this->cust_index[$number] = []; + $this->cust_index[$number][] = $customer; + } + } + } + } + } + + protected function createCustomerVehicle(Customer $cust, $vehicle, $plate_number) + { + $new_cv = new CustomerVehicle(); + + $new_cv->setCustomer($cust) + ->setPlateNumber($plate_number) + ->setStatusCondition(VehicleStatusCondition::BRAND_NEW) + ->setModelYear('') + ->setColor('') + ->setFuelType(FuelType::GAS) + ->setHasMotoliteBattery(true) + ->setVehicle($vehicle); + + $this->em->persist($new_cv); + } + + protected function createReportData($warr, $action) + { + $obj = [ + 'id' => $warr->getID(), + 'mobile_number' => $warr->getMobileNumber(), + 'plate_number' => $warr->getPlateNumber(), + 'action_done' => $action, + ]; + + return $obj; + + } + + protected function processInvalidEntries($warr) + { + $batt_model = ''; + $batt_size = ''; + $sap_batt = ''; + $policy = ''; + $date_purchased = ''; + $date_expire = ''; + $date_claim = ''; + + $create_date = $warr->getDateCreate(); + $date_create = $create_date->format('d/M/y'); + + if ($warr->getDatePurchase() != null) + { + $p_date = $warr->getDatePurchase(); + $date_purchased = $p_date->format('d/M/y'); + } + if ($warr->getDateClaim() != null) + { + $c_date = $warr->getDateClaim(); + $date_claim = $c_date->format('d/M/y'); + } + if ($warr->getDateExpire() != null) + { + $e_date = $warr->getDateExpire(); + $date_expire = $e_date->format('d/M/y'); + } + + if ($warr->getBatteryModel() != null) + { + $batt_model = $warr->getBatteryModel()->getName(); + } + if ($warr->getBatterySize() != null) + { + $batt_size = $warr->getBatterySize()->getName(); + } + if ($warr->getSAPBattery() != null) + { + $sap_batt = $warr->getSAPBattery()->getBrand()->getName(); + } + if ($warr->getPrivacyPolicy() != null) + { + $policy = $warr->getPrivacyPolicy()->getName(); + } + + $invalid_warranty = [ + 'id' => $warr->getID(), + 'serial' => $warr->getSerial(), + 'warranty_class' => $warr->getWarrantyClass(), + 'last_name' => $warr->getLastName(), + 'first_name' => $warr->getFirstName(), + 'mobile_number' => $warr->getMobileNumber(), + 'plate_number' => $warr->getPlateNumber(), + 'battery_model' => $batt_model, + 'battery_size' => $batt_size, + 'sap_battery' => $sap_batt, + 'status' => $warr->getStatus(), + 'date_create' => $date_create, + 'date_purchase' => $date_purchased, + 'date_expire' => $date_expire, + 'date_claim' => $date_claim, + 'claimed_from' => $warr->getClaimedFrom(), + 'privacy_policy' => $policy, + ]; + + return $invalid_warranty; + } + + protected function cleanPlateNumber($plate) + { + // remove spaces and make upper case + return strtoupper(str_replace(' ', '', $plate)); + } +} diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 75dcb9d0..0b360d9c 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -334,6 +334,7 @@ class APIController extends Controller // TODO: check if we have the number registered before and merge + // TODO: check if mobile matches mobile of customer $dupe_sess = $this->findNumberSession($this->session->getPhoneNumber()); if ($dupe_sess != null) { diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index 61b0c392..880f0213 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -10,7 +10,7 @@ use App\Ramcar\CustomerClassification; /** * @ORM\Entity - * @ORM\Table(name="customer") + * @ORM\Table(name="customer", indexes={@ORM\Index(name="phone_mobile_idx", columns={"phone_mobile"})}) */ class Customer { diff --git a/src/Entity/CustomerVehicle.php b/src/Entity/CustomerVehicle.php index 841f7b16..5f1f1031 100644 --- a/src/Entity/CustomerVehicle.php +++ b/src/Entity/CustomerVehicle.php @@ -54,14 +54,12 @@ class CustomerVehicle // model year /** * @ORM\Column(type="smallint") - * @Assert\NotBlank() */ protected $model_year; // color of customer's vehicle /** * @ORM\Column(type="string", length=80) - * @Assert\NotBlank() */ protected $color; diff --git a/symfony.lock b/symfony.lock index 81b878d9..88d10d33 100644 --- a/symfony.lock +++ b/symfony.lock @@ -98,6 +98,9 @@ "doctrine/reflection": { "version": "v1.0.0" }, + "edwinhoksberg/php-fcm": { + "version": "1.0.0" + }, "guzzlehttp/guzzle": { "version": "6.3.0" }, diff --git a/utils/fcm_sender/file_send.php b/utils/fcm_sender/file_send.php new file mode 100644 index 00000000..e413a8df --- /dev/null +++ b/utils/fcm_sender/file_send.php @@ -0,0 +1,23 @@ +addRecipient($device_id) + ->setTitle('Motolite RES-Q') + ->setBody('Test notification sending') + +// Send the notification to the Firebase servers for further handling. +$client->send($notification);