Merge branch 'master' of gitlab.com:jankstudio/resq into 543-autoassign-revisions

This commit is contained in:
Korina Cordero 2021-03-30 02:04:17 +00:00
commit 789d376d91
36 changed files with 1708 additions and 124 deletions

1
.gitignore vendored
View file

@ -11,3 +11,4 @@
###< symfony/framework-bundle ###
*.swp
/public/warranty_uploads/*

View file

@ -14,6 +14,7 @@
"data-dog/audit-bundle": "^0.1.10",
"edwinhoksberg/php-fcm": "^1.0",
"guzzlehttp/guzzle": "^6.3",
"microsoft/azure-storage-blob": "^1.5",
"predis/predis": "^1.1",
"sensio/framework-extra-bundle": "^5.1",
"setasign/fpdf": "^1.8",

96
composer.lock generated
View file

@ -4,7 +4,7 @@
"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": "f03b92d48946e8b2ee19466f931c826f",
"content-hash": "ad9d56a6dff26742f024917e58b919f9",
"packages": [
{
"name": "catalyst/auth-bundle",
@ -944,6 +944,7 @@
"cache",
"caching"
],
"abandoned": true,
"time": "2019-11-29T11:22:01+00:00"
},
{
@ -1611,6 +1612,7 @@
"reflection",
"static"
],
"abandoned": "roave/better-reflection",
"time": "2020-03-27T11:06:43+00:00"
},
{
@ -1901,6 +1903,94 @@
],
"time": "2014-01-12T16:20:24+00:00"
},
{
"name": "microsoft/azure-storage-blob",
"version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/Azure/azure-storage-blob-php.git",
"reference": "2475330963372d519387cb8135d6a9cfd42272da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Azure/azure-storage-blob-php/zipball/2475330963372d519387cb8135d6a9cfd42272da",
"reference": "2475330963372d519387cb8135d6a9cfd42272da",
"shasum": ""
},
"require": {
"microsoft/azure-storage-common": "~1.5",
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"MicrosoftAzure\\Storage\\Blob\\": "src/Blob"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Azure Storage PHP Client Library",
"email": "dmsh@microsoft.com"
}
],
"description": "This project provides a set of PHP client libraries that make it easy to access Microsoft Azure Storage Blob APIs.",
"keywords": [
"azure",
"blob",
"php",
"sdk",
"storage"
],
"time": "2020-12-29T02:22:11+00:00"
},
{
"name": "microsoft/azure-storage-common",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/Azure/azure-storage-common-php.git",
"reference": "e5738035891546075bd369954e8af121d65ebd6d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Azure/azure-storage-common-php/zipball/e5738035891546075bd369954e8af121d65ebd6d",
"reference": "e5738035891546075bd369954e8af121d65ebd6d",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "~6.0|^7.0",
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"MicrosoftAzure\\Storage\\Common\\": "src/Common"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Azure Storage PHP Client Library",
"email": "dmsh@microsoft.com"
}
],
"description": "This project provides a set of common code shared by Azure Storage Blob, Table, Queue and File PHP client libraries.",
"keywords": [
"azure",
"common",
"php",
"sdk",
"storage"
],
"time": "2020-12-28T07:59:51+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.3.0",
@ -2078,12 +2168,12 @@
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/nrk/predis.git",
"url": "https://github.com/predis/predis.git",
"reference": "f0210e38881631afeafb56ab43405a92cafd9fd1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1",
"url": "https://api.github.com/repos/predis/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1",
"reference": "f0210e38881631afeafb56ab43405a92cafd9fd1",
"shasum": ""
},

View file

@ -342,6 +342,8 @@ access_keys:
label: Auto Assigned Job Order Report
- id: report.jo.advance_order
label: Advance Order Job Order Report
- id: report.customer.source
label: Customer Source Report
- id: service
label: Other Services

View file

@ -49,6 +49,11 @@ capi_vehicle_list:
controller: App\Controller\CAPI\VehicleController::list
methods: [GET]
capi_vehicle_by_mfg:
path: /capi/vehicle_manufacturer/{mfg_id}
controller: App\Controller\CAPI\VehicleController::getByManufacturer
methods: [GET]
# plate api
@ -149,3 +154,15 @@ capi_customer_register:
path: /capi/quick_registration
controller: App\Controller\CAPI\CustomerController::register
methods: [POST]
# customer warranty api
capi_cwarr_check:
path: /capi/customer_warranty/{serial}
controller: App\Controller\CAPI\CustomerWarrantyController::check
methods: [GET]
capi_cwarr_register:
path: /capi/customer_warranty/{serial}
controller: App\Controller\CAPI\CustomerWarrantyController::register
methods: [POST]

View file

@ -5,7 +5,7 @@ customer_list:
customer_rows:
path: /customers/rows
controller: App\Controller\CustomerController::rows
methods: [POST]
methods: [GET,POST]
customer_vehicle_search:
path: /customers/vehicles

View file

@ -127,3 +127,13 @@ rep_jo_advance_order_submit:
path: /report/jo_advance_order_report
controller: App\Controller\ReportController::jobOrderAdvanceOrderSubmit
methods: [POST]
rep_customer_source_form:
path: /report/customer_source_report
controller: App\Controller\ReportController::customerSourceForm
methods: [GET]
rep_customer_source_submit:
path: /report/customer_source_report
controller: App\Controller\ReportController::customerSourceSubmit
methods: [POST]

0
public/.gitkeep Normal file
View file

View file

@ -0,0 +1 @@

View file

@ -44,7 +44,7 @@
<h2 style="font-weight: bold; font-size: 40px;">Can I request for any Res-Q service if I don't have or have a weak data signal?
</h2>
<p>Res-Q needs a stable data connection for you to be able to request for a service and track the location of our rider. If you don't have a stable data connection, you may call our hotline at (02) 370-6686.
<p>Res-Q needs a stable data connection for you to be able to request for a service and track the location of our rider. If you don't have a stable data connection, you may call our hotline at (02) 8370-6686.
</p>
<h2 style="font-weight: bold; font-size: 40px;">
@ -58,7 +58,13 @@ Yes, we accept Visa and Mastercard issued in the Philippines.
How can I pay for your services/ products?
</h2>
<p>
We accept COD, local Credit Cards, Debit Cards, and ATM Cards only.
We accept COD, local credit cards, debit cards, and ATM cards for battery replacement transactions. We only accept cash payment for flat tire, refuel and overheat transactions.
</p>
<p>
Credit Card and Debit Card Payment is for Battery Sales only.
</p>
<p>
Cash only for services request.
</p>
<h2 style="font-weight: bold; font-size: 40px;">
@ -72,7 +78,7 @@ Once you have successfully submitted your request, you will be able to see the p
How do I make a follow up for my order/service?
</h2>
<p>
Once your order/ service has been assigned to a Technician Rider, you may be able to see his/her contact details in the App. If no Technician Rider has been assigned yet, you may call our hotline at (02) 370-6686.
Once your order/ service has been assigned to a Technician Rider, you may be able to see his/her contact details in the App. If no Technician Rider has been assigned yet, you may call our hotline at (02) 8370-6686.
</p>
<h2 style="font-weight: bold; font-size: 40px;">
@ -93,14 +99,14 @@ Delivery for battery purchase is free of charge.
Can you deliver anywhere in the Philippines?
</h2>
<p>
Not yet. Res-Q is offered initially in Metro Manila only.
Not yet. Res-Q is offered Metro Manila, Baguio City and Binan, Laguna only.
</p>
<h2 style="font-weight: bold; font-size: 40px;">
My battery was pulled out and is being recharged in an outlet. How do I follow-up when I can take my battery back?
</h2>
<p>
Please call our hotline at (02) 370-6686.
Please call our hotline at (02) 8370-6686.
</p>
@ -109,7 +115,7 @@ Please call our hotline at (02) 370-6686.
How do I contact you for questions or feedback?
</h2>
<p>
You may call our Customer Support Hotline: 02-3706686 or email us at online@motolite.com.
You may call our Customer Support Hotline: 02-83706686 or email us at online@motolite.com.
</p>
<h2 style="font-weight: bold; font-size: 40px;">

View file

@ -58,7 +58,7 @@ Yes, we accept Visa and Mastercard issued in the Philippines.
How can I pay for your services/ products?
</h2>
<p>
We accept COD, local Credit Cards, Debit Cards, and ATM Cards only.
We accept COD, local credit cards, debit cards, and ATM cards for battery replacement transactions. We only accept cash payment for flat tire, refuel and overheat transactions.
</p>
<h2 style="font-weight: bold; font-size: 40px;">
@ -93,7 +93,7 @@ Delivery for battery purchase is free of charge.
Can you deliver anywhere in the Philippines?
</h2>
<p>
Not yet. Res-Q is offered initially in Metro Manila only.
Not yet. Res-Q is offered Metro Manila, Baguio City and Binan, Laguna only.
</p>
<h2 style="font-weight: bold; font-size: 40px;">

View file

@ -12,6 +12,8 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
@ -2792,6 +2794,31 @@ class APIController extends Controller implements LoggedController
return $res->getReturnResponse();
}
protected function checkCustomerPlateNumber($plate_number, $cust)
{
// strip spaces and make all caps
$plate_number = preg_replace('/\s+/', '', strtoupper($plate_number));
// if there's no customer linked to session
if ($cust != null)
{
// check all the customer vehicles
$cvs = $cust->getVehicles();
foreach ($cvs as $cv)
{
$cv_plate = preg_replace('/\s+/', '', strtoupper($cv->getPlateNumber()));
// did we find a match?
if ($cv_plate == $plate_number)
{
return true;
}
}
}
return false;
}
public function warrantyCheck($serial, EntityManagerInterface $em, Request $req)
{
// check required parameters and api key
@ -2800,24 +2827,6 @@ class APIController extends Controller implements LoggedController
if ($res->isError())
return $res->getReturnResponse();
/*
// initialize data
$data = [
'is_valid' => false,
'is_registered' => false,
'customer' => [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
],
'battery' => [
'brand' => '',
'size' => '',
],
];
*/
// check if warranty serial is there
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
@ -2831,100 +2840,224 @@ class APIController extends Controller implements LoggedController
return $res->getReturnResponse();
}
// if warranty serial is there
if ($warr_serial != null)
{
// if we have a warranty entry for the serial already
if ($warr != null)
{
$is_registered = true;
$today = new DateTime();
// null mobile number should be blank string instead
if ($warr->getMobileNumber() == null)
$mobile_num = '';
else
$mobile_num = $warr->getMobileNumber();
// if we have a warranty entry for the serial already
if ($warr != null)
{
$warr_plate = $warr->getPlateNumber();
$is_registered = true;
$is_customer_warranty = false;
// check if the warranty is registered to a car owned by the customer
$cust = $this->session->getCustomer();
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
// null mobile number should be blank string instead
if ($warr->getMobileNumber() == null)
$mobile_num = '';
else
$mobile_num = $warr->getMobileNumber();
$can_edit = $is_customer_warranty;
// if customer plate number matches the one registered on the warranty
if ($is_customer_warranty)
{
// purchase date of customer
if ($warr->getDatePurchaseCustomer() != null)
$date_purchase_cust = $warr->getDatePurchaseCustomer()->format('Y-m-d');
else
$date_purchase_cust = $today->format('Y-m-d');
// invoice
if ($warr->getFileInvoice() != null)
$invoice_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileInvoice();
else
$invoice_url = '';
// warranty card
if ($warr->getFileWarrantyCard() != null)
$warr_card_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileWarrantyCard();
else
$warr_card_url = '';
$customer = [
'first_name' => $warr->getFirstName(),
'last_name' => $warr->getLastName(),
'first_name' => $warr->getFirstName() ?? '',
'last_name' => $warr->getLastName() ?? '',
'mobile_number' => $mobile_num,
'plate_number' => $warr->getPlateNumber(),
'plate_number' => $warr_plate,
'email' => $warr->getEmail() ?? '',
'contact_num' => $warr->getContactNumber() ?? '',
'address' => $warr->getCustomerAddress() ?? '',
];
$other_data = [
'odometer' => (int) $warr->getOdometer() ?? 0,
'date_purchase' => $date_purchase_cust,
'invoice' => $invoice_url,
'warr_card' => $warr_card_url,
'dealer_name' => $warr->getDealerName() ?? '',
'dealer_address' => $warr->getDealerAddress() ?? '',
];
}
else
{
// hide customer information if customer is not the one registered
$customer = [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
'email' => '',
'contact_num' => '',
'address' => '',
];
$other_data = [
'odometer' => 0,
'date_purchase' => $today->format('Y-m-d'),
'invoice' => '',
'warr_card' => '',
'dealer_name' => '',
'dealer_address' => '',
];
}
$sku = $warr_serial->getSKU();
$batt = $em->getRepository(SAPBattery::class)->find($sku);
// TODO: put this in a config file
$image_url = $req->getSchemeAndHttpHost() . '/battery/generic.png';
if ($batt != null)
{
$battery = [
'brand' => $batt->getBrand()->getName(),
'size' => $batt->getSize()->getName(),
'image_url' => $image_url,
];
}
else
{
$battery = [
'brand' => '',
'size' => '',
'image_url' => '',
];
}
// populate data
$data = [
'is_valid' => true,
'is_registered' => $is_registered,
'customer' => $customer,
'battery' => $battery,
'message' => [
'register_error' => 'Warranty serial code has already been registered.',
],
}
else
{
$can_edit = true;
$customer = [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
'email' => '',
'contact_num' => '',
'address' => '',
];
$other_data = [
'odometer' => 0,
'date_purchase' => $today->format('Y-m-d'),
'invoice' => '',
'warr_card' => '',
'dealer_name' => '',
'dealer_address' => '',
];
}
$sku = $warr_serial->getSKU();
$batt = $em->getRepository(SAPBattery::class)->find($sku);
// TODO: put this in a config file
$image_url = $req->getSchemeAndHttpHost() . '/battery/generic.png';
if ($batt != null)
{
$battery = [
'brand' => $batt->getBrand()->getName(),
'size' => $batt->getSize()->getName(),
'image_url' => $image_url,
];
}
else
{
$battery = [
'brand' => '',
'size' => '',
'image_url' => '',
];
}
// populate data
$data = [
'is_valid' => true,
'is_registered' => $is_registered,
'can_edit' => $can_edit,
'customer' => $customer,
'battery' => $battery,
'odometer' => $other_data['odometer'],
'invoice' => $other_data['invoice'],
'warr_card' => $other_data['warr_card'],
'date_purchase' => $other_data['date_purchase'],
'dealer_name' => $other_data['dealer_name'],
'dealer_address' => $other_data['dealer_address'],
'message' => [
'register_error' => 'Warranty serial code has already been registered.',
'edit_error' => 'Sorry, warranty is registered under another vehicle not in your list of vehicles.',
],
];
$res->setData($data);
return $res->getReturnResponse();
}
public function warrantyRegister($serial, EntityManagerInterface $em, Request $req)
protected function handlePictureUpload($file, $target_dir, $serial, $name)
{
error_log("handling $name upload");
// no file sent
if ($file == null)
{
error_log('no file');
return null;
}
// create target dir if it doesn't exist
if (!file_exists($target_dir))
{
if (!mkdir($target_dir, 0744, true))
{
error_log('failed to create folder for warranty pictures');
return null;
}
}
// move file
$filename = $name . '.' . $file->getClientOriginalExtension();
$file->move($target_dir . '/' . $serial, $filename);
error_log("filename - $filename");
error_log($target_dir . '/' . $serial . '/' . $filename);
return $serial . '/' . $filename;
}
public function warrantyRegister($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt, TranslatorInterface $trans)
{
// check required parameters and api key
$required_params = [
'first_name',
'last_name',
'email',
'plate_number',
'date_purchase',
];
// handle file uploads
$invoice = $req->files->get('invoice');
$warr_card = $req->files->get('warr_card');
// normalize serial
$serial = trim(strtoupper($serial));
// process picture uploads
$upload_dir = $kernel->getProjectDir() . '/public/warranty_uploads';
$inv_filename = $this->handlePictureUpload($invoice, $upload_dir, $serial, 'invoice');
$wcard_filename = $this->handlePictureUpload($warr_card, $upload_dir, $serial, 'wcard');
$res = $this->checkParamsAndKey($req, $em, $required_params);
if ($res->isError())
return $res->getReturnResponse();
// update customer information
$cust = $this->updateCustomerInfo($req, $em);
// $cust = $this->updateCustomerInfo($req, $em);
// update warranty
$res = $this->updateWarranty($res, $em, $req, $serial);
$res = $this->updateWarranty($res, $em, $trans, $req, $serial, $inv_filename, $wcard_filename);
$em->flush();
return $res->getReturnResponse();
}
protected function updateWarranty($res, $em, $req, $serial)
protected function updateWarranty($res, $em, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null)
{
// get serial
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
@ -2941,9 +3074,31 @@ class APIController extends Controller implements LoggedController
// skip warranty if it already exists
if ($warr != null)
{
/*
// NOTE: we could not update in the old version
$res->setError(true)
->setErrorMessage('Warranty registration entry already exists.');
return $res;
*/
// check if warranty is registered to a serial owned by customer
$warr_plate = $warr->getPlateNumber();
$cust = $this->session->getCustomer();
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
if (!$is_customer_warranty)
{
$res->setError(true)
->setErrorMessage('Warranty registred to a vehicle not in your list of vehicles.');
return $res;
}
$sms_msg = $trans->trans('warranty_update_confirm');
}
else
{
$warr = new Warranty();
$sms_msg = $trans->trans('warranty_register_confirm');
}
// get sap battery
@ -2956,11 +3111,21 @@ class APIController extends Controller implements LoggedController
return $res;
}
// default date purchase to today
// NOTE: might need to change this later
$date_pur = new DateTime();
// get date purchase specified by customer
$date_pur_cust = DateTime::createFromFormat('Y-m-d', $req->request->get('date_purchase'));
if (!$date_pur_cust)
{
$res->setError(true)
->setErrorMessage('Invalid date format for date of purchase.');
return $res;
}
// create new warranty entry
$warr = new Warranty();
// create or update warranty entry
$warr->setSerial($serial)
->setFirstName($req->request->get('first_name'))
->setLastName($req->request->get('last_name'))
@ -2975,7 +3140,20 @@ class APIController extends Controller implements LoggedController
// ->setBatteryModel()
->setSAPBattery($sap_bty)
->setMobileNumber(substr($this->session->getPhoneNumber(), 2))
->setActivated(true);
->setActivated(true)
// files
->setFileInvoice($inv_filename)
->setFileWarrantyCard($wcard_filename)
// new fields
->setOdometer($req->request->get('odometer', 0))
->setDatePurchaseCustomer($date_pur_cust)
->setContactNumber($req->request->get('contact_num'))
->setCustomerAddress($req->request->get('cust_address'))
->setDealerName($req->request->get('dealer_name'))
->setDealerAddress($req->request->get('dealer_address'))
->setValidated(false);
// TODO: check for date purchase and date expire
@ -2987,6 +3165,10 @@ class APIController extends Controller implements LoggedController
// set data to retrun to user
$res->setData($data);
// send sms
error_log('sending sms to - ' . $this->session->getPhoneNumber());
$rt->sendSMS($this->session->getPhoneNumber(), 'MOTOLITE', $sms_msg);
return $res;
}

View file

@ -129,7 +129,8 @@ class BatterySizeController extends Controller
$obj->setName($req->request->get('name'))
->setTIPriceMotolite($req->request->get('tip_motolite'))
->setTIPricePremium($req->request->get('tip_premium'))
->setTIPriceOther($req->request->get('tip_other'));
->setTIPriceOther($req->request->get('tip_other'))
->setTIPriceLazada($req->request->get('tip_lazada'));
}
public function addSubmit(Request $req, ValidatorInterface $validator)

