diff --git a/catalyst/api-bundle/Command/TestCommand.php b/catalyst/api-bundle/Command/TestCommand.php index e1512157..9a12caad 100644 --- a/catalyst/api-bundle/Command/TestCommand.php +++ b/catalyst/api-bundle/Command/TestCommand.php @@ -42,18 +42,26 @@ class TestCommand extends Command // TODO: shift this out of the bundle, since it's project specific // warranty register $params = [ + 'serial' => 'LJ34LJADR12SDLKJL', + 'plate_number' => 'XEN918', + 'warranty_class' => 'private', + 'date_purchase' => '20181001', + 'date_expire' => '20191001', ]; $api->post('/capi/warranty', $params); // warranty find $api->get('/capi/warranty/LJ34LJADR12SDLKJL'); + // warranty claim + $api->post('/capi/warranty/LJ34LJADR12SDLKJL/claim'); + // battery - $api->get('/capi/battery_models'); - $api->get('/capi/battery_sizes'); + // $api->get('/capi/battery_models'); + // $api->get('/capi/battery_sizes'); // vehicle - $api->get('/capi/vehicle_manufacturers'); - $api->get('/capi/vehicles'); + // $api->get('/capi/vehicle_manufacturers'); + // $api->get('/capi/vehicles'); } } diff --git a/config/routes/warranty_api.yaml b/config/routes/warranty_api.yaml index 6414c97e..bfc4d731 100644 --- a/config/routes/warranty_api.yaml +++ b/config/routes/warranty_api.yaml @@ -48,7 +48,7 @@ capi_warranty_register: # claim warranty capi_warranty_claim: - path: /capi/warranty/{serial} + path: /capi/warranty/{serial}/claim controller: App\Controller\CAPI\WarrantyController::claim methods: [POST] diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index a17b7701..433f710f 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -6,18 +6,76 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; 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\Entity\Warranty; +use App\Ramcar\NameValue; +use App\Ramcar\WarrantyClass; +use App\Ramcar\WarrantyStatus; use DateTime; class WarrantyController extends Controller implements APIController { + protected function checkRequiredParameters(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') + else + { + $check = $req->request->get($param); + if (empty($check)) + $missing[] = $param; + } + } + + // check missing parameters + if (count($missing) > 0) + { + $miss_string = implode(', ', $missing); + return 'Missing required parameter(s): ' . $miss_string; + } + + return false; + } + protected function cleanSerial($serial) { return trim(strtoupper($serial)); } + protected function generateWarrantyData(Warranty $warr) + { + $data = [ + 'id' => (int) $warr->getID(), + 'serial' => (string) $warr->getSerial(), + 'warranty_class' => (string) $warr->getWarrantyClass(), + 'plate_number' => (string) $warr->getPlateNumber(), + 'status' => (string) $warr->getStatus(), + 'date_create' => (string) $warr->getDateCreate()->format('YmdHis'), + 'date_purchase' => (string) $warr->getDatePurchase()->format('Ymd'), + 'date_expire' => (string) $warr->getDateExpire()->format('Ymd'), + ]; + + $date_claim = $warr->getDateClaim(); + if ($date_claim == null) + $data['date_claim'] = null; + else + $data['date_claim'] = (string) $warr->getDateClaim()->format('Ymd'); + + return $data; + } + public function find($serial, EntityManagerInterface $em) { $clean_serial = $this->cleanSerial($serial); @@ -28,12 +86,7 @@ class WarrantyController extends Controller implements APIController $data = [ - 'warranty' => [ - 'id' => (int) $warr->getID(), - 'serial' => (string) $warr->getSerial(), - 'date_create' => (string) $warr->getDateCreate()->format('YmdHis'), - 'date_expire' => (string) $warr->getDateExpire()->format('Ymd'), - ], + 'warranty' => $this->generateWarrantyData($warr), ]; return new APIResponse(true, 'Warranty found.', $data); @@ -42,44 +95,91 @@ class WarrantyController extends Controller implements APIController public function register(Request $req, EntityManagerInterface $em) { // required parameters + $params = [ + 'serial', + 'warranty_class', + 'plate_number', + 'date_expire', + 'date_purchase', + ]; + $msg = $this->checkRequiredParameters($req, $params); + error_log('msg - ' . $msg); + if ($msg) + return new APIResponse(false, $msg); + $serial = $req->request->get('serial'); $date_expire_string = $req->request->get('date_expire'); + $date_pur_string = $req->request->get('date_purchase'); + $warr_class = $req->request->get('warranty_class'); + $plate = $req->request->get('plate_number'); - // missing serial - if ($serial == null) - return new APIResponse(false, 'Required parameter missing: serial.'); - - // missing date expire - if ($date_expire_string == null) - return new APIResponse(false, 'Required parameter missing: date_expire.'); - - // wrong date format + // wrong date expire format $date_expire = DateTime::createFromFormat('Ymd', $date_expire_string); if ($date_expire === false) return new APIResponse(false, 'Wrong date format: date_expire.'); + // wrong date purchase format + $date_pur = DateTime::createFromFormat('Ymd', $date_pur_string); + if ($date_pur === false) + return new APIResponse(false, 'Wrong date format: date_purchase.'); + + // valid warranty class + if (!WarrantyClass::validate($warr_class)) + return new APIResponse(false, 'Invalid warranty class.'); + + // plate number + $plate = Warranty::cleanPlateNumber($plate); + if (!$plate) + return new APIResponse(false, 'Invalid plate number.'); + // warranty $warr = new Warranty(); $warr->setSerial($serial) + ->setWarrantyClass($warr_class) + ->setPlateNumber($plate) + ->setDatePurchase($date_pur) + ->setDateClaim(null) ->setDateExpire($date_expire); - $em->persist($warr); - $em->flush(); + try + { + $em->persist($warr); + $em->flush(); + } + catch (UniqueConstraintViolationException $e) + { + return new APIResponse(false, 'Duplicate serial encountered.'); + } // data $data = [ - 'warranty' => [ - 'id' => (int) $warr->getID(), - 'serial' => (string) $warr->getSerial(), - 'date_create' => (string) $warr->getDateCreate(), - 'date_expire' => (string) $warr->getDateExpire(), - ], + 'warranty' => $this->generateWarrantyData($warr), ]; return new APIResponse(true, 'Warranty registered.', $data); } - public function claim($serial) + public function claim(Request $req, EntityManagerInterface $em, $serial) { + $clean_serial = $this->cleanSerial($serial); + $warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $clean_serial]); + + // no warranty + if ($warr == null) + return new APIResponse(false, 'No warranty found with that serial number.', null, 404); + + // warranty is not active + if (!$warr->canClaim()) + return new APIResponse(false, 'Warranty is not active.'); + + // set status to claim + $warr->setStatus(WarrantyStatus::CLAIMED) + ->setDateClaim(new DateTime()); + + $em->flush(); + + // TODO: claim log + + return new APIResponse(true, 'Warranty claimed successfully.'); } } diff --git a/src/Entity/Warranty.php b/src/Entity/Warranty.php index b2340a08..040c6c49 100644 --- a/src/Entity/Warranty.php +++ b/src/Entity/Warranty.php @@ -3,7 +3,10 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; +use App\Ramcar\WarrantyClass; +use App\Ramcar\WarrantyStatus; use DateTime; +use Exception; /** * @ORM\Entity @@ -30,21 +33,54 @@ class Warranty */ protected $serial; + // warranty class + /** + * @ORM\Column(type="string", length=25) + */ + protected $warranty_class; + + // plate + /** + * @ORM\Column(type="string", length=10) + */ + protected $plate_number; + + // status + /** + * @ORM\Column(type="string", length=25) + */ + protected $status; + // date created /** * @ORM\Column(type="datetime") */ protected $date_create; + // date purchased + /** + * @ORM\Column(type="date") + */ + protected $date_purchase; + // date expires /** * @ORM\Column(type="date") */ protected $date_expire; + // date claimed + /** + * @ORM\Column(type="date", nullable=true) + */ + protected $date_claim; + public function __construct() { $this->date_create = new DateTime(); + $this->warranty_class = WarrantyClass::WTY_PRIVATE; + $this->status = WarrantyStatus::ACTIVE; + $this->date_claim = null; } public function getID() @@ -63,11 +99,79 @@ class Warranty return $this->serial; } + public function setWarrantyClass($class) + { + $this->warranty_class = $class; + return $this; + } + + public function getWarrantyClass() + { + return $this->warranty_class; + } + + // TODO: use a service to handle plate number filtering + public static function cleanPlateNumber($plate) + { + // trim and make upper case + $clean_plate = strtoupper(trim($plate)); + + // remove invalid characters + $clean_plate = preg_replace("/[^A-Z0-9]/", '', $clean_plate); + + // check if format is correct + // AAA123 or AAA1234 + $res = preg_match("/^[A-Z]{3}[0-9]{3,4}$/", $clean_plate); + if ($res) + return $clean_plate; + + return false; + } + + public function setPlateNumber($plate) + { + // TODO: custom exception + $plate_number = $this->cleanPlateNumber($plate); + if (!$plate_number) + throw new Exception('Invalid plate number.'); + + $this->plate_number = $plate_number; + + return $this; + } + + public function getPlateNumber() + { + return $this->plate_number; + } + + public function setStatus($status) + { + $this->status = $status; + return $this; + } + + public function getStatus() + { + return $this->status; + } + public function getDateCreate() { return $this->date_create; } + public function setDatePurchase(DateTime $date) + { + $this->date_purchase = $date; + return $this; + } + + public function getDatePurchase() + { + return $this->date_purchase; + } + public function setDateExpire(DateTime $date) { $this->date_expire = $date; @@ -78,4 +182,26 @@ class Warranty { return $this->date_expire; } + + public function setDateClaim(DateTime $date = null) + { + $this->date_claim = $date; + return $this; + } + + public function getDateClaim() + { + return $this->date_claim; + } + + public function canClaim() + { + if ($this->status == WarrantyStatus::ACTIVE) + return true; + + if ($this->status == WarrantyStatus::CLAIMED) + return true; + + return false; + } } diff --git a/src/Ramcar/WarrantyStatus.php b/src/Ramcar/WarrantyStatus.php new file mode 100644 index 00000000..0dd419a2 --- /dev/null +++ b/src/Ramcar/WarrantyStatus.php @@ -0,0 +1,18 @@ + 'Active', + 'expired' => 'Expired', + 'claimed' => 'Claimed', + 'cancelled' => 'Cancelled', + ]; +}