Compare commits

...

52 commits

Author SHA1 Message Date
081df6e996 Merge branch '270-final-cmb-fixes' of gitlab.com:jankstudio/resq into 296-cmb-redis-geo-cache
Conflicts:
	config/services.yaml
2020-01-12 21:01:48 +08:00
bcaa7bf982 Merge branch '291-vehicle-battery-compatibility-report' into 'master'
Add battery sap code to report. #291

Closes #291

See merge request jankstudio/resq!336
2020-01-09 08:32:17 +00:00
Korina Cordero
b4f1cbfcf0 Add battery sap code to report. #291 2020-01-09 08:31:03 +00:00
0cbd100f27 Merge branch '291-vehicle-battery-compatibility-report' into 'master'
Resolve "Vehicle Battery Compatibility Report"

Closes #291

See merge request jankstudio/resq!335
2020-01-08 03:53:11 +00:00
Korina Cordero
380bb23e25 Add model year from and model year to to report. #291 2020-01-08 01:35:59 +00:00
Korina Cordero
f74b8cff88 Add sql query to get vehicle battery compatibility data. #291 2020-01-07 10:15:53 +00:00
Korina Cordero
16763c5386 Add vehicle battery compatibility report. #291 2020-01-07 08:36:00 +00:00
ec5b8951da Merge branch '281-create-customers-via-third-party-api' into 'master'
Resolve "Create customers via third party API"

Closes #281

See merge request jankstudio/resq!327
2019-11-28 06:52:20 +00:00
4621fa5ec4 Merge branch '275-remove-env-implementation' into 'master'
Resolve "Remove ENV implementation"

Closes #275

See merge request jankstudio/resq!323
2019-11-28 06:51:15 +00:00
fbd96d1296 Merge branch '283-warranty-class-report' into 'master'
Resolve "Warranty Class Report"

Closes #283

See merge request jankstudio/resq!328
2019-11-28 05:45:37 +00:00
Korina Cordero
28b93a83d0 Add index for plate number in warranty. Finish warranty class report. #283 2019-11-28 05:20:29 +00:00
Korina Cordero
743bbf9c61 Add warranty class report to yaml files, templates and ReportController. #283 2019-11-27 08:04:42 +00:00
Korina Cordero
8921f2442b Add prefix for vehicle data. #281 2019-11-27 03:37:42 +00:00
Korina Cordero
2a45de2b31 Rename the path for customer registration. #281 2019-11-27 03:27:53 +00:00
Korina Cordero
16cd59dbfd Add route to register customer. Finish register function. #281 2019-11-27 03:23:39 +00:00
Korina Cordero
9efc0e3a75 Add CustomerController to CAPI. #281 2019-11-26 07:53:31 +00:00
50cb1d8617 Merge branch '277-apicontroller-changes-to-handle-duplicate-customer-mobile-numbers' into 'master'
Resolve "APIController changes to handle duplicate customer mobile numbers"

Closes #277

See merge request jankstudio/resq!322
2019-11-26 05:47:25 +00:00
Korina Cordero
336d29ad34 Merge branch 'master' of gitlab.com:jankstudio/resq into 275-remove-env-implementation 2019-11-25 07:00:50 +00:00
0c5a4c40bc Merge branch '278-optimize-pop-app-report' into 'master'
Resolve "Optimize pop app report"

Closes #278

See merge request jankstudio/resq!324
2019-11-25 06:14:32 +00:00
Korina Cordero
7e5ffdcf26 Add index for plate number. #278 2019-11-25 03:21:50 +00:00
Korina Cordero
0372dc5a5a Remove dotenv implementation from customer creation from warranty. #275 2019-11-22 04:01:54 +00:00
Korina Cordero
e462570d9d Remove dotenv implementation from setting of customer privacy policy. #275 2019-11-22 03:27:16 +00:00
Korina Cordero
bf86a46082 Fix for errors found during testing. #277 2019-11-21 08:03:33 +00:00
Korina Cordero
0adffd92d7 Add checking if mobile session belongs to an existing customer. #277 2019-11-21 06:16:31 +00:00
Korina Cordero
3babcd765f Merge branch '274-create-customer-from-existing-warranties' into 'master'
Resolve "Command to create customer from existing warranties"

Closes #274

See merge request jankstudio/resq!321
2019-11-21 05:22:44 +00:00
Korina Cordero
f914fce20f Add report of added customers and customer vehicles as output. #274 2019-11-21 02:39:31 +00:00
2b21db6c01 Filter valid phone numbers and convert the 09XXXXXXXXX format to 9XXXXXXXXX #274 2019-11-21 10:20:07 +08:00
fba5d9cb86 Add method for getting default vehicle because of em->clear #274 2019-11-21 09:27:35 +08:00
9a4ead6ab9 Return the customer and customer vehicle saving #274 2019-11-21 09:18:31 +08:00
575bf21639 Fix blank phone number issue #274 2019-11-21 09:10:58 +08:00
142e34ba31 Refactor to use bulk processing best practice based on doctrine docs #274
Reference: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/batch-processing.html
2019-11-21 08:53:48 +08:00
d094b5e8d9 Refactor create customer from warranty command #274 2019-11-21 00:02:44 +08:00
Korina Cordero
737dd4e22a Add ids to env.dist. #274 2019-11-20 11:36:56 +00:00
Korina Cordero
98c5bdc670 Add clean plate number function. #274 2019-11-20 08:41:27 +00:00
Korina Cordero
041d5b408b Modify the customer hash. #274 2019-11-20 08:00:12 +00:00
Korina Cordero
9b0bd63723 Add csv file for warranties that have no phone number. #274 2019-11-20 06:40:37 +00:00
Korina Cordero
a8f069781d Fix issues found during testing. #274 2019-11-20 03:53:34 +00:00
Korina Cordero
6bde277fef Fix syntax errors. #274 2019-11-20 02:01:41 +00:00
Korina Cordero
515bb84c13 Remove Assert NotBlank from color and model year. #274 2019-11-20 01:40:07 +00:00
Korina Cordero
9c4db034d0 Add command to create customer and customer vehicle from warranty. #274 2019-11-19 08:35:58 +00:00
Korina Cordero
4c5733f891 Merge branch '258-upload-warranty-csv' into 'master'
Add reason for invalid warranty. #258

Closes #258

See merge request jankstudio/resq!320
2019-11-18 04:43:50 +00:00
Korina Cordero
0d60fe1a9d Add reason for invalid warranty. #258 2019-11-18 04:42:55 +00:00
Korina Cordero
11b60c8655 Merge branch '258-upload-warranty-csv' into 'master'
Resolve "Upload warranty csv"

Closes #258

See merge request jankstudio/resq!305
2019-11-18 03:10:07 +00:00
71350c2e20 Merge branch '273-popapp-comparison-report-private-or-commercial' into 'master'
Add warranty class to popapp comparison report #273

Closes #273

See merge request jankstudio/resq!319
2019-11-15 01:17:20 +00:00
a55d093dce Add warranty class to popapp comparison report #273 2019-11-15 09:16:30 +08:00
2c606b7a13 Merge branch '271-fix-geofence-issue' into 'master'
Resolve "Fix geofence issue"

