diff --git a/config/acl.yaml b/config/acl.yaml index 47d08fbd..e9b2e330 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -114,4 +114,17 @@ access_keys: - id: vmfg.update label: Update - id: vmfg.delete + label: Delete + - id: customer + label: Customer Access + acls: + - id: customer.menu + label: Menu + - id: customer.list + label: List + - id: customer.add + label: Add + - id: customer.update + label: Update + - id: customer.delete label: Delete \ No newline at end of file diff --git a/config/menu.yaml b/config/menu.yaml index e18a6ebb..8c508f12 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -43,4 +43,8 @@ main_menu: - id: vmfg_list acl: vmfg.list label: Vehicle Manufacturers + parent: database + - id: customer_list + acl: customer.list + label: Customers parent: database \ No newline at end of file diff --git a/config/routes.yaml b/config/routes.yaml index c29b8a2b..12dac046 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -235,36 +235,36 @@ bsize_delete: # vehicles vehicle_list: - path: /vehicle + path: /vehicles controller: App\Controller\VehicleController::index vehicle_rows: - path: /vehicle/rows + path: /vehicles/rows controller: App\Controller\VehicleController::rows methods: [POST] vehicle_create: - path: /vehicle/create + path: /vehicles/create controller: App\Controller\VehicleController::create methods: [GET] vehicle_create_submit: - path: /vehicle/create + path: /vehicles/create controller: App\Controller\VehicleController::createSubmit methods: [POST] vehicle_update: - path: /vehicle/{id} + path: /vehicles/{id} controller: App\Controller\VehicleController::update methods: [GET] vehicle_update_submit: - path: /vehicle/{id} + path: /vehicles/{id} controller: App\Controller\VehicleController::updateSubmit methods: [POST] vehicle_delete: - path: /vehicle/{id} + path: /vehicles/{id} controller: App\Controller\VehicleController::destroy methods: [DELETE] @@ -309,6 +309,42 @@ vmfg_delete: controller: App\Controller\VehicleManufacturerController::destroy methods: [DELETE] +# customers + +customer_list: + path: /customers + controller: App\Controller\CustomerController::index + +customer_rows: + path: /customers/rows + controller: App\Controller\CustomerController::rows + methods: [POST] + +customer_create: + path: /customers/create + controller: App\Controller\CustomerController::create + methods: [GET] + +customer_create_submit: + path: /customers/create + controller: App\Controller\CustomerController::createSubmit + methods: [POST] + +customer_update: + path: /customers/{id} + controller: App\Controller\CustomerController::update + methods: [GET] + +customer_update_submit: + path: /customers/{id} + controller: App\Controller\CustomerController::updateSubmit + methods: [POST] + +customer_delete: + path: /customers/{id} + controller: App\Controller\CustomerController::destroy + methods: [DELETE] + # test test_acl: diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php new file mode 100644 index 00000000..e9a0d774 --- /dev/null +++ b/src/Controller/CustomerController.php @@ -0,0 +1,269 @@ +acl_gen = $acl_gen; + parent::__construct($menu_gen); + } + + public function index() + { + $this->denyAccessUnlessGranted('customer.list', null, 'No access.'); + + $params = $this->initParameters('customer_list'); + + // response + return $this->render('customer/list.html.twig', $params); + } + + public function rows(Request $req) + { + $this->denyAccessUnlessGranted('customer.list', null, 'No access.'); + + // build query + $qb = $this->getDoctrine() + ->getRepository(Customer::class) + ->createQueryBuilder('q'); + + // count total records + $total = $qb->select('COUNT(q)') + ->getQuery() + ->getSingleScalarResult(); + + // get datatable params + $datatable = $req->request->get('datatable'); + + // get current page number + $page = $datatable['pagination']['page'] ?? 1; + + $perpage = $datatable['pagination']['perpage']; + $offset = ($page - 1) * $perpage; + + // add metadata + $meta = [ + 'page' => $page, + 'perpage' => $perpage, + 'pages' => ceil($total / $perpage), + 'total' => $total, + 'sort' => 'asc', + 'field' => 'id' + ]; + + // build query + $query = $qb->select('q'); + + // check if filter is present + if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) { + $query->where('q.first_name LIKE :filter') + ->orWhere('q.last_name LIKE :filter') + ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); + } + + // check if sorting is present, otherwise use default + if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) { + $order = $datatable['sort']['sort'] ?? 'asc'; + $query->orderBy('q.' . $datatable['sort']['field'], $order); + } else { + $query->orderBy('q.first_name', 'asc'); + } + + // get rows for this page + $obj_rows = $query->setFirstResult($offset) + ->setMaxResults($perpage) + ->getQuery() + ->getResult(); + + // process rows + $rows = []; + foreach ($obj_rows as $orow) { + // add row data + $row['id'] = $orow->getID(); + $row['first_name'] = $orow->getFirstName(); + $row['last_name'] = $orow->getLastName(); + + // add row metadata + $row['meta'] = [ + 'update_url' => '', + 'delete_url' => '' + ]; + + // add crud urls + if ($this->isGranted('user.update')) + $row['meta']['update_url'] = $this->generateUrl('customer_update', ['id' => $row['id']]); + if ($this->isGranted('user.delete')) + $row['meta']['delete_url'] = $this->generateUrl('customer_delete', ['id' => $row['id']]); + + $rows[] = $row; + } + + // response + return $this->json([ + 'meta' => $meta, + 'data' => $rows + ]); + } + + public function create() + { + $this->denyAccessUnlessGranted('customer.add', null, 'No access.'); + + $params = $this->initParameters('customer_list'); + + $em = $this->getDoctrine()->getManager(); + + // get parent associations + $params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll(); + + // response + return $this->render('customer/form.html.twig', $params); + } + + public function createSubmit(Request $req, ValidatorInterface $validator) + { + $this->denyAccessUnlessGranted('customer.add', null, 'No access.'); + + // create new row + $em = $this->getDoctrine()->getManager(); + $row = new Customer(); + + // set and save values + $row->setName($req->request->get('name')); + + // validate + $errors = $validator->validate($row); + + // initialize error list + $error_array = []; + + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } else { + // validated! save the entity + $em->persist($row); + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + } + + public function update($id) + { + $this->denyAccessUnlessGranted('customer.update', null, 'No access.'); + + $params = $this->initParameters('customer_list'); + + // get row data + $em = $this->getDoctrine()->getManager(); + $row = $em->getRepository(Customer::class)->find($id); + + // make sure this row exists + if (empty($row)) + throw $this->createNotFoundException('The item does not exist'); + + $params['row'] = $row; + $params['values'] = []; + + // response + return $this->render('customer/form.html.twig', $params); + } + + public function updateSubmit(Request $req, ValidatorInterface $validator, $id) + { + $this->denyAccessUnlessGranted('customer.update', null, 'No access.'); + + // get row data + $em = $this->getDoctrine()->getManager(); + $row = $em->getRepository(Customer::class)->find($id); + + // make sure this row exists + if (empty($row)) + throw $this->createNotFoundException('The item does not exist'); + + // set and save values + $row->setName($req->request->get('name')); + + // validate + $errors = $validator->validate($row); + + // initialize error list + $error_array = []; + + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } else { + // validated! save the entity + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + } + + public function destroy($id) + { + $this->denyAccessUnlessGranted('customer.delete', null, 'No access.'); + + $params = $this->initParameters('customer_list'); + + // get row data + $em = $this->getDoctrine()->getManager(); + $row = $em->getRepository(Customer::class)->find($id); + + if (empty($row)) + throw $this->createNotFoundException('The item does not exist'); + + // delete this row + $em->remove($row); + $em->flush(); + + // response + $response = new Response(); + $response->setStatusCode(Response::HTTP_OK); + $response->send(); + } +} diff --git a/src/Entity/Battery.php b/src/Entity/Battery.php index 88383206..87ed9666 100644 --- a/src/Entity/Battery.php +++ b/src/Entity/Battery.php @@ -295,11 +295,6 @@ class Battery public function getCustomerVehicles() { - // has to return set of strings because symfony is trying to move away from role objects - $str_cust_vehicles = []; - foreach ($this->cust_vehicles as $cust_vehicle) - $str_cust_vehicles[] = $cust_vehicle->getName(); - - return $str_cust_vehicles; + return $this->cust_vehicles; } } diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index 1392a28a..6094bb31 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -4,6 +4,7 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; +use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Entity @@ -22,12 +23,14 @@ class Customer // first name /** * @ORM\Column(type="string", length=80) + * @Assert\NotBlank() */ protected $first_name; // last name /** * @ORM\Column(type="string", length=80) + * @Assert\NotBlank() */ protected $last_name; @@ -61,4 +64,93 @@ class Customer $this->sessions = new ArrayCollection(); $this->vehicles = new ArrayCollection(); } + + public function getID() + { + return $this->id; + } + + public function setFirstName($first_name) + { + $this->first_name = $first_name; + return $this; + } + + public function getFirstName() + { + return $this->first_name; + } + + public function setLastName($last_name) + { + $this->last_name = $last_name; + return $this; + } + + public function getLastName() + { + return $this->last_name; + } + + public function addMobileNumber(MobileNumber $number) + { + $this->numbers->add($number); + return $this; + } + + public function clearMobileNumbers() + { + $this->numbers->clear(); + return $this; + } + + public function getMobileNumbers() + { + return $this->numbers; + } + + public function addMobileSession(MobileSession $session) + { + $this->sessions->add($session); + return $this; + } + + public function clearMobileSessions() + { + $this->sessions->clear(); + return $this; + } + + public function getMobileSessions() + { + return $this->sessions; + } + + public function addVehicle(Vehicle $vehicle) + { + $this->vehicles->add($vehicle); + return $this; + } + + public function clearVehicles() + { + $this->vehicles->clear(); + return $this; + } + + public function getVehicles() + { + return $this->vehicles; + } + + public function setConfirmed($flag_confirmed = true) + { + $this->flag_confirmed = $flag_confirmed; + return $this; + } + + public function isConfirmed() + { + return $this->flag_confirmed; + } } diff --git a/src/Entity/CustomerVehicle.php b/src/Entity/CustomerVehicle.php index 8e1393ec..5f26ab23 100644 --- a/src/Entity/CustomerVehicle.php +++ b/src/Entity/CustomerVehicle.php @@ -4,6 +4,8 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; + /** * @ORM\Entity * @ORM\Table(name="customer_vehicle") @@ -28,6 +30,7 @@ class CustomerVehicle /** * @ORM\ManyToOne(targetEntity="Customer", inversedBy="vehicles") * @ORM\JoinColumn(name="customer_id", referencedColumnName="id") + * @Assert\NotBlank() */ protected $customer; @@ -35,30 +38,35 @@ class CustomerVehicle /** * @ORM\ManyToOne(targetEntity="Vehicle", inversedBy="customers") * @ORM\JoinColumn(name="vehicle_id", referencedColumnName="id") + * @Assert\NotBlank() */ protected $vehicle; // plate number /** * @ORM\Column(type="string", length=10) + * @Assert\NotBlank() */ protected $plate_number; // model year /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $model_year; // vehicle status (new / second-hand) /** * @ORM\Column(type="string", length=15) + * @Assert\NotBlank() */ protected $status_condition; // fuel type - diesel, gas /** * @ORM\Column(type="string", length=15) + * @Assert\NotBlank() */ protected $fuel_type; @@ -66,12 +74,14 @@ class CustomerVehicle // TODO: figure out how to check expiration /** * @ORM\Column(type="string", length=20) + * @Assert\NotBlank() */ protected $warranty_code; // date that battery warranty expires /** * @ORM\Column(type="date") + * @Assert\NotBlank() */ protected $warranty_expiration; @@ -79,6 +89,7 @@ class CustomerVehicle /** * @ORM\ManyToOne(targetEntity="Battery", inversedBy="cust_vehicles") * @ORM\JoinColumn(name="battery_id", referencedColumnName="id") + * @Assert\NotBlank() */ protected $curr_battery; @@ -93,4 +104,130 @@ class CustomerVehicle * @ORM\Column(type="boolean") */ protected $flag_active; + + public function getID() + { + return $this->id; + } + + public function setCustomer(Customer $customer) + { + $this->customer = $customer; + return $this; + } + + public function getCustomer() + { + return $this->customer; + } + + public function setVehicle(Vehicle $vehicle) + { + $this->vehicle = $vehicle; + return $this; + } + + public function getVehicle() + { + return $this->vehicle; + } + + public function setPlateNumber($plate_number) + { + $this->plate_number = $plate_number; + return $this; + } + + public function getPlateNumber() + { + return $this->plate_number; + } + + public function setModelYear($model_year) + { + $this->model_year = $model_year; + return $this; + } + + public function getModelYear() + { + return $this->model_year; + } + + public function setStatusCondition($status_condition) + { + $this->status_condition = $status_condition; + return $this; + } + + public function getStatusCondition() + { + return $this->status_condition; + } + + public function setFuelType($fuel_type) + { + $this->fuel_type = $fuel_type; + return $this; + } + + public function getFuelType() + { + return $this->fuel_type; + } + + public function setWarrantyCode($warranty_code) + { + $this->warranty_code = $warranty_code; + return $this; + } + + public function getWarrantyCode() + { + return $this->warranty_code; + } + + public function setWarrantyExpiration($warranty_expiration) + { + $this->warranty_expiration = $warranty_expiration; + return $this; + } + + public function getWarrantyExpiration() + { + return $this->warranty_expiration; + } + + public function setCurrentBattery($curr_battery) + { + $this->curr_battery = $curr_battery; + return $this; + } + + public function getCurrentBattery() + { + return $this->curr_battery; + } + + public function setHasMotoliteBattery($flag_motolite_battery = true) + { + $this->flag_motolite_battery = $flag_motolite_battery; + return $this; + } + + public function hasMotoliteBattery() + { + return $this->flag_motolite_battery; + } + + public function setActive($active = true) + { + $this->active = $active; + return $this; + } + + public function isActive() + { + return $this->active; + } } diff --git a/src/Entity/MobileNumber.php b/src/Entity/MobileNumber.php index 1b7209c2..06d379f2 100644 --- a/src/Entity/MobileNumber.php +++ b/src/Entity/MobileNumber.php @@ -4,6 +4,8 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\Constraints as Assert; + /** * @ORM\Entity * @ORM\Table(name="mobile_number") @@ -15,6 +17,7 @@ class MobileNumber /** * @ORM\Id * @ORM\Column(type="string", length=12) + * @Assert\NotBlank() */ protected $id; @@ -22,6 +25,7 @@ class MobileNumber /** * @ORM\ManyToOne(targetEntity="Customer", inversedBy="numbers") * @ORM\JoinColumn(name="customer_id", referencedColumnName="id") + * @Assert\NotBlank() */ protected $customer; @@ -55,4 +59,59 @@ class MobileNumber $this->confirm_code = null; $this->flag_confirmed = false; } + + public function setID($id) + { + $this->id = $id; + return $this; + } + + public function getID() + { + return $this->id; + } + + public function setCustomer(Customer $customer) + { + $this->customer = $customer; + return $this; + } + + public function getCustomer() + { + return $this->customer; + } + + public function setConfirmCode($confirm_code) + { + $this->confirm_code = $confirm_code; + return $this; + } + + public function getConfirmCode() + { + return $this->confirm_code; + } + + public function setDateRegistered($date_registered) + { + $this->date_registered = $date_registered; + return $this; + } + + public function getDateRegistered() + { + return $this->date_registered; + } + + public function setDateConfirmed($date_confirmed) + { + $this->date_confirmed = $date_confirmed; + return $this; + } + + public function getDateConfirmed() + { + return $this->date_confirmed; + } } diff --git a/templates/battery/form.html.twig b/templates/battery/form.html.twig index 74629ffc..dafd0455 100644 --- a/templates/battery/form.html.twig +++ b/templates/battery/form.html.twig @@ -32,192 +32,183 @@ -