View file

@ -49,6 +49,7 @@ class BatteryController extends APIController
'container_size_name' => $csize_name,
'date_update' => $batt->getDateUpdate()->format('YmdHis'),
'flag_new' => $batt->isNew(),
'flag_inventory' => $batt->isInventory(),
];
}

View file

@ -0,0 +1,502 @@
<?php
namespace App\Controller\CAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Service\RisingTideGateway;
use App\Entity\WarrantySerial;
use App\Entity\Warranty;
use App\Entity\BatteryModel;
use App\Entity\BatterySize;
use App\Entity\SAPBattery;
use App\Entity\SAPBatterySize;
use App\Entity\SAPBatteryBrand;
use App\Entity\PrivacyPolicy;
use App\Entity\Customer;
use App\Entity\CustomerVehicle;
use App\Entity\Vehicle;
use App\Ramcar\NameValue;
use App\Ramcar\WarrantyClass;
use App\Ramcar\WarrantyStatus;
use App\Ramcar\FuelType;
use App\Ramcar\VehicleStatusCondition;
use DateTime;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
// third party API
class CustomerWarrantyController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
protected function checkMissingParameters(Request $req, $params = [])
{
$missing = [];
// check if parameters are there
foreach ($params as $param)
{
if ($req->getMethod() == 'GET')
{
$check = $req->query->get($param);
if (empty($check))
$missing[] = $param;
}
else if ($req->getMethod() == 'POST')
{
$check = $req->request->get($param);
if (empty($check))
$missing[] = $param;
}
else
return $params;
}
return $missing;
}
protected function checkRequiredParams(Request $req, $params)
{
// check required parameters
$missing = $this->checkMissingParameters($req, $params);
if (count($missing) > 0)
{
$miss_string = implode(', ', $missing);
return new APIResponse(false, 'Missing parameter(s): ' . $miss_string);
}
return true;
}
protected function cleanSerial($serial)
{
return trim(strtoupper($serial));
}
protected function cleanPlateNumber($plate_num)
{
return preg_replace('/\s+/', '', strtoupper($plate_num));
}
public function check($serial, EntityManagerInterface $em, Request $req)
{
// check required parameters
$required_params = [];
$res = $this->checkRequiredParams($req, $required_params);
if (!$res)
return $res;
error_log('check warranty serial');
// check if warranty serial is there
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
$batt = null;
$is_registered = false;
if ($warr_serial == null)
{
return new APIResponse(false, 'Invalid warranty serial code.');
}
$today = new DateTime();
// if we have a warranty entry for the serial already
if ($warr != null)
{
error_log('already have warranty.');
$warr_plate = $warr->getPlateNumber();
$is_registered = true;
// null mobile number should be blank string instead
if ($warr->getMobileNumber() == null)
$mobile_num = '';
else
$mobile_num = $warr->getMobileNumber();
// purchase date of customer
if ($warr->getDatePurchaseCustomer() != null)
$date_purchase_cust = $warr->getDatePurchaseCustomer()->format('Y-m-d');
else
$date_purchase_cust = $today->format('Y-m-d');
// invoice
if ($warr->getFileInvoice() != null)
$invoice_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileInvoice();
else
$invoice_url = '';
// warranty card
if ($warr->getFileWarrantyCard() != null)
$warr_card_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileWarrantyCard();
else
$warr_card_url = '';
// vehicle
if ($warr->getVehicle() != null)
{
$v = $warr->getVehicle();
$vmfg_id = $v->getManufacturer()->getID();
$vmake_id = $v->getID();
}
else
{
$vmfg_id = null;
$vmake_id = null;
}
// customer
$cust = $warr->getCustomer();
if ($cust != null)
{
$cust_exists = true;
$priv_promo = $cust->getPrivacyPromo();
}
else
{
$cust_exists = false;
$priv_promo = false;
}
$customer = [
'first_name' => $warr->getFirstName(),
'last_name' => $warr->getLastName(),
'mobile_number' => $mobile_num,
'plate_number' => $warr_plate,
'email' => $warr->getEmail(),
'contact_num' => $warr->getContactNumber(),
'address' => $warr->getCustomerAddress(),
'priv_promo' => $priv_promo,
'exists' => $cust_exists,
];
$other_data = [
'odometer' => $warr->getOdometer(),
'date_purchase' => $date_purchase_cust,
'invoice' => $invoice_url,
'warr_card' => $warr_card_url,
'vmfg_id' => $vmfg_id,
'vmake_id' => $vmake_id,
'vmodel' => $warr->getVehicleModelYear(),
'dealer_name' => $warr->getDealerName(),
'dealer_address' => $warr->getDealerAddress(),
];
}
else
{
$customer = [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
'email' => '',
'contact_num' => '',
'address' => '',
'priv_promo' => false,
'exists' => false,
];
$other_data = [
'odometer' => 0,
'date_purchase' => $today->format('Y-m-d'),
'invoice' => '',
'warr_card' => '',
'vmfg_id' => null,
'vmake_id' => null,
'vmodel' => '',
'dealer_name' => '',
'dealer_address' => '',
];
}
$sku = $warr_serial->getSKU();
$batt = $em->getRepository(SAPBattery::class)->find($sku);
// TODO: put this in a config file
$image_url = $req->getSchemeAndHttpHost() . '/battery/generic.png';
if ($batt != null)
{
$battery = [
'brand' => $batt->getBrand()->getName(),
'size' => $batt->getSize()->getName(),
'image_url' => $image_url,
];
}
else
{
$battery = [
'brand' => '',
'size' => '',
'image_url' => '',
];
}
// populate data
$data = [
'is_valid' => true,
'is_registered' => $is_registered,
'customer' => $customer,
'battery' => $battery,
'odometer' => $other_data['odometer'],
'invoice' => $other_data['invoice'],
'warr_card' => $other_data['warr_card'],
'date_purchase' => $other_data['date_purchase'],
'vmfg_id' => $other_data['vmfg_id'],
'vehicle_id' => $other_data['vmake_id'],
'vmodel' => $other_data['vmodel'],
'dealer_name' => $other_data['dealer_name'],
'dealer_address' => $other_data['dealer_address'],
];
return new APIResponse(true, 'Warranty found.', $data);
}
public function register($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt, TranslatorInterface $trans)
{
error_log('HERE - register');
// check required parameters
$required_params = [
'first_name',
'last_name',
'plate_num'
];
$res = $this->checkRequiredParams($req, $required_params);
if (!$res)
return $res;
// file uploads
$invoice = $req->files->get('invoice');
$warr_card = $req->files->get('warr_card');
error_log('handling file uploads');
// process picture uploads
$upload_dir = $kernel->getProjectDir() . '/public/warranty_uploads';
$inv_filename = $this->handlePictureUpload($invoice, $upload_dir, $serial, 'invoice');
$wcard_filename = $this->handlePictureUpload($warr_card, $upload_dir, $serial, 'wcard');
// do actual registering
$res = $this->updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename, $wcard_filename);
// flush to db
$em->flush();
return $res;
return new APIResponse(true, 'Warranty registered.');
}
// TODO: move this to a service, since it's shared by all warranty updaters
protected function handlePictureUpload($file, $target_dir, $serial, $name)
{
error_log("handling $name upload");
// no file sent
if ($file == null)
{
error_log('no file');
return null;
}
// create target dir if it doesn't exist
if (!file_exists($target_dir))
{
if (!mkdir($target_dir, 0744, true))
{
error_log('failed to create folder for warranty pictures');
return null;
}
}
// move file
$filename = $name . '.' . $file->getClientOriginalExtension();
$file->move($target_dir . '/' . $serial, $filename);
error_log("filename - $filename");
error_log($target_dir . '/' . $serial . '/' . $filename);
return $serial . '/' . $filename;
}
protected function updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null)
{
$plate_num = $this->cleanPlateNumber($req->request->get('plate_num'));
error_log('warranty serial check');
// get serial
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
if ($warr_serial == null)
{
return new APIResponse(false, 'Invalid warranty serial code.');
}
// check if warranty exists already
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
// skip warranty if it already exists
$cust = null;
$sms_message = '';
if ($warr != null)
{
$warr_plate_num = $this->cleanPlateNumber($warr->getPlateNumber());
if ($plate_num != $warr_plate_num)
{
return new APIResponse(false, 'Plate number does not match vehicle registered to warranty.');
}
// get customer
$cust = $warr->getCustomer();
$sms_message = $trans->trans('warranty_update_confirm');
}
else
{
$warr = new Warranty();
$sms_message = $trans->trans('warranty_register_confirm');
}
error_log('sap battery check');
// get sap battery
$sku = $warr_serial->getSKU();
$sap_bty = $em->getRepository(SAPBattery::class)->find($sku);
if ($sap_bty == null)
{
return new APIResponse(false, 'Could not find battery entry for warranty.');
}
// vehicle fetch
$vmake_id = $req->request->get('vmake_id');
$vehicle = null;
if ($vmake_id != null)
{
$vehicle = $em->getRepository(Vehicle::class)->find($vmake_id);
if ($vehicle == null)
{
return new APIResponse(false, 'Could not find vehicle specified for warranty.');
}
}
error_log('date check');
// default date purchase to today
// NOTE: might need to change this later
$date_pur = new DateTime();
// get date purchase specified by customer
$date_pur_cust = DateTime::createFromFormat('Y-m-d', $req->request->get('date_purchase'));
if (!$date_pur_cust)
{
return new APIResponse(false, 'Invalid date format for date of purchase.');
}
// chstomer check
$priv_promo = $req->request->get('priv_promo', false);
if ($cust == null)
{
// if no customer yet, create one and fill in fields
$cust = new Customer();
$cust->setFirstName($req->request->get('first_name'))
->setLastName($req->request->get('last_name'))
->setEmail($req->request->get('email'))
->setCreateSource('web_warranty')
->setPrivacyPromo($priv_promo)
->setPhoneMobile($req->request->get('contact_num'));
$em->persist($cust);
}
else
{
// only update privacy promo
$cust->setPrivacyPromo($priv_promo);
}
error_log('update entity / database');
// create or update warranty entry
$warr->setSerial($serial)
->setFirstName($req->request->get('first_name'))
->setLastName($req->request->get('last_name'))
->setEmail($req->request->get('email'))
->setPlateNumber($req->request->get('plate_num'))
// TODO: figure out how to compute date of purchase
->setDatePurchase($date_pur)
// TODO: set status
// ->setStatus()
// TODO: set battery model and size id
// ->setBatterySize()
// ->setBatteryModel()
->setSAPBattery($sap_bty)
// ->setMobileNumber(substr($this->session->getPhoneNumber(), 2))
->setActivated(true)
// files
->setFileInvoice($inv_filename)
->setFileWarrantyCard($wcard_filename)
// new fields
->setOdometer($req->request->get('odometer', 0))
->setDatePurchaseCustomer($date_pur_cust)
->setContactNumber($req->request->get('contact_num'))
->setCustomerAddress($req->request->get('cust_address'))
->setDealerName($req->request->get('dealer_name'))
->setDealerAddress($req->request->get('dealer_address'))
->setVehicle($vehicle)
->setVehicleModelYear($req->request->get('vmodel'))
->setDealerName($req->request->get('dealer_name'))
->setDealerAddress($req->request->get('dealer_address'))
->setCustomer($cust)
->setValidated(false);
// TODO: check for date purchase and date expire
$em->persist($warr);
// TODO: check if we need to do anyting else
$data = [];
// send sms confirmation
$this->sendSMSConfirmation($rt, $req->request->get('contact_num'), $sms_message);
return new APIResponse(true, 'Warranty registered.', $data);
}
protected function sendSMSConfirmation($rt, $num, $message)
{
$clean_num = trim($num);
// check if number is valid
// number should have 11 to 12 characters
if (strlen($clean_num) < 11 || strlen($clean_num) > 12)
return false;
// check if numeric
if (!is_numeric($clean_num))
return false;
// number should begin with 0 or 6
if ($clean_num[0] != '0' && $clean_num[0] != '6')
return false;
error_log('sending sms to - ' . $clean_num);
$rt->sendSMS($clean_num, 'MOTOLITE', $message);
}
}