Closes #271

See merge request jankstudio/resq!318
2019-10-23 06:05:11 +00:00
Korina Cordero
ed0486fbf5 Improve geofence error message. #271 2019-10-23 05:58:05 +00:00
Korina Cordero
f6dce241ac Move retrieval of env variable to the geofence service. #271 2019-10-23 05:30:12 +00:00
Korina Cordero
e169766efd Modify the error message if delivery is not in the coverage areas. #271 2019-10-22 07:14:30 +00:00
Korina Cordero
590b9b82b4 Add geofence variable to env.dist. Add checking to APIController if geofence is on or not. #271 2019-10-22 07:14:15 +00:00
Korina Cordero
dbee60bf46 Include invalid plate numbers in warranty. Return a csv file with the invalid entries that cannot be inserted into the database. #258 2019-08-29 10:48:08 +00:00
Korina Cordero
33e0e6b41b Add route and access for warranty upload. Add method to WarrantyController to handle the upload. Add template for warranty upload. #258 2019-08-29 07:26:11 +00:00
32 changed files with 1986 additions and 88 deletions

View file

@ -42,3 +42,11 @@ POLICY_MOBILE=insertmobilepolicyidhere
# OTP
OTP_MODE=settotestorrandom
# geofence
GEOFENCE_ENABLE=settotrueorfalse
# unknown manufacturer and vehicle ids
CVU_MFG_ID=insertmfgidforunknownvehicles
CVU_BRAND_ID=insertbrandidforunknownvehicles

View file

@ -41,7 +41,6 @@ class TestAPICommand extends Command
// TODO: shift this out of the bundle, since it's project specific
// warranty register
$serial = 'AJ34LJADR12134LKJL5';
$plate_num = 'XEN918';
@ -119,5 +118,19 @@ class TestAPICommand extends Command
// privacy policy
$privacy_policy_id = 2;
$api->get('/capi/privacy_policy/' . $privacy_policy_id );
// register new customer
$params = [
'first_name' => 'Krispups',
'last_name' =>'Porzindog',
'mobile_number' => '9221111111',
'v_make_id' => '22241',
'v_model_year' => '2018',
'v_plate_number' => 'KPP1234',
'v_color' => 'White',
'v_condition' => 'new',
'v_fuel_type' => 'gas',
];
$api->post('/capi/quick_registration', $params);
}
}

View file

@ -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",

53
composer.lock generated
View file

@ -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",

View file

@ -254,6 +254,8 @@ access_keys:
label: Search
- id: warranty.search
label: Customer Battery Search
- id: warranty.upload
label: Warranty Upload
- id: ticket
label: Ticket Access
@ -296,6 +298,10 @@ access_keys:
label: Popapp Comparison Report
- id: report.meh.customer
label: RESQ MEH Customer Report
- id: report.warranty.class
label: Warranty Class Report
- id: report.vehicle.battery.compatibility
label: Vehicle Battery Compatibility Report
- id: service
label: Other Services

View file

@ -50,3 +50,8 @@ access_keys:
acls:
- id: privacypolicy.find
label: Find Privacy Policy
- id: customer
label: Customer
acls:
- id: customer.register
label: Register Customer

View file

@ -155,6 +155,10 @@ main_menu:
acl: warranty.list
label: Warranty
parent: support
- id: warranty_upload
acl: warranty.upload
label: Warranty Upload
parent: support
- id: service
acl: service.menu

View file

@ -18,6 +18,7 @@ doctrine:
geometry: CrEOF\Spatial\DBAL\Types\GeometryType
point: CrEOF\Spatial\DBAL\Types\Geometry\PointType
polygon: CrEOF\Spatial\DBAL\Types\Geometry\PolygonType
multipolygon: CrEOF\Spatial\DBAL\Types\Geometry\MultiPolygonType
linestring: CrEOF\Spatial\DBAL\Types\Geometry\LineStringType
orm:
auto_generate_proxy_classes: '%kernel.debug%'

View file

@ -135,3 +135,11 @@ capi_privacy_policy:
path: /capi/privacy_policy/{id}
controller: App\Controller\CAPI\PrivacyPolicyController::getPrivacyPolicy
methods: [GET]
# customer
# register customer and customer vehicle
capi_customer_register:
path: /capi/quick_registration
controller: App\Controller\CAPI\CustomerController::register
methods: [POST]

View file

@ -47,3 +47,23 @@ rep_resq_meh_export_csv:
path: /report/meh_customer_export
controller: App\Controller\ReportController::mehCustomerExportCSV
methods: [POST]
rep_warranty_class_form:
path: /report/warranty_class_report
controller: App\Controller\ReportController::warrantyClassForm
methods: [GET]
rep_warranty_class_export_csv:
path: /report/warranty_class_report
controller: App\Controller\ReportController::warrantyClassExportCSV
methods: [POST]
rep_vehicle_battery_compatibility_form:
path: /report/vehicle_battery_compatibility_report
controller: App\Controller\ReportController::vehicleBatteryCompatibilityForm
methods: [GET]
rep_vehicle_battery_compatibility_export_csv:
path: /report/vehicle_battery_compatibility_report
controller: App\Controller\ReportController::vehicleBatteryCompatibilityExportCSV
methods: [POST]

View file

@ -28,3 +28,13 @@ warranty_update_submit:
path: /warranties/{id}
controller: App\Controller\WarrantyController::updateSubmit
methods: [POST]
warranty_upload:
path: /warranty/upload
controller: App\Controller\WarrantyController::uploadForm
methods: [GET]
warranty_upload_submit:
path: /warranty/upload
controller: App\Controller\WarrantyController::uploadSubmit
methods: [POST]

View file

@ -87,6 +87,21 @@ services:
$password: "%env(REDIS_CLIENT_PASSWORD)%"
$env_flag: "dev"
App\Service\GeofenceTracker:
arguments:
$geofence_flag: "%env(GEOFENCE_ENABLE)%"
App\Command\SetCustomerPrivacyPolicyCommand:
arguments:
$policy_promo: "%env(POLICY_PROMO)%"
$policy_third_party: "%env(POLICY_THIRD_PARTY)%"
$policy_mobile: "%env(POLICY_MOBILE)%"
App\Command\CreateCustomerFromWarrantyCommand:
arguments:
$cvu_mfg_id: "%env(CVU_MFG_ID)%"
$cvu_brand_id: "%env(CVU_BRAND_ID)%"
# rider tracker service
App\Service\RiderTracker:
arguments:

View file

@ -0,0 +1,459 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Dotenv\Dotenv;
use Doctrine\Common\Persistence\ObjectManager;
use App\Entity\Warranty;
use App\Entity\Customer;
use App\Entity\CustomerVehicle;
use App\Entity\VehicleManufacturer;
use App\Entity\Vehicle;
use App\Ramcar\FuelType;
use App\Ramcar\VehicleStatusCondition;
use DateTime;
class CreateCustomerFromWarrantyCommand extends Command
{
const CV_FOUND = 'Vehicle found';
const CV_NEW = 'New vehicle';
const CUST_NEW = 'New customer and vehicle.';
protected $em;
protected $cust_index;
protected $cvu_mfg_id;
protected $cvu_brand_id;
public function __construct(ObjectManager $em, $cvu_mfg_id, $cvu_brand_id)
{
$this->em = $em;
$this->cvu_mfg_id = $cvu_mfg_id;
$this->cvu_brand_id = $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));
}
}

