Add checking for duplicate generated ids when flushing. #638

This commit is contained in:
Korina Cordero 2021-11-16 09:54:58 +00:00
parent f29c69cad1
commit c40143dced
8 changed files with 152 additions and 22 deletions

View file

@ -306,3 +306,9 @@ services:
App\Service\UniqueIdGenerator: App\Service\UniqueIdGenerator:
arguments: arguments:
$em: "@doctrine.orm.entity_manager" $em: "@doctrine.orm.entity_manager"
# service to generate id for customer and to save customer
App\Service\CustomerGeneratedIdService:
arguments:
$em: "@doctrine.orm.entity_manager"
$id_gen: "@App\\Service\\UniqueIdGenerator"

View file

@ -47,6 +47,7 @@ use App\Service\HubSelector;
use App\Service\HubDistributor; use App\Service\HubDistributor;
use App\Service\HubFilterLogger; use App\Service\HubFilterLogger;
use App\Service\HubFilteringGeoChecker; use App\Service\HubFilteringGeoChecker;
use App\Service\CustomerGeneratedIdService;
use App\Entity\MobileSession; use App\Entity\MobileSession;
use App\Entity\Customer; use App\Entity\Customer;
@ -442,7 +443,7 @@ class APIController extends Controller implements LoggedController
return $cust; return $cust;
} }
public function updateInfo(Request $req, EntityManagerInterface $em) public function updateInfo(Request $req, EntityManagerInterface $em, CustomerGeneratedIdService $cust_gen_id)
{ {
// check required parameters and api key // check required parameters and api key
$required_params = [ $required_params = [
@ -468,8 +469,26 @@ class APIController extends Controller implements LoggedController
{ {
$cust->setPrivacyPolicyMobile($mobile_policy); $cust->setPrivacyPolicyMobile($mobile_policy);
} }
$em->flush(); // need to check if it's a new customer or updated existing customer
// a new customer would not have a generated id while an existing one
// already have one.
if ($cust->getGeneratedId() == null)
{
// TODO: temporary fix on how to save customer with a generated id
// since we need to keep generating an id until we are sure that there
// are no duplicates for generated id
// when saving the customer. This is an additional check.
// This will keep generating an id until a unique id is generated
// and the customer entity can then be inserted
$cust_gen_id->saveCustomerWithGeneratedId($cust);
}
else
{
// we do a simple flush with no id generation for updated existing
// customers
$em->flush();
}
return $res->getReturnResponse(); return $res->getReturnResponse();
} }

View file

@ -15,6 +15,8 @@ use App\Entity\Customer;
use App\Entity\CustomerVehicle; use App\Entity\CustomerVehicle;
use App\Entity\Vehicle; use App\Entity\Vehicle;
use App\Service\CustomerGeneratedIdService;
use Catalyst\APIBundle\Access\Generator as ACLGenerator; use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class CustomerController extends APIController class CustomerController extends APIController
@ -26,7 +28,7 @@ class CustomerController extends APIController
$this->acl_gen = $acl_gen; $this->acl_gen = $acl_gen;
} }
public function register(Request $req, EntityManagerInterface $em) public function register(Request $req, EntityManagerInterface $em, CustomerGeneratedIdService $cust_gen_id)
{ {
$this->denyAccessUnlessGranted('customer.register', null, 'No access.'); $this->denyAccessUnlessGranted('customer.register', null, 'No access.');
@ -150,6 +152,8 @@ class CustomerController extends APIController
]; ];
} }
} }
$em->flush();
} }
else else
{ {
@ -194,9 +198,16 @@ class CustomerController extends APIController
'condition' => $condition, 'condition' => $condition,
'fuel_type' => $fuel_type, 'fuel_type' => $fuel_type,
]; ];
// TODO: temporary fix on how to save customer with a generated id
// since we need to keep generating an id until we are sure that there
// are no duplicates for generated id
// when saving the customer. This is an additional check.
// This will keep generating an id until a unique id is generated
// and the customer entity can then be inserted
$cust_gen_id->saveCustomerWithGeneratedId($new_cust);
} }
$em->flush();
$em->clear(); $em->clear();
return new APIResponse(true, $message, $data); return new APIResponse(true, $message, $data);

View file