View file

@ -44,6 +44,35 @@ class VehicleController extends APIController
return new APIResponse(true, 'Vehicle manufacturers loaded.', $data);
}
public function getByManufacturer($mfg_id, EntityManagerInterface $em)
{
$this->denyAccessUnlessGranted('vehicle.list', null, 'No access.');
$mfg = $this->em->getRepository(VehicleManufacturer::class)->find($mfg_id);
// manufacturer not found
if ($mfg == null)
{
return new APIResponse(false, 'No vehicle manufacturer found with that Id.', null, 404);
}
// get all vehicles from manufacturer
$vehicles = $mfg->getVehicles();
foreach($vehicles as $vehicle)
{
$make_data[] = [
'id' => $vehicle->getID(),
'mfg_id' => $vehicle->getManufacturer()->getID(),
'make' => $vehicle->getMake(),
'model' => $vehicle->getModelYearFormatted(),
];
}
// TODO: need to add manufacturer details
return new APIResponse(true, 'Vehicles loaded.', $data);
}
public function list(EntityManagerInterface $em)
{
$this->denyAccessUnlessGranted('vehicle.list', null, 'No access.');

View file

@ -38,6 +38,7 @@ use Catalyst\MenuBundle\Annotation\Menu;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
use DateTime;
use PDO;
class ReportController extends Controller
{
@ -1016,6 +1017,64 @@ class ReportController extends Controller
}
/**
* @Menu(selected="outlet_list")
*/
public function customerSourceForm()
{
$this->denyAccessUnlessGranted('report.customer.source', null, 'No access.');
return $this->render('report/customer-source/form.html.twig');
}
public function customerSourceSubmit(Request $req, EntityManagerInterface $em)
{
// get dates
$raw_date_start = $req->request->get('date_start');
$raw_date_end = $req->request->get('date_end');
$date_start = DateTime::createFromFormat('m/d/Y', $raw_date_start);
$date_end = DateTime::createFromFormat('m/d/Y', $raw_date_end);
$data = $this->getCustomerSourceDetails($req, $em);
$resp = new StreamedResponse();
$resp->setCallback(function() use ($data) {
// csv output
$csv_handle = fopen('php://output', 'w+');
fputcsv($csv_handle, [
'Customer ID',
'First Name',
'Last Name',
'Mobile Phone',
'Landline',
'Office Phone',
'Fax',
'Email Address',
'Vehicle Manufacturer',
'Vehicle Make',
'Model Year',
'Plate Number',
'Source',
'Date Created',
]);
foreach ($data as $row)
{
fputcsv($csv_handle, $row);
}
fclose($csv_handle);
});
$filename = 'customer_source_' . $date_start->format('Ymd') . '_' . $date_end->format('Ymd') . '.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)
{
@ -2018,4 +2077,85 @@ class ReportController extends Controller
return $result;
}
protected function getCustomerSourceDetails(Request $req, EntityManagerInterface $em)
{
// get dates
$raw_date_start = $req->request->get('date_start');
$raw_date_end = $req->request->get('date_end');
$date_start = DateTime::createFromFormat('m/d/Y', $raw_date_start);
$date_end = DateTime::createFromFormat('m/d/Y', $raw_date_end);
// change to this format: Y-m-d H:i:s
$new_date_start = $date_start->format('Y-m-d H:i:s');
$new_date_end = $date_end->format('Y-m-d H:i:s');
// get all mobile user customer id hash
$resq_cust_ids = $this->getRESQCustomerIDs($em);
// pdo connection
$db = $em->getConnection();
// get all customers
$sql = 'select c.id, c.first_name, c.last_name, c.phone_mobile, c.phone_landline, c.phone_office, c.phone_fax, c.email, c.flag_mobile_app, vm.name, v.make, cv.model_year, cv.plate_number, c.date_create from customer c, customer_vehicle cv, vehicle v, vehicle_manufacturer vm where c.date_create >= :date_start and c.date_create <= :date_end and c.id = cv.customer_id and cv.vehicle_id = v.id and v.manufacturer_id = vm.id';
$stmt = $db->prepare($sql);
$stmt->execute([
'date_start' => $new_date_start,
'date_end' => $new_date_end,
]);
$result = [];
// go through rows
while ($row = $stmt->fetch(PDO::FETCH_NUM))
{
// TODO: find customer source
// NOTE: flag_mobile_app is 0 for some reason
// customer source
if (isset($resq_cust_ids[$row[0]]))
$source = 'resq';
else
$source = 'crm / owr';
$result[] = [
$row[0], // id
$row[1], // first name
$row[2], // last name
$row[3], // phone - mobile
$row[4], // phone - landline
$row[5], // phone - office
$row[6], // phone - fax
$row[7], // email
$row[9], // vehicle manufacturer
$row[10], // vehicle make
$row[11], // vehicle model
$row[12], // plate number
$source, // customer source
$row[13],
];
}
return $result;
}
protected function getRESQCustomerIDs(EntityManagerInterface $em)
{
// pdo connection
$db = $em->getConnection();
// get all customer ids of all mobile sessions
$sql = 'select distinct customer_id from mobile_session';
$stmt = $db->prepare($sql);
$stmt->execute();
$res = $stmt->fetchAll();
$cust_ids = [];
foreach ($res as $cust)
{
$cust_ids[$cust['customer_id']] = $cust['customer_id'];
}
return $cust_ids;
}
}

View file

@ -171,9 +171,12 @@ class SAPBatteryController extends Controller
$error_array['id'] = 'SAP code is required.';
$flag_new = $req->request->get('flag_new', false);
$flag_inventory = $req->request->get('flag_inventory', false);
// set and save values
$row->setID($id)
->setNew($flag_new);
->setNew($flag_new)
->setInventory($flag_inventory);
// custom validation for battery brand
$brand = $em->getRepository(SAPBatteryBrand::class)
@ -277,9 +280,12 @@ class SAPBatteryController extends Controller
$error_array['id'] = 'SAP code is required.';
$flag_new = $req->request->get('flag_new', false);
$flag_inventory = $req->request->get('flag_inventory', false);
// set and save values
$row->setID($id)
->setNew($flag_new);
->setNew($flag_new)
->setInventory($flag_inventory);
// custom validation for battery brand
$brand = $em->getRepository(SAPBatteryBrand::class)

View file

@ -51,12 +51,19 @@ class BatterySize
*/
protected $tip_other;
// lazada trade-in price
/**
* @ORM\Column(type="decimal", precision=7, scale=2)
*/
protected $tip_lazada;
public function __construct()
{
$this->batteries = new ArrayCollection();
$this->tip_motolite = 0;
$this->tip_premium = 0;
$this->tip_other = 0;
$this->tip_lazada = 0;
}
public function getID()
@ -130,4 +137,16 @@ class BatterySize
{
return $this->tip_other;
}
public function setTIPriceLazada($price)
{
$this->tip_lazada = $price;
return $this;
}
public function getTIPriceLazada()
{
return $this->tip_lazada;
}
}