View file

@ -0,0 +1,70 @@
<?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 CrEOF\Spatial\PHP\Types\Geometry\Polygon;
use CrEOF\Spatial\PHP\Types\Geometry\MultiPolygon;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
use CrEOF\Spatial\PHP\Types\Geometry\LineString;
use App\Entity\GeoCity;
class DetectCity extends Command
{
protected $em;
protected $query;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->query = $this->em->createQuery('SELECT gc.name from App\Entity\GeoCity gc where st_contains(gc.area, point(:long, :lat)) = true');
parent::__construct();
}
protected function configure()
{
$this->setName('geocity:detect')
->setDescription('Detect what city the long / lat falls under in the CSV file.')
->setHelp('Detect what city the long / lat falls under in the CSV file.')
->addArgument('file', InputArgument::REQUIRED, 'Path to the CSV file')
->addArgument('output', InputArgument::REQUIRED, 'Output CSV file');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = $input->getArgument('file');
$outfile = $input->getArgument('output');
$fh = fopen($file, 'r');
$out_fh = fopen($outfile, 'w');
while ($line = fgetcsv($fh))
{
$point = new Point($line[1], $line[0]);
$city_name = $this->detectCity($point);
fputcsv($out_fh, [$line[0], $line[1], $city_name]);
}
fclose($fh);
fclose($out_fh);
}
protected function detectCity($point)
{
$this->query->setParameter('long', $point->getLongitude())
->setParameter('lat', $point->getLatitude());
$res = $this->query->getResult();
if (count($res) <= 0)
return 'Unknown';
return $res[0]['name'];
}
}

View file

@ -0,0 +1,214 @@
<?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 CrEOF\Spatial\PHP\Types\Geometry\Polygon;
use CrEOF\Spatial\PHP\Types\Geometry\MultiPolygon;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
use CrEOF\Spatial\PHP\Types\Geometry\LineString;
use App\Entity\GeoCity;
class ImportCityKML extends Command
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
parent::__construct();
}
protected function configure()
{
$this->setName('geocity:import')
->setDescription('Import the Philippine cities geojson and store it in the db.')
->setHelp('Import the Philippine cities geojson and store it in the db.')
->addArgument('file', InputArgument::REQUIRED, 'Path to the geojson file');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = $input->getArgument('file');
// import geojson file to GeoCity
$this->importGeojson($file);
}
protected function importGeojson($file)
{
$geodata = json_decode(file_get_contents($file), true);
$batch_count = 0;
foreach ($geodata['features'] as $feat)
{
$geocity = new GeoCity();
$geometry = $feat['geometry'];
$name = $feat['properties']['NAME_2'];
echo "$name\n";
$geocity->setName($name);
switch ($geometry['type'])
{
case 'Polygon':
$point_array = [];
$coords = $geometry['coordinates'][0];
$coords_count = count($coords);
for ($i = 0; $i < $coords_count; $i++)
{
$coord = $coords[$i];
$point_array[] = new Point($coord[0], $coord[1]);
// echo "$coord[0] - $coord[1]\n";
}
$poly = new Polygon([new LineString($point_array)]);
$polygons = [];
$polygons[] = $poly;
$multi_poly = new MultiPolygon($polygons);
$geocity->setArea($multi_poly);
break;
case 'MultiPolygon':
$coords_group = $geometry['coordinates'];
$polygons = [];
foreach ($coords_group as $coords_base)
{
$point_array = [];
$coords = $coords_base[0];
$coords_count = count($coords);
for ($i = 0; $i < $coords_count; $i++)
{
$coord = $coords[$i];
$point_array[] = new Point($coord[0], $coord[1]);
// echo "$coord[0] - $coord[1]\n";
}
$poly = new Polygon([new LineString($point_array)]);
$polygons[] = $poly;
}
$multi_poly = new MultiPolygon($polygons);
$geocity->setArea($multi_poly);
break;
}
// persist
$this->em->persist($geocity);
// check for batch limit
if ($batch_count >= 100)
{
$this->em->flush();
$this->em->clear();
$batch_count = 0;
}
}
// save the remaining ones
$this->em->flush();
$this->em->clear();
/*
while ($reader->read())
{
// echo $reader->nodeType . ' - ' . $reader->name . "\n";
if ($reader->nodeType == XMLReader::ELEMENT)
{
switch ($reader->name)
{
// placemark
case 'Placemark':
$geocity = new GeoCity();
$polygons = [];
echo "***** placemark START *****\n";
break;
// placemark name
case 'name':
if ($eflags['Placemark'])
{
$name = $reader->readInnerXML();
echo "name - $name\n";
$geocity->setName($name);
}
break;
case 'Polygon':
echo "----- polygon START -----\n";
break;
case 'coordinates':
if ($eflags['Placemark'] && $eflags['Polygon'])
{
$coords = $reader->readInnerXML();
$coord_split = preg_split('/\s+/', $coords);
$point_array = [];
foreach ($coord_split as $coord)
{
if (strlen($coord) <= 0)
continue;
// echo "coord - $coord\n";
$point_split = explode(',', $coord);
$point_array[] = new Point($point_split[0], $point_split[1]);
// echo "point - $point_split[0] - $point_split[1]\n";
}
$poly = new Polygon([new LineString($point_array)]);
$polygons[] = $poly;
}
break;
}
// set flag
$eflags[$reader->name] = true;
}
if ($reader->nodeType == XMLReader::END_ELEMENT)
{
switch ($reader->name)
{
case 'Placemark':
$multi_poly = new MultiPolygon($polygons);
$geocity->setArea($multi_poly);
$this->em->persist($geocity);
$batch_count++;
// check if we need to save batch
if ($batch_count >= 100)
{
$this->em->flush();
$this->em->clear();
$batch_count = 0;
}
echo "***** placemark END *****\n";
break;
case 'Polygon':
echo "----- polygon END -----\n";
break;
}
// set flag
$eflags[$reader->name] = false;
}
// if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Placemark")
}
$this->em->flush();
$this->em->clear();
*/
}
}

View file

