diff --git a/.env.dist b/.env.dist index f170c3c9..a9fe4b6a 100644 --- a/.env.dist +++ b/.env.dist @@ -50,3 +50,6 @@ GEOFENCE_ENABLE=settotrueorfalse CVU_MFG_ID=insertmfgidforunknownvehicles CVU_BRAND_ID=insertbrandidforunknownvehicles +# country code prefix +COUNTRY_CODE=+insertcountrycodehere + diff --git a/catalyst/api-bundle/Command/TestAPICommand.php b/catalyst/api-bundle/Command/TestAPICommand.php index d32097fe..7e959808 100644 --- a/catalyst/api-bundle/Command/TestAPICommand.php +++ b/catalyst/api-bundle/Command/TestAPICommand.php @@ -53,16 +53,22 @@ class TestAPICommand extends Command 'date_expire' => '20191001', 'first_name' => 'First', 'last_name' => 'Last', - 'mobile_number' => '12345678910', + 'mobile_number' => '09231234567', ]; - $api->post('/capi/warranties', $params); + //$api->post('/capi/warranties', $params); // get all warranties - $api->get('/capi/warranties'); + $params = [ + 'order' => 'DESC', + 'limit' => '5', + 'start' => '1', + ]; + + $api->get('/capi/warranties', $params); // warranty find - $api->get('/capi/warranties/' . $serial); + //$api->get('/capi/warranties/' . $serial); // warranty update $id = 86811; @@ -77,7 +83,7 @@ class TestAPICommand extends Command 'last_name' => 'Last', 'mobile_number' => '123456789111', ]; - $api->post('/capi/warranties/'. $id, $params); + //$api->post('/capi/warranties/'. $id, $params); // warranty set privacy policy $id = 86811; @@ -85,7 +91,7 @@ class TestAPICommand extends Command $params = [ 'privacy_policy_id' => $policy_id, ]; - $api->post('/capi/warranties/' . $id .'/privacypolicy', $params); + //$api->post('/capi/warranties/' . $id .'/privacypolicy', $params); // warranty claim $id = 86811; @@ -93,27 +99,27 @@ class TestAPICommand extends Command $params = [ 'serial' => $serial, ]; - $api->post('/capi/warranties/' . $id . '/claim', $params); + //$api->post('/capi/warranties/' . $id . '/claim', $params); // warranty cancel $id = 86811; - $api->get('/capi/warranties/' . $id . '/cancel'); + //$api->get('/capi/warranties/' . $id . '/cancel'); // plate warranty - $api->get('/capi/plates/' . $plate_num . '/warranties'); + //$api->get('/capi/plates/' . $plate_num . '/warranties'); // warranty delete $id = 86811; - $api->post('/capi/warranties/' . $id . '/delete'); + //$api->post('/capi/warranties/' . $id . '/delete'); // battery - $api->get('/capi/battery_brands'); - $api->get('/capi/battery_sizes'); - $api->get('/capi/batteries'); + //$api->get('/capi/battery_brands'); + //$api->get('/capi/battery_sizes'); + //$api->get('/capi/batteries'); // vehicle - $api->get('/capi/vehicle_manufacturers'); - $api->get('/capi/vehicles'); + //$api->get('/capi/vehicle_manufacturers'); + //$api->get('/capi/vehicles'); // privacy policy $privacy_policy_id = 2; diff --git a/config/services.yaml b/config/services.yaml index 1ea6a25e..4249102e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -10,6 +10,7 @@ parameters: api_access_key: 'api_access_keys' app_acl_file: 'acl.yaml' app_access_key: 'access_keys' + cvu_brand_id: "%env(CVU_BRAND_ID)%" services: # default configuration for services in *this* file @@ -91,6 +92,10 @@ services: arguments: $geofence_flag: "%env(GEOFENCE_ENABLE)%" + App\Service\WarrantyHandler: + arguments: + $em: "@doctrine.orm.entity_manager" + App\Command\SetCustomerPrivacyPolicyCommand: arguments: $policy_promo: "%env(POLICY_PROMO)%" @@ -159,14 +164,26 @@ services: #App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator" # job order generator - App\Service\JobOrderHandler\CMBJobOrderHandler: ~ + #App\Service\JobOrderHandler\ResqJobOrderHandler: + # arguments: + # $country_code: "%env(COUNTRY_CODE)%" + + App\Service\JobOrderHandler\CMBJobOrderHandler: + arguments: + $country_code: "%env(COUNTRY_CODE)%" #job order generator interface App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\CMBJobOrderHandler" #App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\ResqJobOrderHandler" # customer generator - App\Service\CustomerHandler\CMBCustomerHandler: ~ + App\Service\CustomerHandler\CMBCustomerHandler: + arguments: + $country_code: "%env(COUNTRY_CODE)%" + + #App\Service\CustomerHandler\ResqCustomerHandler: + # arguments: + # $country_code: "%env(COUNTRY_CODE)%" # customer generator interface App\Service\CustomerHandlerInterface: "@App\\Service\\CustomerHandler\\CMBCustomerHandler" diff --git a/src/Command/ComputeWarrantyExpiryDateCommand.php b/src/Command/ComputeWarrantyExpiryDateCommand.php new file mode 100644 index 00000000..383370f7 --- /dev/null +++ b/src/Command/ComputeWarrantyExpiryDateCommand.php @@ -0,0 +1,75 @@ +em = $em; + $this->wh = $wh; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('warranty:computeexpirydate') + ->setDescription('Compute expiry date for existing warranties.') + ->setHelp('Compute expiry date for existing warranties.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $warr_q = $this->em->createQuery('select w from App\Entity\Warranty w where w.date_expire is null'); + $warranties = $warr_q->iterate(); + + foreach($warranties as $row) + { + $warr = $row[0]; + + error_log('Processing warranty for ' . $warr->getID()); + + $date_purchase = $warr->getDatePurchase(); + + $batteries = $this->wh->getBatteriesForWarranty($warr); + if (!empty($batteries)) + { + $warranty_class = $warr->getWarrantyClass(); + + $warr_period = $this->wh->getWarrantyPeriod($batteries, $warranty_class); + + if ($warr_period != null) + { + $expiry_date = $this->wh->computeDateExpire($date_purchase, $warr_period); + } + else + { + $expiry_date = $date_purchase; + } + + // save expiry date + $warr->setDateExpire($expiry_date); + + $this->em->persist($warr); + $this->em->flush(); + } + + $this->em->clear(); + } + } +} diff --git a/src/Command/CreateCustomerFromWarrantyCommand.php b/src/Command/CreateCustomerFromWarrantyCommand.php index 91ae38d1..e644fc06 100644 --- a/src/Command/CreateCustomerFromWarrantyCommand.php +++ b/src/Command/CreateCustomerFromWarrantyCommand.php @@ -7,7 +7,6 @@ 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; diff --git a/src/Command/UpdateCustomerVehicleWarrantyCommand.php b/src/Command/UpdateCustomerVehicleWarrantyCommand.php new file mode 100644 index 00000000..89b6e5e0 --- /dev/null +++ b/src/Command/UpdateCustomerVehicleWarrantyCommand.php @@ -0,0 +1,98 @@ +em = $em; + $this->wh = $wh; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('customervehicle:updatewarrantyinfo') + ->setDescription('Update customer vehicle warranty.') + ->setHelp('Update customer vehicle warranty.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + // get all warranties + // since it's possible that the same plate number will have multiple warranties, order them from earliest to latest + $warr_q = $this->em->createQuery('select w from App\Entity\Warranty w where w.plate_number is not null order by w.date_purchase asc'); + $warranties = $warr_q->iterate(); + + foreach ($warranties as $row) + { + $warr = $row[0]; + + // clean plate number + $plate_number = $this->wh->cleanPlateNumber($warr->getPlateNumber()); + + // get other warranty information + $serial = $warr->getSerial(); + $expiry_date = $warr->getDateExpire(); + + // TODO: check length of serial for now. Should not exceed 20. + // there is a warranty with 2 serial codes in live + // for now, ignore the warranty + if (strlen($serial) > 20) + { + continue; + } + + // find battery + $batteries = $this->wh->getBatteriesForWarranty($warr); + + // find customer vehicle using plate number + /* + error_log('Finding customer vehicle with plate number ' . $plate_number); + $cust_vehicles = $this->em->getRepository(CustomerVehicle::class)->findBy(['plate_number' => $plate_number]); + + if (!empty($cust_vehicles)) + { + if (!empty($batteries)) + { + // set current battery to the first battery in list. + // there are cases where multiple batteries linked to an SAP code. + $battery = $batteries[0]; + $battery_id = $battery->getID(); + } + $q = $this->em->createQuery('update App\Entity\CustomerVehicle cv + set cv.curr_battery = :batt_id, + cv.warranty_code = :serial, + cv.warranty_expiration = :expiry_date + where cv.plate_number = :plate_number') + ->setParameters([ + 'batt_id' => $battery_id, + 'serial' => $serial, + 'expiry_date' => $expiry_date, + 'plate_number' => $plate_number]); + $q->execute(); + + } */ + $this->wh->updateCustomerVehicle($serial, $batteries, $plate_number, $expiry_date); + + $this->em->detach($row[0]); + } + } +} diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index d76afffc..83ecf74a 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -17,10 +17,16 @@ 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; @@ -226,6 +232,9 @@ class WarrantyController extends APIController try { $em->persist($warr); + + $this->getCustomerFromMobile($em, $warr); + $em->flush(); } catch (UniqueConstraintViolationException $e) @@ -488,9 +497,156 @@ class WarrantyController extends APIController } $em->persist($warr); - $em->flush(); return new APIResponse(true, 'Privacy policy for warranty set successfully.'); } + + protected function getCustomerFromMobile($em, $warranty) + { + $w_mobile = $warranty->getMobileNumber(); + if (empty($w_mobile)) + { + return null; + } + + // set values for new customer vehicle + $w_plate_number = $this->cleanPlateNumber($warranty->getPlateNumber()); + + $cust_found = false; + + $w_mobile_num = trim($w_mobile); + + // 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)) + return null; + + /* + // 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; + */ + + $customers = $this->findCustomerByNumber($em, $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); + } + 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($em, $customer, $this->getDefaultVehicle($em), $w_plate_number); + } + } + } + // 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 = $warranty->getFirstName(); + $w_last_name = $warranty->getLastName(); + + $new_cust = new Customer(); + $new_cust->setFirstName($w_first_name) + ->setLastName($w_last_name) + ->setPhoneMobile($w_mobile_num); + + $em->persist($new_cust); + + $this->createCustomerVehicle($em, $new_cust, $this->getDefaultVehicle($em), $w_plate_number); + } + + $em->flush(); + $em->clear(); + } + + protected function getDefaultVehicle($em) + { + // get default vehicle + $cvu_brand_id = $this->getParameter('cvu_brand_id'); + $default_vehicle = $em->getRepository(Vehicle::class)->find($cvu_brand_id); + if ($default_vehicle == null) + { + $output->writeln("Need to add vehicle with default values."); + return null; + } + + return $default_vehicle; + } + + + protected function cleanPlateNumber($plate) + { + // remove spaces and make upper case + return strtoupper(str_replace(' ', '', $plate)); + } + + protected function createCustomerVehicle($em, 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); + + $em->persist($new_cv); + } + + + protected function findCustomerByNumber($em, $number) + { + $customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]); + return $customers; + } + } diff --git a/src/Controller/WarrantyController.php b/src/Controller/WarrantyController.php index ede93334..40afec1a 100644 --- a/src/Controller/WarrantyController.php +++ b/src/Controller/WarrantyController.php @@ -7,10 +7,14 @@ use App\Entity\SAPBattery; use App\Entity\Battery; use App\Entity\BatteryModel; use App\Entity\BatterySize; +use App\Entity\Invoice; +use App\Entity\CustomerVehicle; use App\Ramcar\WarrantyClass; use App\Ramcar\WarrantyStatus; +use App\Service\WarrantyHandler; + use Doctrine\ORM\Query; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\Request; @@ -372,13 +376,14 @@ class WarrantyController extends Controller /** * @Menu(selected="warranty_list") */ - public function uploadSubmit(Request $req, EntityManagerInterface $em) + public function uploadSubmit(Request $req, EntityManagerInterface $em, + WarrantyHandler $wh) { // retrieve temporary info for file $file = $req->files->get('csv_file'); // process the csv file - $inv_entries = $this->processWarrantyFile($file, $em); + $inv_entries = $this->processWarrantyFile($file, $em, $wh); $resp = new StreamedResponse(); $resp->setCallback(function() use($inv_entries) { @@ -422,7 +427,8 @@ class WarrantyController extends Controller return $resp; } - protected function processWarrantyFile(UploadedFile $csv_file, EntityManagerInterface $em) + protected function processWarrantyFile(UploadedFile $csv_file, EntityManagerInterface $em, + WarrantyHandler $wh) { // attempt to open file try @@ -469,10 +475,13 @@ class WarrantyController extends Controller $first_name = trim($fields[0]); $last_name = trim($fields[1]); $mobile_number = trim($fields[4]); - $plate_number = trim($fields[9]); + $plate = trim($fields[9]); $serial = trim($fields[10]); $purchase_date = trim($fields[12]); $battery_id = trim($fields[16]); + $batt_invoice = trim($fields[11]); + + $plate_number = $wh->cleanPlateNumber($plate); // check if purchase_date or plate_number or serial is empty or if // purchase date is valid @@ -509,7 +518,7 @@ class WarrantyController extends Controller 'vehicle_year' => trim($fields[8]), 'vehicle_plate_number' => $plate_number, 'battery_serial_number' => $serial, - 'battery_sales_invoice' => trim($fields[11]), + 'battery_sales_invoice' => $batt_invoice, 'battery_date_purchase' => $purchase_date, 'distributor_name' => trim($fields[13]), 'distributor_address' => trim($fields[14]), @@ -521,55 +530,65 @@ class WarrantyController extends Controller } else { + // additional validation + // check if serial number and plate number already exists + $warr_results = $em->getRepository(Warranty::class)->findBy(['serial' => $serial, 'plate_number' => $plate_number]); - // new warranty - $warranty = new Warranty(); + // get battery via the invoice because battery_id doesn't match what's in the live data + // get job order via invoice to get the warranty class + $warranty_class = ''; + $batt_list = array(); - // get the battery purchased - // check battery first. If not found, check sap_battery - $battery = $em->getRepository(Battery::class)->find($battery_id); - if ($battery != null) + // find invoice + $invoice = $em->getRepository(Invoice::class)->find($batt_invoice); + if (!empty($invoice)) { - // get the battery model and battery size - $model_id = $battery->getModel()->getID(); - $size_id = $battery->getSize()->getID(); + // get job order + $jo = $invoice->getJobOrder(); - $bty_model = $em->getRepository(BatteryModel::class)->find($model_id); - $bty_size = $em->getRepository(BatterySize::class)->find($size_id); + // get warranty class + $warranty_class = $jo->getWarrantyClass(); - if ($bty_model != null) + // get battery + $invoice_items = $invoice->getItems(); + foreach ($invoice_items as $item) { - $warranty->setBatteryModel($bty_model); + $battery = $item->getBattery(); + if ($battery != null) + { + $batt_list[] = $item->getBattery(); + } } + } - if ($bty_size != null) + if (!empty($warr_results)) + { + foreach($warr_results as $warr) { - $warranty->setBatterySize($bty_size); + // call service to check if warranty details is incomplete and then update warranty + // using details from csv file + error_log('Updating warranty for ' . $warr->getID()); + $wh->updateWarranty($warr, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase); } } else - { - // find battery in sap_battery - $battery = $em->getRepository(SAPBattery::class)->find($battery_id); - if ($battery != null) + { + // TODO: what if serial exists but plate number is different? + // check if just the serial exists + // if warranty exists, ignore for now + $w_results = $em->getRepository(Warranty::class)->findBy(['serial' => $serial]); + if (!empty($w_results)) { - // battery is SAPBattery - $warranty->setSAPBattery($battery); + continue; } + + error_log('Creating warranty for serial ' . $serial . ' and plate number ' . $plate_number); + + $wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } - - // 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(); } - + + $em->clear(); $row_num++; } @@ -595,4 +614,10 @@ class WarrantyController extends Controller ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); } } + + protected function cleanPlateNumber($plate) + { + // remove spaces and make upper case + return strtoupper(str_replace(' ', '', $plate)); + } } diff --git a/src/Entity/BatteryModel.php b/src/Entity/BatteryModel.php index 86f3b666..b516e8a6 100644 --- a/src/Entity/BatteryModel.php +++ b/src/Entity/BatteryModel.php @@ -68,6 +68,7 @@ class BatteryModel public function getBatteries() { + // TODO: fix this to be a proper getter function // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) diff --git a/src/Entity/BatterySize.php b/src/Entity/BatterySize.php index 021e115c..9fff4d44 100644 --- a/src/Entity/BatterySize.php +++ b/src/Entity/BatterySize.php @@ -89,6 +89,7 @@ class BatterySize public function getBatteries() { + // TODO: fix this to be a proper getter function // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index abe8286b..b96dfae9 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -14,9 +14,6 @@ use App\Ramcar\CustomerClassification; */ class Customer { - // TODO: make this a setting somewhere - const COUNTRY_CODE_PREFIX = '+60'; - // unique id /** * @ORM\Id @@ -266,16 +263,16 @@ class Customer $phones = []; if (!empty($this->phone_mobile)) - $phones[] = self::COUNTRY_CODE_PREFIX . $this->phone_mobile; + $phones[] = $this->phone_mobile; if (!empty($this->phone_landline)) - $phones[] = self::COUNTRY_CODE_PREFIX . $this->phone_landline; + $phones[] = $this->phone_landline; if (!empty($this->phone_office)) - $phones[] = self::COUNTRY_CODE_PREFIX . $this->phone_office; + $phones[] = $this->phone_office; if (!empty($this->phone_fax)) - $phones[] = self::COUNTRY_CODE_PREFIX . $this->phone_fax; + $phones[] = $this->phone_fax; return $phones; } diff --git a/src/Service/CustomerHandler/CMBCustomerHandler.php b/src/Service/CustomerHandler/CMBCustomerHandler.php index a0f3ca2e..fb6a888e 100644 --- a/src/Service/CustomerHandler/CMBCustomerHandler.php +++ b/src/Service/CustomerHandler/CMBCustomerHandler.php @@ -25,17 +25,17 @@ use DateTime; class CMBCustomerHandler implements CustomerHandlerInterface { - const COUNTRY_CODE_PREFIX = '+60'; - protected $em; protected $validator; - + protected $country_code; protected $template_hash; - public function __construct(EntityManagerInterface $em, ValidatorInterface $validator) + public function __construct(EntityManagerInterface $em, ValidatorInterface $validator, + string $country_code) { $this->em = $em; $this->validator = $validator; + $this->country_code = $country_code; $this->loadTemplates(); } @@ -121,7 +121,14 @@ class CMBCustomerHandler implements CustomerHandlerInterface $row['flag_csat'] = $orow->isCSAT(); // TODO: properly add mobile numbers and plate numbers as searchable/sortable fields, use doctrine events - $row['mobile_numbers'] = implode("
", $orow->getMobileNumberList()); + // prepend the country code before each mobile number + $mobile_number_list = []; + $mobile_numbers = $orow->getMobileNumberList(); + foreach ($mobile_numbers as $mobile_number) + { + $mobile_number_list[] = $this->country_code . $mobile_number; + } + $row['mobile_numbers'] = implode("
", $mobile_number_list); $row['plate_numbers'] = implode("
", $orow->getPlateNumberList()); $rows[] = $row; @@ -467,7 +474,7 @@ class CMBCustomerHandler implements CustomerHandlerInterface $cust = $cv->getCustomer(); $vehicles[] = [ 'id' => $cv->getID(), - 'text' => $cv->getPlateNumber() . ' ' . $cust->getFirstName() . ' ' . $cust->getLastName() . ' ('. self::COUNTRY_CODE_PREFIX . $cust->getPhoneMobile() . ')', + 'text' => $cv->getPlateNumber() . ' ' . $cust->getFirstName() . ' ' . $cust->getLastName() . ' ('. $this->country_code . $cust->getPhoneMobile() . ')', ]; } diff --git a/src/Service/CustomerHandler/ResqCustomerHandler.php b/src/Service/CustomerHandler/ResqCustomerHandler.php index 8ea688cf..5f7e00e2 100644 --- a/src/Service/CustomerHandler/ResqCustomerHandler.php +++ b/src/Service/CustomerHandler/ResqCustomerHandler.php @@ -27,17 +27,17 @@ use DateTime; class ResqCustomerHandler implements CustomerHandlerInterface { - const COUNTRY_CODE_PREFIX = '+63'; - protected $em; protected $validator; - + protected $country_code; protected $template_hash; - public function __construct(EntityManagerInterface $em, ValidatorInterface $validator) + public function __construct(EntityManagerInterface $em, ValidatorInterface $validator, + string $country_code) { $this->em = $em; $this->validator = $validator; + $this->country_code = $country_code; $this->loadTemplates(); } @@ -124,7 +124,14 @@ class ResqCustomerHandler implements CustomerHandlerInterface $row['flag_csat'] = $orow->isCSAT(); // TODO: properly add mobile numbers and plate numbers as searchable/sortable fields, use doctrine events - $row['mobile_numbers'] = implode("
", $orow->getMobileNumberList()); + // prepend the country code before each mobile number + $mobile_number_list = []; + $mobile_numbers = $orow->getMobileNumberList(); + foreach ($mobile_numbers as $mobile_number) + { + $mobile_number_list[] = $this->country_code . $mobile_number; + } + $row['mobile_numbers'] = implode("
", $mobile_number_list); $row['plate_numbers'] = implode("
", $orow->getPlateNumberList()); $rows[] = $row; @@ -465,7 +472,7 @@ class ResqCustomerHandler implements CustomerHandlerInterface $cust = $cv->getCustomer(); $vehicles[] = [ 'id' => $cv->getID(), - 'text' => $cv->getPlateNumber() . ' ' . $cust->getFirstName() . ' ' . $cust->getLastName() . ' ('. self::COUNTRY_CODE_PREFIX . $cust->getPhoneMobile() . ')', + 'text' => $cv->getPlateNumber() . ' ' . $cust->getFirstName() . ' ' . $cust->getLastName() . ' ('. $this->country_code . $cust->getPhoneMobile() . ')', ]; } diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 1e4d8f9f..4803e1ec 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -40,6 +40,7 @@ use App\Ramcar\JORejectionReason; use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; use App\Service\RiderAssignmentHandlerInterface; +use App\Service\WarrantyHandler; use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; @@ -55,20 +56,21 @@ use FPDF; class CMBJobOrderHandler implements JobOrderHandlerInterface { - const COUNTRY_CODE_PREFIX = '+60'; - protected $em; protected $ic; protected $security; protected $validator; protected $translator; protected $rah; + protected $country_code; + protected $wh; protected $template_hash; public function __construct(Security $security, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, ValidatorInterface $validator, - TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah) + TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah, + string $country_code, WarrantyHandler $wh) { $this->em = $em; $this->ic = $ic; @@ -76,6 +78,8 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->validator = $validator; $this->translator = $translator; $this->rah = $rah; + $this->country_code = $country_code; + $this->wh = $wh; $this->loadTemplates(); } @@ -841,7 +845,37 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface // create the warranty if new battery only if ($obj->getServiceType () == CMBServiceType::BATTERY_REPLACEMENT_NEW) { - $this->createWarranty($obj); + $serial = null; + $warranty_class = $obj->getWarrantyClass(); + $first_name = $obj->getCustomer()->getFirstName(); + $last_name = $obj->getCustomer()->getLastName(); + $mobile_number = $obj->getCustomer()->getPhoneMobile(); + + // check if date fulfilled is null + if ($obj->getDateFulfill() == null) + $date_purchase = $obj->getDateCreate(); + else + $date_purchase = $obj->getDateFulfill(); + + $plate_number = $this->wh->cleanPlateNumber($obj->getCustomerVehicle()->getPlateNumber()); + + $batt_list = array(); + $invoice = $obj->getInvoice(); + if (!empty($invoice)) + { + // get battery + $invoice_items = $invoice->getItems(); + foreach ($invoice_items as $item) + { + $battery = $item->getBattery(); + if ($battery != null) + { + $batt_list[] = $item->getBattery(); + } + } + } + + $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } } } @@ -1860,7 +1894,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Mobile Phone:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneMobile() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneMobile() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneMobile() ? $this->country_code . $customer->getPhoneMobile() : '', 0, 'L'); // get Y after right cell $y2 = $pdf->GetY(); @@ -1877,7 +1911,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Landline:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneLandline() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneLandline() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneLandline() ? $this->country_code . $customer->getPhoneLandline() : '', 0, 'L'); // get Y after right cell $y2 = $pdf->GetY(); @@ -1887,11 +1921,11 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Office Phone:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneOffice() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneOffice() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneOffice() ? $this->country_code . $customer->getPhoneOffice() : '', 0, 'L'); $pdf->SetX($col2_x); $pdf->Cell($label_width, $line_height, 'Fax:'); - $pdf->MultiCell($val_width, $line_height, $customer && $customer->getPhoneFax() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneFax() : '', 0, 'L'); + $pdf->MultiCell($val_width, $line_height, $customer && $customer->getPhoneFax() ? $this->country_code . $customer->getPhoneFax() : '', 0, 'L'); // insert vehicle info $cv = $obj->getCustomerVehicle(); @@ -2394,79 +2428,6 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface ->setWarrantyExpiration($warr_date); } - protected function createWarranty($jo) - { - $warranty = new Warranty(); - - $warranty_class = $jo->getWarrantyClass(); - $first_name = $jo->getCustomer()->getFirstName(); - $last_name = $jo->getCustomer()->getLastName(); - $mobile_number = $jo->getCustomer()->getPhoneMobile(); - - // check if date fulfilled is null - if ($jo->getDateFulfill() == null) - $date_create = $jo->getDateCreate(); - else - $date_create = $jo->getDateFulfill(); - - // normalize the plate number - $plate_number = $this->normalizePlateNumber($jo->getCustomerVehicle()->getPlateNumber()); - - // get battery and its warranty periods - $warranty_period = 0; - $invoice_items = $jo->getInvoice()->getItems(); - foreach ($invoice_items as $item) - { - if ($item->getBattery() != null) - { - $battery = $item->getBattery(); - $warranty->setBatteryModel($battery->getModel()); - $warranty->setBatterySize($battery->getSize()); - - // use getWarrantyPrivate for passenger warranty - if ($warranty_class == CMBWarrantyClass::WTY_PASSENGER) - $warranty_period = $battery->getWarrantyPrivate(); - else if ($warranty_class == CMBWarrantyClass::WTY_COMMERCIAL) - $warranty_period = $battery->getWarrantyCommercial(); - } - } - - // compute expiry date - $expiry_date = $this->computeDateExpire($date_create, $warranty_period); - - $warranty->setWarrantyClass($warranty_class) - ->setFirstName($first_name) - ->setLastName($last_name) - ->setMobileNumber($mobile_number) - ->setDatePurchase($date_create) - ->setDateExpire($expiry_date) - ->setPlateNumber($plate_number); - - $this->em->persist($warranty); - $this->em->flush(); - - } - - protected function normalizePlateNumber($plate_number) - { - // make it upper case - $plate_number = trim(strtoupper($plate_number)); - - // remove special characters and spaces - $plate_number = preg_replace('/[^A-Za-z0-9]/', '', $plate_number); - - //error_log('plate number ' . $plate_number); - - return $plate_number; - } - - protected function computeDateExpire($date_create, $warranty_period) - { - $expire_date = clone $date_create; - $expire_date->add(new DateInterval('P'.$warranty_period.'M')); - return $expire_date; - } - // TODO: re-enable search, figure out how to group the orWhere filters into one, so can execute that plus the pending filter // check if datatable filter is present and append to query protected function setQueryFilters($datatable, &$query, $qb, $hubs, $tier, $status) diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index f6f07188..3f6a336c 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -38,6 +38,7 @@ use App\Ramcar\JORejectionReason; use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; +use App\Service\WarrantyHandler; use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; @@ -53,25 +54,28 @@ use FPDF; class ResqJobOrderHandler implements JobOrderHandlerInterface { - const COUNTRY_CODE_PREFIX = '+60'; - protected $em; protected $ic; protected $security; protected $validator; protected $translator; + protected $country_code; + protected $wh; protected $template_hash; public function __construct(Security $security, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, ValidatorInterface $validator, - TranslatorInterface $translator) + TranslatorInterface $translator, string $country_code, + WarrantyHandler $wh) { $this->em = $em; $this->ic = $ic; $this->security = $security; $this->validator = $validator; $this->translator = $translator; + $this->country_code = $country_code; + $this->wh = $wh; $this->loadTemplates(); } @@ -703,6 +707,43 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface ]; $mclient->sendEvent($obj, $payload); $mclient->sendRiderEvent($obj, $payload); + + // create the warranty if new battery only + if ($obj->getServiceType () == ServiceType::BATTERY_REPLACEMENT_NEW) + { + $serial = null; + $warranty_class = $obj->getWarrantyClass(); + $first_name = $obj->getCustomer()->getFirstName(); + $last_name = $obj->getCustomer()->getLastName(); + $mobile_number = $obj->getCustomer()->getPhoneMobile(); + + // check if date fulfilled is null + if ($obj->getDateFulfill() == null) + $date_purchase = $obj->getDateCreate(); + else + $date_purchase = $obj->getDateFulfill(); + + $plate_number = $this->wh->cleanPlateNumber($obj->getCustomerVehicle()->getPlateNumber()); + + $batt_list = array(); + $invoice = $obj->getInvoice(); + if (!empty($invoice)) + { + // get battery + $invoice_items = $invoice->getItems(); + foreach ($invoice_items as $item) + { + $battery = $item->getBattery(); + if ($battery != null) + { + $batt_list[] = $item->getBattery(); + } + } + } + + $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); + } + } } @@ -1868,7 +1909,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Mobile Phone:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneMobile() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneMobile() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneMobile() ? $this->country_code . $customer->getPhoneMobile() : '', 0, 'L'); // get Y after right cell $y2 = $pdf->GetY(); @@ -1885,7 +1926,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Landline:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneLandline() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneLandline() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneLandline() ? $this->country_code . $customer->getPhoneLandline() : '', 0, 'L'); // get Y after right cell $y2 = $pdf->GetY(); @@ -1895,11 +1936,11 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $pdf->SetXY($col2_x, $y); $pdf->Cell($label_width, $line_height, 'Office Phone:'); - $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneOffice() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneOffice() : '', 0, 'L'); + $pdf->MultiCell(0, $line_height, $customer && $customer->getPhoneOffice() ? $this->country_code . $customer->getPhoneOffice() : '', 0, 'L'); $pdf->SetX($col2_x); $pdf->Cell($label_width, $line_height, 'Fax:'); - $pdf->MultiCell($val_width, $line_height, $customer && $customer->getPhoneFax() ? self::COUNTRY_CODE_PREFIX . $customer->getPhoneFax() : '', 0, 'L'); + $pdf->MultiCell($val_width, $line_height, $customer && $customer->getPhoneFax() ? $this->country_code . $customer->getPhoneFax() : '', 0, 'L'); // insert vehicle info $cv = $obj->getCustomerVehicle(); diff --git a/src/Service/WarrantyHandler.php b/src/Service/WarrantyHandler.php new file mode 100644 index 00000000..bfc30021 --- /dev/null +++ b/src/Service/WarrantyHandler.php @@ -0,0 +1,332 @@ +em = $em; + } + + public function createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, + $batt_list, DateTime $date_purchase, $warranty_class) + { + // new warranty + $warranty = new Warranty(); + + foreach ($batt_list as $battery) + { + // get the battery model and battery size + $model_id = $battery->getModel()->getID(); + $size_id = $battery->getSize()->getID(); + + $bty_model = $this->em->getRepository(BatteryModel::class)->find($model_id); + $bty_size = $this->em->getRepository(BatterySize::class)->find($size_id); + + if ($bty_model != null) + { + $warranty->setBatteryModel($bty_model); + } + if ($bty_size != null) + { + $warranty->setBatterySize($bty_size); + } + + $sap_code = $battery->getSAPCode(); + if (!empty($sap_code)) + { + // find sap battery + $sap_battery = $this->em->getRepository(SAPBattery::class)->find($sap_code); + if ($sap_battery != null) + { + $warranty->setSAPBattery($sap_battery); + } + } + } + + // compute expiry date + $date_expire = null; + if ((!empty($warranty_class)) && + (count($batt_list) != 0)) + { + $period = $this->getWarrantyPeriod($batt_list, $warranty_class); + $date_expire = $this->computeDateExpire($date_purchase, $period); + + $warranty->setDateExpire($date_expire); + } + + // set and save values + $warranty->setSerial($serial) + ->setPlateNumber($plate_number) + ->setFirstName($first_name) + ->setLastName($last_name) + ->setMobileNumber($mobile_number) + ->setDatePurchase($date_purchase); + + $this->em->persist($warranty); + $this->em->flush(); + + // update customer vehicle with warranty info + $this->updateCustomerVehicle($serial, $batt_list, $plate_number, $date_expire); + + $this->em->clear(); + } + + public function updateCustomerVehicle($serial, $batteries, $plate_number, $date_expire) + { + // find customer vehicle using plate number + error_log('Finding customer vehicle with plate number ' . $plate_number); + $cv_q = $this->em->createQuery('select count(cv) from App\Entity\CustomerVehicle cv where cv.plate_number = :plate_number') + ->setParameter('plate_number', $plate_number); + $cv_result = $cv_q->getSingleScalarResult(); + + $battery_id = null; + if ($cv_result != 0) + { + if (!empty($batteries)) + { + // set current battery to the first battery in list. + // there are cases where multiple batteries linked to an SAP code. + $battery = $batteries[0]; + $battery_id = $battery->getID(); + } + //error_log('Serial/Warranty Code = ' . $serial); + $q = $this->em->createQuery('update App\Entity\CustomerVehicle cv + set cv.curr_battery = :batt_id, + cv.warranty_code = :serial, + cv.warranty_expiration = :expiry_date + where cv.plate_number = :plate_number') + ->setParameters([ + 'batt_id' => $battery_id, + 'serial' => $serial, + 'expiry_date' => $date_expire, + 'plate_number' => $plate_number]); + $q->execute(); + } + } + + public function updateWarranty(Warranty $warr, $first_name, $last_name, $mobile_number, $batt_list, DateTime $date_purchase) + { + // TODO: add serial and plate number to update + // TODO: check if data from existing warranty matches the new data + // check if details are complete + if (empty($warr->getFirstName())) + { + if (!empty($first_name)) + { + $warr->setFirstName($first_name); + } + } + if (empty($warr->getLastName())) + { + if (!empty($last_name)) + { + $warr->setLastName($last_name); + } + } + if (empty($warr->getMobileNumber())) + { + if (!empty($mobile_number)) + { + $warr->setMobileNumber($mobile_number); + } + } + if ((empty($warr->getBatteryModel())) || + (empty($warr->getBatterySize()))) + { + if (count($batt_list) != 0) + { + foreach ($batt_list as $battery) + { + // get the battery model and battery size + $model_id = $battery->getModel()->getID(); + $size_id = $battery->getSize()->getID(); + + $bty_model = $this->em->getRepository(BatteryModel::class)->find($model_id); + $bty_size = $this->em->getRepository(BatterySize::class)->find($size_id); + + if ($bty_model != null) + { + $warranty->setBatteryModel($bty_model); + } + if ($bty_size != null) + { + $warranty->setBatterySize($bty_size); + } + + $sap_code = $battery->getSAPCode(); + if (!empty($sap_code)) + { + // find sap battery + $sap_battery = $this->em->getRepository(SAPBattery::class)->find($sap_code); + if ($sap_battery != null) + { + $warranty->setSAPBattery($sap_battery); + } + } + } + } + } + + $purchase_date = $warr->getDatePurchase(); + if (empty($purchase_date)) + { + if (!empty($date_purchase)) + { + $warr->setDatePurchase($date_purchase); + } + $purchase_date = $date_purchase; + } + + if (empty($warr->getDateExpire())) + { + $batteries = []; + if (count($batt_list) == 0) + { + $batteries = $this->getBatteriesForWarranty($warr); + } + else + { + $batteries = $batt_list; + } + + if (!empty($batteries)) + { + $period = $this->getWarrantyPeriod($batteries, $warr->getWarrantyClass()); + if (!empty($purchase_date)) + { + $expire_date = $this->computeDateExpire($purchase_date, $period); + $warr->setDateExpire($expire_date); + } + } + } + + $this->em->persist($warr); + $this->em->flush(); + $this->em->clear(); + } + + public function computeDateExpire($date_create, $warranty_period) + { + $expire_date = clone $date_create; + $expire_date->add(new DateInterval('P'.$warranty_period.'M')); + return $expire_date; + } + + public function getWarrantyPeriod($batteries, $warranty_class) + { + // set to -1 to show that we haven't set a warranty period yet + // cannot set initial value to 0 because warranty tnv can be 0 + $least_warranty = -1; + $warr_period = 0; + foreach ($batteries as $battery) + { + // if multiple batteries, get the smallest warranty period + // check warranty class to get warranty period + if ($warranty_class == WarrantyClass::WTY_PRIVATE) + { + $warr_period = $battery->getWarrantyPrivate(); + //error_log('Warranty Period for Private: ' . $warr_period); + } + if ($warranty_class == WarrantyClass::WTY_COMMERCIAL) + { + $warr_period = $battery->getWarrantyCommercial(); + //error_log('Warranty Period for Commercial: ' . $warr_period); + } + if ($warranty_class == WarrantyClass::WTY_TNV) + { + $warr_period = $battery->getWarrantyTnv(); + //error_log('Warranty Period for TNV: ' . $warr_period); + } + + if ($least_warranty < 0) + { + // set least warranty to the first obtained warranty period + $least_warranty = $warr_period; + } + + if ($least_warranty > $warr_period) + { + $least_warranty = $warr_period; + } + } + + $warranty_period = $least_warranty; + + return $warranty_period; + } + + public function getBatteriesForWarranty($warr) + { + // find battery via sku/sap battery first + // if sku is null, use battery model and battery size to find battery + // if all three are null, do nothing + $batteries = null; + + $sap_battery = $warr->getSAPBattery(); + $batt_model = $warr->getBatteryModel(); + $batt_size = $warr->getBatterySize(); + $warranty_class = $warr->getWarrantyClass(); + + if (empty($warranty_class)) + { + error_log('Warranty class is empty for warranty id ' . $warr->getID()); + return null; + } + + if ($sap_battery != null) + { + // get the battery linked to SAP Battery using sap_battery id + $batteries = $this->em->getRepository(Battery::class)->findBy(['sap_code' => $sap_battery->getID()]); + } + else + { + if ($batt_model == null) + { + error_log('Battery model is null for warranty id ' . $warr->getID()); + return null; + } + if ($batt_size == null) + { + error_log('Battery size is null for warranty id ' . $warr->getID()); + return null; + } + + // find battery using battery model and battery size + $batteries = $this->em->getRepository(Battery::class)->findBy(['model' => $batt_model, 'size' => $batt_size]); + } + + if (empty($batteries)) + { + error_log('Battery not found for warranty id ' . $warr->getID()); + return null; + } + + return $batteries; + } + + + public function cleanPlateNumber($plate) + { + // remove spaces and make upper case + return strtoupper(str_replace(' ', '', $plate)); + } + +} diff --git a/templates/customer/form.html.twig b/templates/customer/form.html.twig index 4f2f5e9f..f502e778 100644 --- a/templates/customer/form.html.twig +++ b/templates/customer/form.html.twig @@ -131,7 +131,7 @@ Mobile Phone
- +63 + {% trans %}country_code_prefix{% endtrans %}
@@ -141,7 +141,7 @@ Landline
- +63 + {% trans %}country_code_prefix{% endtrans %}
@@ -153,7 +153,7 @@ Office Phone
- +63 + {% trans %}country_code_prefix{% endtrans %}
@@ -163,7 +163,7 @@ Fax
- +63 + {% trans %}country_code_prefix{% endtrans %}