View file

@ -192,6 +192,22 @@ class Customer
*/
protected $date_create;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
protected $flag_research_sms;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
protected $flag_research_email;
// where customer was created from
/**
* @ORM\Column(type="string", length=80, options={"default": "legacy"})
*/
protected $create_source;
public function __construct()
{
$this->numbers = new ArrayCollection();
@ -222,8 +238,12 @@ class Customer
$this->flag_promo_email = false;
$this->flag_promo_sms = false;
$this->flag_dpa_consent = false;
$this->flag_research_sms = false;
$this->flag_research_email = false;
$this->date_create = new DateTime();
$this->create_source = 'unknown';
}
public function getID()
@ -555,4 +575,37 @@ class Customer
{
return $this->flag_dpa_consent;
}
public function setResearchSms($flag_research_sms = true)
{
$this->flag_research_sms = $flag_research_sms;
return $this;
}
public function isResearchSms()
{
return $this->flag_research_sms;
}
public function setResearchEmail($flag_research_email = true)
{
$this->flag_research_email = $flag_research_email;
return $this;
}
public function isResearchEmail()
{
return $this->flag_research_email;
}
public function setCreateSource($source)
{
$this->create_source = $source;
return $this;
}
public function getCreateSource()
{
return $this->create_source;
}
}