@ -34,7 +34,7 @@ class ImportPartnersCommand extends Command
protected $em;
public function __construct(Objectmanager $om)
public function __construct(ObjectManager $om)
{
$this->em = $om;

View file

@ -7,7 +7,6 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Dotenv\Dotenv;
use Doctrine\Common\Persistence\ObjectManager;
@ -19,10 +18,19 @@ class SetCustomerPrivacyPolicyCommand extends Command
{
private $em;
public function __construct(ObjectManager $om)
private $policy_promo_id;
private $policy_third_party_id;
private $policy_mobile_id;
public function __construct(ObjectManager $om, $policy_promo,
$policy_third_party, $policy_mobile)
{
$this->em = $om;
$this->policy_promo_id = $policy_promo;
$this->policy_third_party_id = $policy_third_party;
$this->policy_mobile_id = $policy_mobile;
parent::__construct();
}
@ -35,16 +43,8 @@ class SetCustomerPrivacyPolicyCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output)
{
// get the policy ids from .env
$dotenv = new Dotenv();
$dotenv->loadEnv(__DIR__.'/../../.env');
$policy_promo_id = $_ENV['POLICY_PROMO'];
$policy_third_party_id = $_ENV['POLICY_THIRD_PARTY'];
$policy_mobile_id = $_ENV['POLICY_MOBILE'];
// get third party policy
$third_party_policy = $this->em->getRepository(PrivacyPolicy::class)->find($policy_third_party_id);
$third_party_policy = $this->em->getRepository(PrivacyPolicy::class)->find($this->policy_third_party_id);
// get customers on third party
$third_party_customers = $this->em->getRepository(Customer::class)->findBy(['priv_third_party' => true]);
@ -54,7 +54,7 @@ class SetCustomerPrivacyPolicyCommand extends Command
}
// get promo policy
$promo_policy = $this->em->getRepository(PrivacyPolicy::class)->find($policy_promo_id);
$promo_policy = $this->em->getRepository(PrivacyPolicy::class)->find($this->policy_promo_id);
// get customers on promo
$promo_customers = $this->em->getRepository(Customer::class)->findBy(['priv_promo' => true]);
@ -66,7 +66,7 @@ class SetCustomerPrivacyPolicyCommand extends Command
$this->em->flush();
// get mobile policy
$mobile_policy = $this->em->getRepository(PrivacyPolicy::class)->find($policy_mobile_id);
$mobile_policy = $this->em->getRepository(PrivacyPolicy::class)->find($this->policy_mobile_id);
// get mobile sessions
$mobile_sessions = $this->em->getRepository(MobileSession::class)->findAll();

View file

@ -341,6 +341,15 @@ class APIController extends Controller
$this->session->setCustomer($dupe_cust);
}
// TODO: check if mobile matches mobile of customer
$customer = $this->findCustomerByNumber($this->session->getPhoneNumber());
if ($customer != null)
{
// TODO: if there is a dupe_sess, do we need to check if
// dupe_cust is the same as the customer we found?
$this->session->setCustomer($customer);
}
$em->flush();
// response
@ -839,18 +848,15 @@ class APIController extends Controller
$long = $req->request->get('long');
$lat = $req->request->get('lat');
/*
// geofence
$is_covered = $geo->isCovered($long, $lat);
if (!$is_covered)
{
// TODO: put geofence error message in config file somewhere
$res->setError(true)
->setErrorMessage('Oops! Our service is limited to Metro Manila only. We will update you as soon as we are able to cover your area');
->setErrorMessage('Oops! Our service is limited to some areas in Metro Manila, Laguna, and Baguio only. We will update you as soon as we are able to cover your area');
return $res->getReturnResponse();
}
*/
$jo = new JobOrder();
$jo->setSource(TransactionOrigin::MOBILE_APP)
@ -2182,4 +2188,29 @@ class APIController extends Controller
return $res->getReturnResponse();
}
protected function findCustomerByNumber($number)
{
$em = $this->getDoctrine()->getManager();
$customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]);
// find the customer with the most number of cars
$car_count = 0;
$cust = null;
foreach($customers as $customer)
{
$vehicles = $customer->getVehicles();
if (count($vehicles) > $car_count)
{
$car_count = count($vehicles);
// "save" customer object
$cust = $customer;
}
}
return $cust;
}
}

View file

@ -0,0 +1,204 @@
<?php
namespace App\Controller\CAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\Customer;
use App\Entity\CustomerVehicle;
use App\Entity\Vehicle;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class CustomerController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function register(Request $req, EntityManagerInterface $em)
{
$this->denyAccessUnlessGranted('customer.register', null, 'No access.');
// required parameters
$params = [
'first_name',
'last_name',
'mobile_number',
'v_make_id',
'v_model_year',
'v_plate_number',
'v_color',
'v_condition',
'v_fuel_type',
];
$msg = $this->checkRequiredParameters($req, $params);
error_log('msg - ' . $msg);
if ($msg)
return new APIResponse(false, $msg);
$first_name = $req->request->get('first_name');
$last_name = $req->request->get('last_name');
$mobile_number = $req->request->get('mobile_number');
$make_id = $req->request->get('v_make_id');
$model_year = $req->request->get('v_model_year');
$plate_number = $this->cleanPlateNumber($req->request->get('v_plate_number'));
$color = $req->request->get('v_color');
$condition = $req->request->get('v_condition');
$fuel_type = $req->request->get('v_fuel_type');
// check if vehicle exists
$vehicle = $em->getRepository(Vehicle::class)->find($make_id);
if ($vehicle == null)
return new APIResponse(false, 'Invalid vehicle make.');
// clean up mobile number
// does it fit our 09XXXXXXXXX pattern?
if (preg_match('/^09[0-9]{9}$/', $mobile_number))
{
// remove first '0'
$mobile_number = substr($mobile_number, 1);
error_log("CONVERTED TO $mobile_number");
}
// does it fit our 9XXXXXXXXX pattern?
if (!preg_match('/^9[0-9]{9}$/', $mobile_number))
return new APIResponse(false, 'Invalid mobile number.');
/*
// 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($mobile_number <= 2))
continue;
*/
$data = [];
$message = '';
// check if customer already exists
$customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $mobile_number]);
if (!empty($customers))
{
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 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 == $plate_number)
{
// customer and customer vehicle already exists
$cv_found = true;
break;
}
}
}
// if there is a customer vehicle matched
if ($cv_found)
{
// vehicle found, do nothing
$message = 'Customer found.';
}
else
{
// customer already exists but not customer vehicle
// add customer vehicle
$new_cv = new CustomerVehicle();
$new_cv->setCustomer($customer)
->setPlateNumber($plate_number)
->setStatusCondition($condition)
->setModelYear($model_year)
->setColor($color)
->setFuelType($fuel_type)
->setHasMotoliteBattery(true)
->setVehicle($vehicle);
$em->persist($new_cv);
$message = 'Vehicle added.';
$data[] = [
'make_id' => $make_id,
'model_year' => $model_year,
'plate_number' => $plate_number,
'color' => $color,
'condition' => $condition,
'fuel_type' => $fuel_type,
];
}
}
}
else
{
// customer not found
$new_cust = new Customer();
$new_cust->setFirstName($first_name)
->setLastName($last_name)
->setPhoneMobile($mobile_number);
$em->persist($new_cust);
// add customer vehicle
$new_cv = new CustomerVehicle();
$new_cv->setCustomer($new_cust)
->setPlateNumber($plate_number)
->setStatusCondition($condition)
->setModelYear($model_year)
->setColor($color)
->setFuelType($fuel_type)
->setHasMotoliteBattery(true)
->setVehicle($vehicle);
$em->persist($new_cv);
$message = 'Customer and vehicle added.';
$data[] = [
'first_name' => $first_name,
'last_name' => $last_name,
'mobile_number' => $mobile_number,
'make_id' => $make_id,
'model_year' => $model_year,
'plate_number' => $plate_number,
'color' => $color,
'condition' => $condition,
'fuel_type' => $fuel_type,
];
}
$em->flush();
$em->clear();
return new APIResponse(true, $message, $data);
}
protected function cleanPlateNumber($plate)
{
// remove spaces and make upper case
return strtoupper(str_replace(' ', '', $plate));
}
}