@ -15,6 +15,7 @@ use Catalyst\APIBundle\Response\APIResponse;
use App\Service\RisingTideGateway; use App\Service\RisingTideGateway;
use App\Service\WarrantyAPILogger; use App\Service\WarrantyAPILogger;
use App\Service\CustomerGeneratedIdService;
use App\Entity\WarrantySerial; use App\Entity\WarrantySerial;
use App\Entity\Warranty; use App\Entity\Warranty;
@ -301,7 +302,7 @@ class CustomerWarrantyController extends APIController
public function register($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt, TranslatorInterface $trans, public function register($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt, TranslatorInterface $trans,
WarrantyAPILogger $logger) WarrantyAPILogger $logger, CustomerGeneratedIdService $cust_gen_id)
{ {
error_log('HERE - register'); error_log('HERE - register');
@ -325,7 +326,7 @@ class CustomerWarrantyController extends APIController
$username = $this->getUser()->getName(); $username = $this->getUser()->getName();
$source = 'CAPI_USER_' . $username; $source = 'CAPI_USER_' . $username;
error_log('SOURCE: ' . $source); // error_log('SOURCE: ' . $source);
// TODO: maybe add vmake_id? since warranty cannot be created with no vmake // TODO: maybe add vmake_id? since warranty cannot be created with no vmake
// TODO: maybe also add mobile and email since customer creation won't let mobile and email be null // TODO: maybe also add mobile and email since customer creation won't let mobile and email be null
@ -353,7 +354,7 @@ class CustomerWarrantyController extends APIController
// do actual registering // do actual registering
$res = $this->updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename, $wcard_filename, $res = $this->updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename, $wcard_filename,
$logger, $log_data, $user_id, $action, $source); $logger, $log_data, $user_id, $action, $source, $cust_gen_id);
// flush to db // flush to db
$em->flush(); $em->flush();
@ -395,7 +396,7 @@ class CustomerWarrantyController extends APIController
} }
protected function updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null, protected function updateWarranty($em, $rt, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null,
$logger, $log_data, $user_id, $action, $source) $logger, $log_data, $user_id, $action, $source, $cust_gen_id)
{ {
$plate_num = $this->cleanPlateNumber($req->request->get('plate_num')); $plate_num = $this->cleanPlateNumber($req->request->get('plate_num'));
@ -512,7 +513,6 @@ class CustomerWarrantyController extends APIController
$cust->setPrivacyPromo($priv_promo); $cust->setPrivacyPromo($priv_promo);
} }
error_log('update entity / database'); error_log('update entity / database');
// create or update warranty entry // create or update warranty entry
$warr->setSerial($serial) $warr->setSerial($serial)
@ -556,15 +556,30 @@ class CustomerWarrantyController extends APIController
$em->persist($warr); $em->persist($warr);
$logger->logWarrantyInfo($log_data, '', $user_id, $action, $source); // need to check if it's a new customer or updated existing customer
// a new customer would not have a generated id while an existing one
// already have one.
if ($cust->getGeneratedId() == null)
{
// TODO: temporary fix on how to save customer with a generated id
// since we need to keep generating an id until we are sure that there
// are no duplicates for generated id
// when saving the customer. This is an additional check.
// This will keep generating an id until a unique id is generated
// and the customer entity can then be inserted
$cust_gen_id->saveCustomerWithGeneratedId($cust);
}
// TODO: check if we need to do anything else // TODO: check if we need to do anything else
$data = []; $data = [];
// send sms confirmation // send sms confirmation
$this->sendSMSConfirmation($rt, $req->request->get('contact_num'), $sms_message); $this->sendSMSConfirmation($rt, $req->request->get('contact_num'), $sms_message);
$logger->logWarrantyInfo($log_data, '', $user_id, $action, $source);
$em->flush();
return new APIResponse(true, 'Warranty registered.', $data); return new APIResponse(true, 'Warranty registered.', $data);
} }

View file

@ -23,6 +23,7 @@ use App\Entity\Vehicle;
use App\Entity\WarrantyAPILog; use App\Entity\WarrantyAPILog;
use App\Service\WarrantyAPILogger; use App\Service\WarrantyAPILogger;
use App\Service\CustomerGeneratedIdService;
use App\Ramcar\NameValue; use App\Ramcar\NameValue;
use App\Ramcar\WarrantyClass; use App\Ramcar\WarrantyClass;
@ -146,7 +147,7 @@ class WarrantyController extends APIController
return new APIResponse(true, 'Warranties found.', $data); return new APIResponse(true, 'Warranties found.', $data);
} }
public function register(Request $req, EntityManagerInterface $em, WarrantyAPILogger $logger) public function register(Request $req, EntityManagerInterface $em, WarrantyAPILogger $logger, CustomerGeneratedIdService $cust_gen_id)
{ {
$this->denyAccessUnlessGranted('warranty.register.battery', null, 'No access.'); $this->denyAccessUnlessGranted('warranty.register.battery', null, 'No access.');
@ -287,7 +288,7 @@ class WarrantyController extends APIController
{ {
$em->persist($warr); $em->persist($warr);
$this->getCustomerFromMobile($em, $warr); $this->getCustomerFromMobile($em, $warr, $cust_gen_id);
$em->flush(); $em->flush();
} }
@ -638,7 +639,7 @@ class WarrantyController extends APIController
return new APIResponse(true, 'Warranties found.', $data); return new APIResponse(true, 'Warranties found.', $data);
} }
protected function getCustomerFromMobile($em, $warranty) protected function getCustomerFromMobile($em, $warranty, $cust_gen_id)
{ {
$w_mobile = $warranty->getMobileNumber(); $w_mobile = $warranty->getMobileNumber();
if (empty($w_mobile)) if (empty($w_mobile))
@ -717,6 +718,7 @@ class WarrantyController extends APIController
$this->createCustomerVehicle($em, $customer, $this->getDefaultVehicle($em), $w_plate_number); $this->createCustomerVehicle($em, $customer, $this->getDefaultVehicle($em), $w_plate_number);
} }
} }
$em->flush();
} }
// customer not found // customer not found
else else
@ -738,9 +740,17 @@ class WarrantyController extends APIController
$em->persist($new_cust); $em->persist($new_cust);
$this->createCustomerVehicle($em, $new_cust, $this->getDefaultVehicle($em), $w_plate_number); $this->createCustomerVehicle($em, $new_cust, $this->getDefaultVehicle($em), $w_plate_number);
// TODO: temporary fix on how to save customer with a generated id
// since we need to keep generating an id until we are sure that there
// are no duplicates for generated id
// when saving the customer. This is an additional check.
// This will keep generating an id until a unique id is generated
// and the customer entity can then be inserted
$cust_gen_id->saveCustomerWithGeneratedId($new_cust);
} }
$em->flush(); // $em->flush();
$em->clear(); $em->clear();
} }