View file

@ -58,10 +58,17 @@ class SAPBattery
*/
protected $container_size;
// flag to indicate if this SAP battery is inventory or non-inventory
/**
* @ORM\Column(type="boolean")
*/
protected $flag_inventory;
public function __construct()
{
$this->date_create = new DateTime();
$this->flag_new = false;
$this->flag_inventory = false;
}
public function setID($id)
@ -129,4 +136,14 @@ class SAPBattery
return $this->container_size;
}
public function setInventory($inventory = false)
{
$this->flag_inventory = $inventory;
return $this;
}
public function isInventory()
{
return $this->flag_inventory;
}
}

View file

@ -141,6 +141,87 @@ class Warranty
*/
protected $privacy_policy;
// NOTE: the following were added later on, so they should all be nullable or have defaults,
// otherwise we get issues
// invoice picture
/**
* @ORM\Column(type="string", length=80, nullable=true)
*/
protected $file_invoice;
// warranty card picture
/**
* @ORM\Column(type="string", length=80, nullable=true)
*/
protected $file_warr_card;
// vehicle
/**
* @ORM\ManyToOne(targetEntity="Vehicle")
* @ORM\JoinColumn(name="vehicle_id", referencedColumnName="id", nullable=true)
*/
protected $vehicle;
// vehicle model year
/**
* @ORM\Column(type="string", length=10, nullable=true)
*/
protected $v_model_year;
// odometer reading
/**
* @ORM\Column(type="integer", nullable=true)
*/
protected $odometer;
// dealer name
/**
* @ORM\Column(type="string", length=80, nullable=true)
*/
protected $dealer_name;
// dealer address
/**
* @ORM\Column(type="string", length=180, nullable=true)
*/
protected $dealer_address;
// customer contact number
/**
* @ORM\Column(type="string", length=30, nullable=true)
*/
protected $contact_num;
// customer address
/**
* @ORM\Column(type="string", length=280, nullable=true)
*/
protected $cust_address;
// date purchase as specified by customer
// TODO: currently this does not affect warranty, someone will have to view this and set
// actual purchase date
/**
* @ORM\Column(type="date", nullable=true)
*/
protected $date_purchase_cust;
// if the warranty has been validated by an agent
/**
* @ORM\Column(type="boolean", options={"default": false})
*/
protected $flag_validated;
// link to customer
// TODO: check if this is the best way to do it, we'll be creating a new customer for every warranty since there is no reliable way to match customer to existing
/**
* @ORM\ManyToOne(targetEntity="Customer")
* @ORM\JoinColumn(name="customer_id", referencedColumnName="id", nullable=true)
*/
protected $customer;
public function __construct()
{
$this->date_create = new DateTime();
@ -149,6 +230,8 @@ class Warranty
$this->date_claim = null;
$this->flag_activated = false;
$this->email = '';
$this->odometer = 0;
$this->flag_validated = false;
}
public function getID()
@ -412,4 +495,135 @@ class Warranty
return $this->privacy_policy;
}
public function setFileInvoice($file = null)
{
$this->file_invoice = $file;
return $this;
}
public function getFileInvoice()
{
return $this->file_invoice;
}
public function setFileWarrantyCard($file = null)
{
$this->file_warr_card = $file;
return $this;
}
public function getFileWarrantyCard()
{
return $this->file_warr_card;
}
public function setVehicle(Vehicle $v)
{
$this->vehicle = $v;
return $this;
}
public function getVehicle()
{
return $this->vehicle;
}
public function setVehicleModelYear($year)
{
$this->v_model_year = $year;
return $this;
}
public function getVehicleModelYear()
{
return $this->v_model_year;
}
public function setOdometer($odometer)
{
$this->odometer = $odometer;
return $this;
}
public function getOdometer()
{
return $this->odometer;
}
public function setDealerName($name)
{
$this->dealer_name = $name;
return $this;
}
public function getDealerName()
{
return $this->dealer_name;
}
public function setDealerAddress($address)
{
$this->dealer_address = $address;
return $this;
}
public function getDealerAddress()
{
return $this->dealer_address;
}
public function setContactNumber($contact_num)
{
$this->contact_num = $contact_num;
return $this;
}
public function getContactNumber()
{
return $this->contact_num;
}
public function setCustomerAddress($address)
{
$this->cust_address = $address;
return $this;
}
public function getCustomerAddress()
{
return $this->cust_address;
}
public function setDatePurchaseCustomer($date)
{
$this->date_purchase_cust = $date;
return $this;
}
public function getDatePurchaseCustomer()
{
return $this->date_purchase_cust;
}
public function setValidated($bool = true)
{
$this->flag_validated = $bool;
return $this;
}
public function isValidated()
{
return $this->flag_validated;
}
public function setCustomer(Customer $customer)
{
$this->customer = $customer;
return $this;
}
public function getCustomer()
{
return $this->customer;
}
}