View file

@ -27,7 +27,6 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Dotenv\Dotenv;
use Catalyst\MenuBundle\Annotation\Menu;
@ -36,6 +35,8 @@ use DateTime;
class ReportController extends Controller
{
const PREREGISTER_PREFIX = '9';
/**
* @Menu(selected="outlet_list")
*/
@ -474,6 +475,7 @@ class ReportController extends Controller
'Plate Number',
'Warranty Create Date',
'Activation Status',
'Warranty Class',
'Has Mobile App?',
'Date Mobile App Downloaded',
'Mobile Number Using Mobile App',
@ -546,6 +548,121 @@ class ReportController extends Controller
return $resp;
}
/**
* @Menu(selected="outlet_list")
*/
public function warrantyClassForm()
{
$this->denyAccessUnlessGranted('report.warranty.class', null, 'No access.');
$params['mode'] = 'form';
return $this->render('report/warranty-class/form.html.twig', $params);
}
/**
* @Menu(selected="outlet_list")
*/
public function warrantyClassExportCSV(Request $req, EntityManagerInterface $em)
{
$data = $this->getWarrantyClassData($em);
$resp = new StreamedResponse();
$resp->setCallback(function() use ($data) {
// csv output
$csv_handle = fopen('php://output', 'w+');
fputcsv($csv_handle, [
'Customer Last Name',
'Customer First Name',
'Vehicle Manufacturer',
'Vehicle Make',
'Model Year',
'Vehicle Color',
'Warranty Serial',
'Warranty Class',
'Plate Number',
'Warranty Last Name',
'Warranty First Name',
'Warranty Mobile Number',
'Warranty Battery Model',
'Warranty Battery Size',
'Warranty SAP Battery',
'Warranty Status',
'Warranty Created',
'Warranty Purchased',
'Warranty Expiry Date',
'Warranty Claim Date',
'Warranty Claimed From',
'Warranty Privacy Policy',
'Is Warranty Activated?',
]);
foreach ($data as $row)
{
fputcsv($csv_handle, $row);
}
fclose($csv_handle);
});
$filename = 'warranty_class_report' . '.csv';
$resp->setStatusCode(200);
$resp->headers->set('Content-Type', 'text/csv; charset=utf-8');
$resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
return $resp;
}
/**
* @Menu(selected="outlet_list")
*/
public function vehicleBatteryCompatibilityForm()
{
$this->denyAccessUnlessGranted('report.vehicle.battery.compatibility', null, 'No access.');
$params['mode'] = 'form';
return $this->render('report/vehicle-battery-compatibility/form.html.twig', $params);
}
/**
* @Menu(selected="outlet_list")
*/
public function vehicleBatteryCompatibilityExportCSV(Request $req, EntityManagerInterface $em)
{
$data = $this->getVehicleBatteryCompatibilityData($em);
$resp = new StreamedResponse();
$resp->setCallback(function() use ($data) {
// csv output
$csv_handle = fopen('php://output', 'w+');
fputcsv($csv_handle, [
'Vehicle Manufacturer',
'Vehicle Make',
'Vehicle Model Year From',
'Vehicle Model Year To',
'Battery Manufacturer',
'Battery Model',
'Battery Size',
'Battery SAP Code',
]);
foreach ($data as $row)
{
fputcsv($csv_handle, $row);
}
fclose($csv_handle);
});
$filename = 'vehicle_battery_compatibility_report' . '.csv';
$resp->setStatusCode(200);
$resp->headers->set('Content-Type', 'text/csv; charset=utf-8');
$resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
return $resp;
}
protected function processPopappFile(UploadedFile $csv_file, EntityManagerInterface $em)
{
// attempt to open file
@ -588,6 +705,7 @@ class ReportController extends Controller
'plate_num' => '',
'warr_date_create' => '',
'warr_activation_status' => '',
'warr_class' => '',
'has_mobile' => '',
'date_mobile' => '',
'mobile_number' => '',
@ -605,66 +723,68 @@ class ReportController extends Controller
if (!empty($serial))
{
// get the warranty for serial
$warr_qb = $this->getDoctrine()
->getRepository(Warranty::class)
->createQueryBuilder('q');
$warranty_query = $warr_qb->select('q')
->where('q.serial = :serial')
->setParameter('serial', $serial);
$warranty = $warranty_query->getQuery()->getOneOrNullResult();
$warranties = $em->getRepository(Warranty::class)->findBy(['serial' => $serial]);
if ($warranty != null)
if (!empty($warranties))
{
$isValid = InvalidPlateNumber::isInvalid($warranty->getPlateNumber());
if ($isValid)
foreach ($warranties as $warranty)
{
// get customer vehicles using plate number
$customer_vehicles = $em->getRepository(CustomerVehicle::class)->findBy(['plate_number' => $warranty->getPlateNumber()]);
// check if customer vehicle is empty
if (count($customer_vehicles) != 0)
//error_log('found warranty for serial ' . $serial);
$plate_number = $warranty->getPlateNumber();
$isValid = InvalidPlateNumber::isInvalid($plate_number);
if ($isValid)
{
$has_mobile = false;
$mobile_date = '';
$mobile_number = '';
// get the first customer vehicle, store as best_cv until we find one with a mobile session
$best_cv = current($customer_vehicles);
foreach($customer_vehicles as $cv)
// get customer vehicles using plate number
$customer_vehicles = $em->getRepository(CustomerVehicle::class)->findBy(['plate_number' => $plate_number]);
// check if customer vehicle is empty
if (count($customer_vehicles) != 0)
{
// get mobile session of customer
//error_log($cv->getCustomer()->getLastName() . ' ' . $cv->getCustomer()->getFirstName());
$mobile_session = $em->getRepository(MobileSession::class)
->findOneBy(['customer' => $cv->getCustomer()->getID()], ['date_generated' => 'ASC']);
if ($mobile_session != null)
//error_log('found customer vehicle for plate number ' . $plate_number);
$has_mobile = false;
$mobile_date = '';
$mobile_number = '';
// get the first customer vehicle, store as best_cv until we find one with a mobile session
$best_cv = current($customer_vehicles);
foreach($customer_vehicles as $cv)
{
// get mobile data
$has_mobile = true;
$mobile_date = $mobile_session->getDateGenerated()->format("d M Y");
$mobile_number = $mobile_session->getPhoneNumber();
// get mobile session of customer
//error_log($cv->getCustomer()->getLastName() . ' ' . $cv->getCustomer()->getFirstName());
$cust_id = $cv->getCustomer()->getID();
$mobile_session = $em->getRepository(MobileSession::class)
->findOneBy(['customer' => $cust_id], ['date_generated' => 'ASC']);
if ($mobile_session != null)
{
// get mobile data
//error_log('found mobile session for customer id ' . $cv->getCustomer()->getID());
$has_mobile = true;
$mobile_date = $mobile_session->getDateGenerated()->format("d M Y");
$mobile_number = $mobile_session->getPhoneNumber();
// set best_cv to this customer vehicle with mobile session
$best_cv = $cv;
// set best_cv to this customer vehicle with mobile session
$best_cv = $cv;
}
}
// set the customer data in results
$results[$key]['cust_id'] = $best_cv->getCustomer()->getID();
$results[$key]['cust_lastname'] = $best_cv->getCustomer()->getLastName();
$results[$key]['cust_firstname'] = $best_cv->getCustomer()->getFirstName();
$results[$key]['cust_mobile_number'] = $best_cv->getCustomer()->getPhoneMobile();
$results[$key]['plate_num'] = $best_cv->getPlateNumber();
$results[$key]['has_mobile'] = ($has_mobile ? 'Yes' : 'No');
$results[$key]['date_mobile'] = $mobile_date;
$results[$key]['mobile_number'] = $mobile_number;
}
// set the customer data in results
$results[$key]['cust_id'] = $best_cv->getCustomer()->getID();
$results[$key]['cust_lastname'] = $best_cv->getCustomer()->getLastName();
$results[$key]['cust_firstname'] = $best_cv->getCustomer()->getFirstName();
$results[$key]['cust_mobile_number'] = $best_cv->getCustomer()->getPhoneMobile();
$results[$key]['plate_num'] = $best_cv->getPlateNumber();
$results[$key]['has_mobile'] = ($has_mobile ? 'Yes' : 'No');
$results[$key]['date_mobile'] = $mobile_date;
$results[$key]['mobile_number'] = $mobile_number;
}
// set the warranty data in results
$results[$key]['warr_lastname'] = $warranty->getLastName();
$results[$key]['warr_firstname'] = $warranty->getFirstName();
$results[$key]['warr_date_create'] = $warranty->getDateCreate()->format("d M Y");
$results[$key]['warr_activation_status'] = ($warranty->isActivated() ? 'Active' : 'Inactive');
$results[$key]['warr_class'] = $warranty->getWarrantyClass();
}
// set the warranty data in results
$results[$key]['warr_lastname'] = $warranty->getLastName();
$results[$key]['warr_firstname'] = $warranty->getFirstName();
$results[$key]['warr_date_create'] = $warranty->getDateCreate()->format("d M Y");
$results[$key]['warr_activation_status'] = ($warranty->isActivated() ? 'Active' : 'Inactive');
}
}
}
@ -719,6 +839,173 @@ class ReportController extends Controller
}
return $results;
}
protected function getWarrantyClassData(EntityManagerInterface $em)
{
$results = [];
// query preregistered ustomers using search term '%9'
$cust_query = $em->createQuery('select c from App\Entity\Customer c where c.phone_mobile like :search_mobile')
->setParameter('search_mobile', "%" . self::PREREGISTER_PREFIX);
$customers = $cust_query->iterate();
foreach($customers as $crow)
{
$cust = $crow[0];
//error_log('Processing customer ' . $cust->getID());
// get list of customer vehicles
$c_vehicles = $cust->getVehicles();
foreach($c_vehicles as $cv)
{
if (!empty($c_vehicles))
{
// find warranty for plate number
$clean_cv_plate = $this->cleanPlateNumber($cv->getPlateNumber());
$warranties = $em->getRepository(Warranty::class)->findBy(['plate_number' => $clean_cv_plate]);
foreach ($warranties as $warr)
{
//error_log('Found warranty for plate number ' . $warr->getPlateNumber());
// form the result row
$results[] = $this->formWarrantyClassResult($cust, $cv, $warr);
}
}
}
$em->clear();
}
return $results;
}
protected function cleanPlateNumber($plate)
{
// remove spaces and make upper case
return strtoupper(str_replace(' ', '', $plate));
}
protected function formWarrantyClassResult($cust, $cv, $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();
}
$data = [
'c_last_name' => $cust->getLastName(),
'c_first_name' => $cust->getFirstName(),
'manufacturer' => $cv->getVehicle()->getManufacturer()->getName(),
'make' => $cv->getVehicle()->getMake(),
'model_year' => $cv->getModelYear(),
'color' => $cv->getColor(),
'serial' => $warr->getSerial(),
'class' => $warr->getWarrantyClass(),
'plate_number' => $warr->getPlateNumber(),
'w_last_name' => $warr->getLastName(),
'w_first_name' => $warr->getFirstName(),
'w_mobile_num' => $warr->getMobileNumber(),
'w_batt_model' => $batt_model,
'w_batt_size' => $batt_size,
'w_sap_batt' => $sap_batt,
'w_status' => $warr->getStatus(),
'w_date_create' => $date_create,
'w_date_purchase' => $date_purchased,
'w_date_expire' => $date_expire,
'w_date_claim' => $date_claim,
'w_claimed_from' => $warr->getClaimedFrom(),
'w_privacy_policy' => $policy,
'w_activated' => ($warr->isActivated() ? 'Active' : 'Inactive'),
];
return $data;
}
protected function getVehicleBatteryCompatibilityData(EntityManagerInterface $em)
{
$results = [];
$conn = $em->getConnection();
$sql = 'SELECT vm.name AS vm_name, v.make,
v.model_year_from, v.model_year_to,
bm.name AS bm_name, bmodel.name AS bmodel_name,
bsize.name AS bsize_name,
b.sap_code
FROM vehicle_manufacturer vm, vehicle v, battery_vehicle bv,
battery b, battery_manufacturer bm, battery_model bmodel,
battery_size bsize
WHERE vm.id = v.manufacturer_id
AND v.id = bv.vehicle_id
AND bv.battery_id = b.id
AND b.manufacturer_id = bm.id
AND b.model_id = bmodel.id
AND b.size_id = bsize.id
ORDER BY vm.name, v.make';
$stmt = $conn->prepare($sql);
$stmt->execute();
$query_results = $stmt->fetchAll();
foreach($query_results as $row)
{
$results[] = [
'vehicle_manufacturer' => $row['vm_name'],
'vehicle_make' => $row['make'],
'vehicle_model_year_from' => $row['model_year_from'],
'vehicle_model_year_to' => $row['model_year_to'],
'battery_manufacturer' => $row['bm_name'],
'battery_model' => $row['bmodel_name'],
'battery_size' => $row['bsize_name'],
'battery_sap_code' => $row['sap_code'],
];
}
return $results;
}
}