View file

@ -0,0 +1,59 @@
<?php
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Customer;
use App\Service\UniqueIdGenerator;
class CustomerGeneratedIdService
{
protected $em;
protected $id_gen;
public function __construct(EntityManagerInterface $em, UniqueIdGenerator $id_gen)
{
$this->em = $em;
$this->id_gen = $id_gen;
}
public function saveCustomerWithGeneratedId(Customer $cust)
{
$em = $this->em;
$id_gen = $this->id_gen;
// need to generate id
// have to try catch the flush because of the generated id
// need to retry until we get a unique generated id
while (true)
{
try
{
$generated_id = $id_gen->generateCustomerUniqueId(40);
$cust->setGeneratedId($generated_id);
// reopen in case we get an exception
if (!$em->isOpen())
{
$em = $em->create(
$em->getConnection(),
$em->getConfiguration()
);
}
$em->flush();
}
catch (UniqueConstraintViolationException $e)
{
error_log($e->getMessage());
// delay one second and try again
sleep(1);
continue;
}
break;
}
}
}

View file

@ -4,12 +4,15 @@ namespace App\Service\CustomerHandler;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use App\Service\CustomerHandlerInterface; use App\Service\CustomerHandlerInterface;
use App\Service\CustomerGeneratedIdService;
use App\Ramcar\CustomerClassification; use App\Ramcar\CustomerClassification;
use App\Ramcar\FuelType; use App\Ramcar\FuelType;
@ -34,14 +37,16 @@ class ResqCustomerHandler implements CustomerHandlerInterface
protected $country_code; protected $country_code;
protected $security; protected $security;
protected $template_hash; protected $template_hash;
protected $cust_gen_id;
public function __construct(EntityManagerInterface $em, ValidatorInterface $validator, public function __construct(EntityManagerInterface $em, ValidatorInterface $validator,
string $country_code, Security $security) string $country_code, Security $security, CustomerGeneratedIdService $cust_gen_id)
{ {
$this->em = $em; $this->em = $em;
$this->validator = $validator; $this->validator = $validator;
$this->country_code = $country_code; $this->country_code = $country_code;
$this->security = $security; $this->security = $security;
$this->cust_gen_id = $cust_gen_id;
$this->loadTemplates(); $this->loadTemplates();
} }
@ -292,7 +297,16 @@ class ResqCustomerHandler implements CustomerHandlerInterface
{ {
// validated! save the entity // validated! save the entity
$em->persist($row); $em->persist($row);
$em->flush();
// TODO: temporary fix on how to save customer with a generated id
// since we need to keep generating an id until we are sure that there
// are no duplicates for generated id
// when saving the customer. This is an additional check.
// This will keep generating an id until a unique id is generated
// and the customer entity can then be inserted
$this->cust_gen_id->saveCustomerWithGeneratedId($row);
//$em->flush();
$result = [ $result = [
'id' => $row->getID(), 'id' => $row->getID(),

View file

@ -9,13 +9,10 @@ use App\Entity\Customer;
class UniqueIdGenerator class UniqueIdGenerator
{ {
protected $em; protected $em;
protected $cust_generated_ids;
public function __construct(EntityManagerInterface $em) public function __construct(EntityManagerInterface $em)
{ {
$this->em = $em; $this->em = $em;
$this->loadGeneratedIds();
} }
public function generateCustomerUniqueId($str_length) public function generateCustomerUniqueId($str_length)
@ -36,7 +33,6 @@ class UniqueIdGenerator
sleep(1); sleep(1);
} }
} }
protected function generateUniqueId($str_length) protected function generateUniqueId($str_length)