View file

@ -539,6 +539,8 @@ class ResqCustomerHandler implements CustomerHandlerInterface
'flag_dpa_consent' => $customer->isDpaConsent(),
'flag_promo_sms' => $customer->isPromoSms(),
'flag_promo_email' => $customer->isPromoEmail(),
'flag_research_sms' => $customer->isResearchSms(),
'flag_research_email' => $customer->isResearchEmail(),
],
'vehicle' => [
'id' => $vehicle->getID(),
@ -599,7 +601,9 @@ class ResqCustomerHandler implements CustomerHandlerInterface
->setActive($req->request->get('flag_active') ? true : false)
->setPromoSms($req->request->get('flag_promo_sms', false))
->setPromoEmail($req->request->get('flag_promo_email', false))
->setDpaConsent($is_dpa_checked);
->setDpaConsent($is_dpa_checked)
->setResearchSms($req->request->get('flag_research_sms', false))
->setResearchEmail($req->request->get('flag_research_email', false));
// phone numbers
$obj->setPhoneMobile($req->request->get('phone_mobile'))

View file

@ -326,6 +326,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$customer->setEmail($req->request->get('customer_email'))
->setPromoSms($req->request->get('flag_promo_sms', false))
->setPromoEmail($req->request->get('flag_promo_email', false))
->setResearchSms($req->request->get('flag_research_sms', false))
->setResearchEmail($req->request->get('flag_research_email', false))
->setDpaConsent($is_dpa_checked);
}

View file

@ -113,6 +113,12 @@
"jdorn/sql-formatter": {
"version": "v1.2.17"
},
"microsoft/azure-storage-blob": {
"version": "1.5.2"
},
"microsoft/azure-storage-common": {
"version": "1.5.1"
},
"nikic/php-parser": {
"version": "v4.1.0"
},

View file

@ -241,6 +241,14 @@
SMS Messages Report
</span>
</a>
<a href="{{ url('rep_customer_source_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">
Customer Source Report
</span>
</a>
</li>
</ul>
</li>

View file

@ -70,7 +70,16 @@
<input type="text" name="tip_other" class="form-control m-input" value="{{ obj.getTIPriceOther }}">
<div class="form-control-feedback hide" data-field="tip_other"></div>
</div>
</div>
</div>
<div class="form-group m-form__group row no-border">
<label class="col-lg-3 col-form-label" data-field="tip_lazada">
{% trans %}battery_size_tradein_lazada{% endtrans %}
</label>
<div class="col-lg-9">
<input type="text" name="tip_lazada" class="form-control m-input" value="{{ obj.getTIPriceLazada }}">
<div class="form-control-feedback hide" data-field="tip_lazada"></div>
</div>
</div>
</div>
<div class="m-portlet__foot m-portlet__foot--fit">
<div class="m-form__actions m-form__actions--solid m-form__actions--right">