View file

@ -4,6 +4,7 @@ namespace App\Controller;
use App\Entity\Warranty;
use App\Entity\SAPBattery;
use App\Entity\Battery;
use App\Entity\BatteryModel;
use App\Entity\BatterySize;
@ -11,8 +12,11 @@ use App\Ramcar\WarrantyClass;
use App\Ramcar\WarrantyStatus;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
@ -22,6 +26,11 @@ use Catalyst\MenuBundle\Annotation\Menu;
class WarrantyController extends Controller
{
const PURCHASE_DATE_EMPTY = 'Purchase date missing.';
const PLATE_NUM_EMPTY = 'Plate number missing.';
const SERIAL_EMPTY = 'Serial number missing.';
const PURCHASE_DATE_INVALID = 'Invalid purchase date.';
/**
* @Menu(selected="warranty_list")
*/
@ -348,9 +357,224 @@ class WarrantyController extends Controller
'success' => 'Changes have been saved!'
]);
}
}
/**
* @Menu(selected="warranty_list")
*/
public function uploadForm()
{
$this->denyAccessUnlessGranted('warranty.upload', null, 'No access.');
return $this->render('warranty/upload.form.html.twig');
}
/**
* @Menu(selected="warranty_list")
*/
public function uploadSubmit(Request $req, EntityManagerInterface $em)
{
// retrieve temporary info for file
$file = $req->files->get('csv_file');
// process the csv file
$inv_entries = $this->processWarrantyFile($file, $em);
$resp = new StreamedResponse();
$resp->setCallback(function() use($inv_entries) {
// csv output
$csv_handle = fopen('php://output', 'w+');
fputcsv($csv_handle, [
'Owner First Name',
'Owner Last Name',
'Owner Email',
'Owner Address',
'Owner Mobile',
'Owner Telephone',
'Vehicle Make',
'Vehicle Model',
'Vehicle Year',
'Vehicle Plate Number',
'Battery Serial Number',
'Battery Sales Invoice',
'Battery Date of Purchase',
'Distributor Name',
'Distributor Address',
'Application Type ID',
'Battery ID',
'Ownership Type',
'Reason Warranty Not Added',
]);
foreach ($inv_entries as $row)
{
fputcsv($csv_handle, $row);
}
fclose($csv_handle);
});
$filename = 'invalid_warranties' . '.csv';
$resp->setStatusCode(200);
$resp->headers->set('Content-Type', 'text/csv; charset=utf-8');
$resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
return $resp;
}
protected function processWarrantyFile(UploadedFile $csv_file, EntityManagerInterface $em)
{
// attempt to open file
try
{
$fh = fopen($csv_file, "r");
}
catch (Exception $e)
{
throw new Exception('The file "' . $csv_file . '" could be read.');
}
// loop through the rows
// 0 - Owner First Name
// 1 - Owner Last Name
// 2 - Owner Email
// 3 - Owner Address
// 4 - Owner Mobile
// 5 - Owner Telephone
// 6 - Vehicle Make
// 7 - Vehicle Model
// 8 - Vehicle Year
// 9 - Vehicle Plate Number
// 10 - Battery Serial Number
// 11 - Battery Sales Invoice
// 12 - Battery Date of Purchase
// 13 - Distributor Name
// 14 - Distributor Address
// 15 - Application Type ID
// 16 - Battery ID
// 17 - Ownership Type
$row_num = 0;
$invalid_entries = [];
while (($fields = fgetcsv($fh)) !== false)
{
// start processing at row 1, not 0
if ($row_num < 1)
{
$row_num++;
continue;
}
// get the data
$first_name = trim($fields[0]);
$last_name = trim($fields[1]);
$mobile_number = trim($fields[4]);
$plate_number = trim($fields[9]);
$serial = trim($fields[10]);
$purchase_date = trim($fields[12]);
$battery_id = trim($fields[16]);
// check if purchase_date or plate_number or serial is empty or if
// purchase date is valid
$date_purchase = DateTime::createFromFormat('d-M-y', $purchase_date);
if (empty($purchase_date) ||
empty($plate_number) ||
empty($serial) ||
($date_purchase == false))
{
$reason = '';
if (empty($plate_number))
$reason = $reason . self::PLATE_NUM_EMPTY . ' ';
if (empty($serial))
$reason = $reason . self::SERIAL_EMPTY . ' ';
if (empty($purchase_date))
$reason = $reason . self::PURCHASE_DATE_EMPTY . ' ';
else
{
if ($date_purchase == false)
$reason = $reason . self::PURCHASE_DATE_INVALID . ' ';
}
// add to invalid_entries
$invalid_entries[] = [
'owner_first_name' => $first_name,
'owner_last_name' => $last_name,
'owner_email' => trim($fields[2]),
'owner_address' => trim($fields[3]),
'owner_mobile' => $mobile_number,
'owner_telephone' => trim($fields[5]),
'vehicle_make' => trim($fields[6]),
'vehicle_model' => trim($fields[7]),
'vehicle_year' => trim($fields[8]),
'vehicle_plate_number' => $plate_number,
'battery_serial_number' => $serial,
'battery_sales_invoice' => trim($fields[11]),
'battery_date_purchase' => $purchase_date,
'distributor_name' => trim($fields[13]),
'distributor_address' => trim($fields[14]),
'application_type_id' => trim($fields[15]),
'battery_id' => $battery_id,
'ownership_type' => trim($fields[17]),
'reason' => $reason,
];
}
else
{
// new warranty
$warranty = new Warranty();
// get the battery purchased
// check battery first. If not found, check sap_battery
$battery = $em->getRepository(Battery::class)->find($battery_id);
if ($battery != null)
{
// get the battery model and battery size
$model_id = $battery->getModel()->getID();
$size_id = $battery->getSize()->getID();
$bty_model = $em->getRepository(BatteryModel::class)->find($model_id);
$bty_size = $em->getRepository(BatterySize::class)->find($size_id);
if ($bty_model != null)
{
$warranty->setBatteryModel($bty_model);
}
if ($bty_size != null)
{
$warranty->setBatterySize($bty_size);
}
}
else
{
// find battery in sap_battery
$battery = $em->getRepository(SAPBattery::class)->find($battery_id);
if ($battery != null)
{
// battery is SAPBattery
$warranty->setSAPBattery($battery);
}
}
// set and save values
$warranty->setSerial($serial)
->setPlateNumber($plate_number)
->setFirstName($first_name)
->setLastName($last_name)
->setMobileNumber($mobile_number)
->setDatePurchase($date_purchase);
$em->persist($warranty);
$em->flush();
}
$row_num++;
}
return $invalid_entries;
}
protected function fillDropdownParameters(&$params)
{

View file

@ -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
{

View file

@ -10,7 +10,8 @@ use DateTime;
/**
* @ORM\Entity
* @ORM\Table(name="customer_vehicle", indexes={@ORM\Index(columns={"plate_number"}, flags={"fulltext"})})
* @ORM\Table(name="customer_vehicle", indexes={@ORM\Index(columns={"plate_number"}, flags={"fulltext"}),
@ORM\Index(name="plate_number_idx", columns={"plate_number"})})
*/
class CustomerVehicle
{
@ -54,7 +55,6 @@ class CustomerVehicle
// model year
/**
* @ORM\Column(type="smallint")
* @Assert\NotBlank()
*/
protected $model_year;

65
src/Entity/GeoCity.php Normal file
View file

@ -0,0 +1,65 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use CrEOF\Spatial\PHP\Types\Geometry\Polygon;
use CrEOF\Spatial\PHP\Types\Geometry\MultiPolygon;
use DateTime;
/**
* @ORM\Entity
* @ORM\Table(name="geo_city")
*/
class GeoCity
{
// unique id
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=120)
*/
protected $name;
/**
* @ORM\Column(type="multipolygon")
*/
protected $area;
public function __construct()
{
}
public function getID()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
public function setArea(MultiPolygon $geo)
{
$this->area = $geo;
return $this;
}
public function getArea()
{
return $this->area;
}
}

View file

@ -14,7 +14,8 @@ use Exception;
* name="warranty",
* uniqueConstraints={
* @ORM\UniqueConstraint(columns={"serial"})
* }
* },
* indexes={@ORM\Index(name="plate_number_idx", columns={"plate_number"})})
* )
*/
class Warranty

View file

@ -11,25 +11,33 @@ use CrEOF\Spatial\PHP\Types\Geometry\Point;
class GeofenceTracker
{
protected $em;
protected $geofence_flag;
public function __construct(EntityManagerInterface $em)
public function __construct(EntityManagerInterface $em, $geofence_flag)
{
$this->em = $em;
$this->geofence_flag = $geofence_flag;
}
public function isCovered($long, $lat)
{
// see if the point is in any of the polygons
$query = $this->em->createQuery('SELECT count(s) from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true')
->setParameter('long', $long)
->setParameter('lat', $lat);
// check if geofence is enabled
if ($this->geofence_flag == 'true')
{
// see if the point is in any of the polygons
$query = $this->em->createQuery('SELECT count(s) from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true')
->setParameter('long', $long)
->setParameter('lat', $lat);
// number of polygons that contain the point
$count = $query->getSingleScalarResult();
// number of polygons that contain the point
$count = $query->getSingleScalarResult();
if ($count > 0)
return true;
if ($count > 0)
return true;
return false;
return false;
}
return true;
}
}

View file

@ -98,6 +98,9 @@
"doctrine/reflection": {
"version": "v1.0.0"
},
"edwinhoksberg/php-fcm": {
"version": "1.0.0"
},
"guzzlehttp/guzzle": {
"version": "6.3.0"
},