View file

@ -122,6 +122,27 @@
</div>
</div>
</div>
<div class="col-lg-4">
<div class="col-lg-12 form-group-inner">
<label data-field="source">Marketing Research</label>
<div class="m-checkbox-list">
<label class="m-checkbox">
<input type="checkbox" name="flag_research_sms" value="1"{{ obj.isResearchSms ? ' checked' }} >
SMS
<span></span>
<div class="form-control-feedback hide" data-field="flag_research_sms"></div>
</label>
<label class="m-checkbox">
<input type="checkbox" name="flag_research_email" value="1"{{ obj.isResearchEmail ? ' checked' }} >
Email
<span></span>
<div class="form-control-feedback hide" data-field="flag_research_email"></div>
</label>
</div>
</div>
</div>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-4">
{% if is_granted('customer.dpa') %}
<input type="checkbox" name="flag_dpa_consent" id="flag-dpa_consent" value="1"{{ obj.isDpaConsent ? ' checked' }} >
@ -129,9 +150,7 @@
<div class="form-control-feedback hide" data-field="flag_dpa_consent"></div>
{% endif %}
</div>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-12">
<div class="col-lg-4">
<span class="m-switch m-switch--icon block-switch">
<label>
<input type="checkbox" name="flag_active" id="flag_active" value="1"{{ obj.isActive() ? ' checked' }}>

View file

@ -153,6 +153,53 @@
<div class="form-control-feedback hide" data-field="customer_customer_notes"></div>
</div>
<div class="col-lg-6">
<div class="col-lg-12 form-group-inner">
<label>Email Address</label>
<input type="text" name="customer_email" id="customer-email" class="form-control m-input" value="{{ obj.getCustomer ? obj.getCustomer.getEmail|default('') }}" data-vehicle-field="1" >
<div class="form-control-feedback hide" data-field="customer_email"></div>
</div>
</div>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-3">
<div class="col-lg-12 form-group-inner">
<label data-field="source">Marketing Promo</label>
<div class="m-checkbox-list">
<label class="m-checkbox">
<input type="checkbox" name="flag_promo_sms" id="flag-promo-sms" value="1"{{ obj.getCustomer ? obj.getCustomer.isPromoSms ? ' checked' }} >
SMS
<span></span>
<div class="form-control-feedback hide" data-field="flag_promo_sms"></div>
</label>
<label class="m-checkbox">
<input type="checkbox" name="flag_promo_email" id="flag-promo-email" value="1"{{ obj.getCustomer ? obj.getCustomer.isPromoEmail ? ' checked' }} >
Email
<span></span>
<div class="form-control-feedback hide" data-field="flag_promo_email"></div>
</label>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="col-lg-12 form-group-inner">
<label data-field="source">Marketing Research</label>
<div class="m-checkbox-list">
<label class="m-checkbox">
<input type="checkbox" name="flag_research_sms" id="flag-research-sms" value="1"{{ obj.getCustomer ? obj.getCustomer.isResearchSms ? ' checked' }} >
SMS
<span></span>
<div class="form-control-feedback hide" data-field="flag_research_sms"></div>
</label>
<label class="m-checkbox">
<input type="checkbox" name="flag_research_email" id="flag-research-email" "value="1"{{ obj.getCustomer ? obj.getCustomer.isResearchEmail ? ' checked' }} >
Email
<span></span>
<div class="form-control-feedback hide" data-field="flag_research_email"></div>
</label>
</div>
</div>
</div>
<div class="col-lg-3">
{% if is_granted('customer.dpa') %}
<input type="checkbox" name="flag_dpa_consent" id="flag-dpa-consent" value="1"{{ obj.getCustomer ? obj.getCustomer.isDpaConsent ? ' checked' }} i>
<label class="switch-label">With DPA Consent</label>
@ -219,6 +266,15 @@
<input type="text" name="warranty_expiration" id="warranty-expiration" class="form-control m-input" value="{{ obj.getCustomerVehicle.getCurrentBattery|default(false) ? obj.getCustomerVehicle.getWarrantyExpiration|date("d M Y") : '' }}" data-vehicle-field="1" disabled>
<div class="form-control-feedback hide" data-field="warranty_expiration"></div>
</div>
<div class="col-g-3">
<span class="m-switch m-switch--icon block-switch">
<label>
<input type="checkbox" name="flag_motolite_battery" id="flag-motolite-battery" value="1" {{ obj.getCustomerVehicle.getCurrentBattery|default(false) ? obj.getCustomerVehicle.hasMotoliteBattery ? ' checked' }} disabled>
<label class="switch-label">This vehicle is using a Motolite battery</label>
<span></span>
</label>
</span>
</div>
{% if obj.getCustomerVehicle %}
<div class="col-lg-3">
<div><label>&nbsp;</label></div>
@ -353,7 +409,7 @@
<br>
<div class="col-lg-12 form-group-inner">
<label data-field="delivery_instructions">Delivery Instructions</label>
<textarea name="delivery_instructions" class="form-control m-input" rows="4">{{ obj.getDeliveryInstructions }}</textarea>
<textarea name="delivery_instructions" class="form-control m-input" rows="7">{{ obj.getDeliveryInstructions }}</textarea>
</div>
</div>
<div class="col-lg-6">
@ -375,34 +431,6 @@
<div class="form-control-feedback hide" data-field="date_transaction"></div>
</div>
</div>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-6">
<div class="col-lg-12 form-group-inner">
<label data-field="source">Marketing Promo</label>
<div class="m-checkbox-list">
<label class="m-checkbox">
<input type="checkbox" name="flag_promo_sms" id="flag-promo-sms" value="1"{{ obj.getCustomer ? obj.getCustomer.isPromoSms ? ' checked' }} >
SMS
<span></span>
<div class="form-control-feedback hide" data-field="flag_promo_sms"></div>
</label>
<label class="m-checkbox">
<input type="checkbox" name="flag_promo_email" id="flag-promo-email" value="1"{{ obj.getCustomer ? obj.getCustomer.isPromoEmail ? ' checked' }} >
Email
<span></span>
<div class="form-control-feedback hide" data-field="flag_promo_email"></div>
</label>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="col-lg-12 form-group-inner">
<label>Email Address</label>
<input type="text" name="customer_email" id="customer-email" class="form-control m-input" value="{{ obj.getCustomer ? obj.getCustomer.getEmail|default('') }}" data-vehicle-field="1" >
<div class="form-control-feedback hide" data-field="customer_email"></div>
</div>
</div>
</div>
<!--
<div class="form-group m-form__group row">
@ -1175,6 +1203,8 @@ $(function() {
$("#flag-dpa-consent").prop("disabled", true);
$("#flag-promo-sms").prop("disabled", true);
$("#flag-promo-email").prop("disabled", true);
$("#flag-research-sms").prop("disabled", true);
$("#flag-research-email").prop("disabled", true);
{% endif %}
$("#row-form").submit(function(e) {
@ -1334,6 +1364,12 @@ $(function() {
if (vdata.customer.flag_promo_email === true) {
$("#flag-promo-email").prop("checked", true);
}
if (vdata.customer.flag_research_sms === true) {
$("#flag-research-sms").prop("checked", true);
}
if (vdata.customer.flag_research_email === true) {
$("#flag-research-email").prop("checked", true);
}
// set hidden customer id
$("#cid").val(vdata.customer.id);
@ -1342,8 +1378,10 @@ $(function() {
$("#current-battery").val(vdata.battery.mfg_name + " " + vdata.battery.model_name + " " + vdata.battery.size_name + " (" + vdata.battery.prod_code + ")");
$("#warranty-code").val(vdata.battery.warranty_code);
$("#warranty-expiration").val(vdata.battery.warranty_expiration);
$("#flag-motolite-battery").prop("checked", true);
} else {
$("#current-battery, #warranty-code, #warranty-expiration").val("No current battery").css('color', '#f4516c');
$("#flag-motolite-battery").prop("checked", false);
}
})
}).focus();
@ -1377,6 +1415,8 @@ $(function() {
$("#flag-dpa-consent").prop("checked", false);
$("#flag-promo-sms").prop("checked", false);
$("#flag-promo-email").prop("checked", false);
$("#flag-research-sms").prop("checked", false);
$("#flag-research-email").prop("checked", false);
}
// datepicker

View file

@ -0,0 +1,82 @@
{% 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">Customer Source 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-calendar"></i>
</span>
<h3 class="m-portlet__head-text">
Select a date range
</h3>
</div>
</div>
</div>
<form id="row-form" autocomplete="off" class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ url('rep_customer_source_submit') }}">
<div class="m-portlet__body">
<div class="form-group m-form__group row">
<div class="input-daterange input-group" id="date-range">
<input role="presentation" type="text" class="form-control m-input" name="date_start" placeholder="Start date" />
<div class="input-group-append">
<span class="input-group-text"><i class="la la-ellipsis-h"></i></span>
</div>
<input role="presentation" type="text" class="form-control" name="date_end" placeholder="End date" />
</div>
</div>
</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">Submit</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(function() {
$("#date-range").datepicker({
orientation: "bottom"
});
$("#row-form").submit(function(e) {
var form = $(this);
if (!$("[name='date_start']").val() || !$("[name='date_end']").val()) {
e.preventDefault();
swal({
title: 'Whoops!',
text: 'Please fill in both date fields.',
type: 'warning'
});
return false;
}
});
});
</script>
{% endblock %}

View file

@ -86,15 +86,25 @@
</select>
<div class="form-control-feedback hide" data-field="container_size"></div>
</div>
<div class="col-lg-4">
<span class="m-switch m-switch--icon block-switch">
<label>
<input type="checkbox" name="flag_new" id="flag_new" value="1"{{ obj.isNew() ? ' checked' }}>
<label class="switch-label">New</label>
<span></span>
</label>
</span>
<div class="form-control-feedback hide" data-field="flag_new"></div>
</div>
<div class="col-lg-4">
<span class="m-switch m-switch--icon block-switch">
<label>
<input type="checkbox" name="flag_new" id="flag_new" value="1"{{ obj.isNew() ? ' checked' }}>
<label class="switch-label">New</label>
<input type="checkbox" name="flag_inventory" id="flag_inventory" value="1"{{ obj.isInventory() ? ' checked' }}>
<label class="switch-label">Inventory</label>
<span></span>
</label>
</span>
<div class="form-control-feedback hide" data-field="flag_new"></div>
<div class="form-control-feedback hide" data-field="flag_inventory"></div>
</div>
</div>
</div>

View file

@ -8,6 +8,7 @@ copyright: Motolite Res-Q
battery_size_tradein_brand: Trade-in Motolite
battery_size_tradein_premium: Trade-in Premium
battery_size_tradein_other: Trade-in Other
battery_size_tradein_lazada: Trade-in Lazada
add_cust_vehicle_battery_info: This vehicle is using a Motolite battery
jo_title_pdf: Motolite Res-Q Job Order
country_code_prefix: '+63'
@ -25,3 +26,7 @@ image_jo_pdf: /public/assets/images/logo-resq.png
default_lat: 14.6091
default_long: 121.0223
default_region: ph
# warranty text
warranty_register_confirm: Congratulations! Your warranty has been successfully registered! Read about Motolite's privacy policy at https://www.motolite.com/privacy/.
warranty_update_confirm: Congratulations! Your warranty has been successfully updated! Read about Motolite's privacy policy at https://www.motolite.com/privacy/.

View file

@ -0,0 +1,7 @@
#!/bin/sh
MONTH=`date +"%m"`
YEAR=`date +"%Y"`
FILE_DATE=`date +"%Y%m%d"`
FILE="/var/www/resq/public/cust_reports/cust_report_$FILE_DATE.csv"
/var/www/resq/bin/console report:customer_source $YEAR $MONTH $FILE

View file

@ -0,0 +1,50 @@
<?php
// load csv
$csv = fopen($argv[1], 'r');
$dsn = $argv[2];
$user = $argv[3];
$pass = $argv[4];
// connect to db
$db = new PDO($dsn, $user, $pass);
// prepared statement
$sth = $db->prepare('insert into warranty_serial (id, sku, date_create, source) values (:serial, :sku, :date_create, :source)');
// go through rows
$counter = 0;
$source = 'motiv';
while (($row = fgetcsv($csv)) !== false)
{
// skip first line
if ($counter == 0)
{
$counter++;
continue;
}
$serial = trim(strtoupper($row[0]));
$sku = trim($row[1]);
$date_create = $row[2];
$ref_id = $row[3];
$res = $sth->execute([
':serial' => $serial,
':sku' => $sku,
':date_create' => $date_create,
':source' => $source
]);
if (!$res)
{
$err = $sth->errorInfo();
echo "Error ($serial) - " . $err[2] . "\n";
}
}
// close file
fclose($csv);

View file

@ -0,0 +1,11 @@
DispatcheDate,Sku,SerialNumber
2020-08-07 05:32:04.537,WMGL23DL-CPNMB-L,MGS706202004
2020-08-07 05:32:04.537,WMGL23DL-CPNMB-L,MGS706202005
2020-08-07 05:32:04.537,WMGL23DL-CPNMB-L,MGS706202006
2020-08-08 09:27:14.480,WMXX26EL-CPN00-LX,MXS808202001
2020-08-08 09:31:48.737,WMXX26EL-CPN00-LX,MXS808202002
2020-08-08 10:27:08.117,WMXX26EL-CPN00-LX,MXS808202003
2020-08-08 10:41:10.060,WMXX26EL-CPN00-LX,MXS808202004
2020-08-08 10:41:10.060,WMXX26EL-CPN00-LX,MXS808202005
2020-08-08 10:41:10.060,WMXX26EL-CPN00-LX,MXS808202006
2020-10-05 13:53:57.000,ECHD26AL-SPN00-LX,CH2000012625

39
utils/test_azure/test.php Normal file
View file

@ -0,0 +1,39 @@
<?php
// NOTE: reference: https://github.com/Azure/azure-storage-php/blob/master/samples/BlobSamples.php
require_once(__DIR__ . '/../../vendor/autoload.php');
use MicrosoftAzure\Storage\Blob\BlobRestProxy;
use MicrosoftAzure\Storage\Common\ServiceException;
$blob_url = 'https://popappshopprodstorage.blob.core.windows.net/warranty';
$sas_token = 'sp=r&st=2021-03-18T08:26:36Z&se=2021-04-29T16:26:36Z&spr=https&sv=2020-02-10&sr=c&sig=Rwl3aCNThXEzuPjNB9sTvZzsx84ULDylyS1WtPwgyzg%3D';
$blob_url = 'https://popappshopprodstorage.blob.core.windows.net';
$sas_token = 'sp=r&st=2021-03-20T17:09:13Z&se=2021-04-01T01:09:13Z&spr=https&sv=2020-02-10&sr=c&sig=pU2fxj6eXALfGTTrsmaJ7W0QtdstyR88Xs5lvMJ35xQ%3D';
$conn_string = "BlobEndpoint=$blob_url;\nSharedAccessSignature=$sas_token";
$blob_client = BlobRestProxy::createBlobService($conn_string);
// NOTE: via download blob
$res = $blob_client->getBlob('warranty', 'Sample Result.csv');
// print_r($res);
file_put_contents("output.txt", $res->getContentStream());
/*
// NOTE: getting via url
echo $blob_client->getPsrPrimaryUri() . "\n";
$url = $blob_client->getPsrPrimaryUri() . '?' . $sas_token;
$url = $blob_url . '?' . $sas_token;
file_put_contents('output.txt', fopen($url, 'r'));
*/