View file

@ -153,7 +153,7 @@
</h3>
<ul class="m-menu__inner">
<li class="m-menu__item " data-redirect="true" aria-haspopup="true">
<a href="{{ url('rep_popapp_comp_form') }}" class="m-menu__link">
<a href="{{ url('rep_popapp_comp_form') }}" class="m-menu__link">
<i class="m-menu__link-bullet m-menu__link-bullet--dot">
<span></span>
</i>
@ -161,7 +161,7 @@
Popapp Comparison Report
</span>
</a>
<a href="{{ url('rep_resq_meh_form') }}" class="m-menu__link">
<a href="{{ url('rep_resq_meh_form') }}" class="m-menu__link">
<i class="m-menu__link-bullet m-menu__link-bullet--dot">
<span></span>
</i>
@ -169,6 +169,23 @@
RESQ MEH Customer Report
</span>
</a>
<a href="{{ url('rep_warranty_class_form') }}" class="m-menu__link">
<i class="m-menu__link-bullet m-menu__link-bullet--dot">
<span></span>
</i>
<span class="m-menu__link-text">
Warranty Class Report
</span>
</a>
<a href="{{ url('rep_vehicle_battery_compatibility_form') }}" class="m-menu__link">
<i class="m-menu__link-bullet m-menu__link-bullet--dot">
<span></span>
</i>
<span class="m-menu__link-text">
Vehicle Battery Compatibility Report
</span>
</a>
</li>
</ul>
</li>

View file

@ -0,0 +1,50 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- BEGIN: Subheader -->
<div class="m-subheader">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title">
Vehicle Battery Compatibility Report
</h3>
</div>
</div>
</div>
<!-- END: Subheader -->
<div class="m-content">
<!--Begin::Section-->
<div class="row">
<div class="col-xl-6">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<span class="m-portlet__head-icon">
<i class="fa fa-upload"></i>
</span>
<h3 class="m-portlet__head-text">
Generate Vehicle Battery Compatibility CSV File
</h3>
</div>
</div>
</div>
<form id="upload_form" class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ url('rep_vehicle_battery_compatibility_export_csv') }}" enctype="multipart/form-data">
<div class="m-portlet__body">
<div class="m-portlet__foot m-portlet__foot--fit">
<div class="m-form__actions m-form__actions--solid m-form__actions--right">
<div class="row">
<div class="col-lg-12">
<button type="submit" class="btn btn-success">Export to CSV</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,50 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- BEGIN: Subheader -->
<div class="m-subheader">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title">
Warranty Class Report
</h3>
</div>
</div>
</div>
<!-- END: Subheader -->
<div class="m-content">
<!--Begin::Section-->
<div class="row">
<div class="col-xl-6">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<span class="m-portlet__head-icon">
<i class="fa fa-upload"></i>
</span>
<h3 class="m-portlet__head-text">
Generate Warranty Class CSV File
</h3>
</div>
</div>
</div>
<form id="upload_form" class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ url('rep_warranty_class_export_csv') }}" enctype="multipart/form-data">
<div class="m-portlet__body">
<div class="m-portlet__foot m-portlet__foot--fit">
<div class="m-form__actions m-form__actions--solid m-form__actions--right">
<div class="row">
<div class="col-lg-12">
<button type="submit" class="btn btn-success">Export to CSV</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,52 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- BEGIN: Subheader -->
<div class="m-subheader">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title">
Warranty Upload
</h3>
</div>
</div>
</div>
<!-- END: Subheader -->
<div class="m-content">
<!--Begin::Section-->
<div class="row">
<div class="col-xl-6">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<span class="m-portlet__head-icon">
<i class="fa fa-upload"></i>
</span>
<h3 class="m-portlet__head-text">
Upload Warranty CSV File
</h3>
</div>
</div>
</div>
<form id="upload_form" class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ url('warranty_upload_submit') }}" enctype="multipart/form-data">
<div class="m-portlet__body">
<div class="form-group m-form__group row">
<input type="file" id="csv_file" name="csv_file" >
</div>
<div class="m-portlet__foot m-portlet__foot--fit">
<div class="m-form__actions m-form__actions--solid m-form__actions--right">
<div class="row">
<div class="col-lg-12">
<button type="submit" class="btn btn-success">Upload</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,23 @@
<?php
require __DIR__ . '/../../vendor/autoload.php';
use Fcm\FcmClient;
use Fcm\Push\Notification;
$api_token = 'AAAArpsiQbQ:APA91bHQVXxkUxNp3i2kviEmRDAnXKUyP0-Z5HZD15gV5V4TgidjmEiVVHilPnLffTW4u9txWkA_PPthTv7Baq8_wx99hr9Bx62q4JWrPsrfnNMeEw9w5ojPPu0eCOGOKHn_l1HoY_SJBS1n6DTt7IC0L14Kn33kmw';
$sender_id = 'AIzaSyD5gUUkXwaKarWYIigJGLLTzf9KQwoJ2wM';
// Instantiate the client with the project api_token and sender_id.
$client = new FcmClient($api_token, $sender_id);
// Instantiate the push notification request object.
$notification = new Notification();
// Enhance the notification object with our custom options.
$notification->addRecipient($device_id)
->setTitle('Motolite RES-Q')
->setBody('Test notification sending')
// Send the notification to the Firebase servers for further handling.
$client->send($notification);