diff --git a/config/routes.yaml b/config/routes.yaml index 25618dbd..c29b8a2b 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -289,6 +289,11 @@ vmfg_create_submit: controller: App\Controller\VehicleManufacturerController::createSubmit methods: [POST] +vmfg_vehicles: + path: /vehicle-manufacturers/vehicles + controller: App\Controller\VehicleManufacturerController::getVehicles + methods: [POST] + vmfg_update: path: /vehicle-manufacturers/{id} controller: App\Controller\VehicleManufacturerController::update diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 4e766ec9..6bedb575 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -26,4 +26,14 @@ label.has-danger, .flex-row > * + * { margin-left: 10px; +} + +.form-group-inner { + padding-left: 0 !important; + padding-right: 0 !important; +} + +.normal-font { + font-size: inherit !important; + font-weight: inherit !important; } \ No newline at end of file diff --git a/src/Controller/BatteryController.php b/src/Controller/BatteryController.php index eaa21098..a19b2e23 100644 --- a/src/Controller/BatteryController.php +++ b/src/Controller/BatteryController.php @@ -84,9 +84,9 @@ class BatteryController extends BaseController // check if filter is present if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) { - $query->where('mfg_name LIKE :filter') - ->orWhere('model_name LIKE :filter') - ->orWhere('size_name LIKE :filter') + $query->where('mfg.name LIKE :filter') + ->orWhere('model.name LIKE :filter') + ->orWhere('size.name LIKE :filter') ->orWhere('q.prod_code LIKE :filter') ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); } @@ -114,18 +114,19 @@ class BatteryController extends BaseController $rows = []; foreach ($obj_rows as $orow) { // add row data - $row['mfg_name'] = $orow->getManufacturer()->getName(); - $row['model_name'] = $orow->getModel()->getName(); - $row['size_name'] = $orow->getSize()->getName(); - $row['prod_code'] = $orow->getProductCode(); - $row['sell_price'] = $orow->getSellingPrice(); - $row['warr_personal'] = $orow->getWarrantyPersonal(); - $row['warr_commercial'] = $orow->getWarrantyCommercial(); - $row['res_capacity'] = $orow->getReserveCapacity(); - $row['length'] = $orow->getLength(); - $row['width'] = $orow->getWidth(); - $row['height'] = $orow->getHeight(); - $row['total_height'] = $orow->getTotalHeight(); + $row['id'] = $orow[0]->getID(); + $row['mfg_name'] = $orow['mfg_name']; + $row['model_name'] = $orow['model_name']; + $row['size_name'] = $orow['size_name']; + $row['prod_code'] = $orow[0]->getProductCode(); + $row['sell_price'] = $orow[0]->getSellingPrice(); + $row['warr_personal'] = $orow[0]->getWarrantyPersonal(); + $row['warr_commercial'] = $orow[0]->getWarrantyCommercial(); + $row['res_capacity'] = $orow[0]->getReserveCapacity(); + $row['length'] = $orow[0]->getLength(); + $row['width'] = $orow[0]->getWidth(); + $row['height'] = $orow[0]->getHeight(); + $row['total_height'] = $orow[0]->getTotalHeight(); // add row metadata $row['meta'] = [ @@ -176,22 +177,62 @@ class BatteryController extends BaseController $row = new Battery(); // set and save values - $row->setID($req->request->get('id')) - ->setName($req->request->get('name')); + $row->setProductCode($req->request->get('prod_code')) + ->setWarrantyPersonal($req->request->get('warr_personal')) + ->setWarrantyCommercial($req->request->get('warr_commercial')) + ->setReserveCapacity($req->request->get('res_capacity')) + ->setLength($req->request->get('length')) + ->setWidth($req->request->get('width')) + ->setHeight($req->request->get('height')) + ->setTotalHeight($req->request->get('total_height')) + ->setSellingPrice($req->request->get('sell_price')); - // acl attributes - $acl_attribs = $req->request->get('acl'); - foreach ($acl_attribs as $acl_key) - { - $row->addACLAccess($acl_key); + // initialize error list + $error_array = []; + + // custom validation for battery manufacturer + $manufacturer = $em->getRepository(BatteryManufacturer::class) + ->find($req->request->get('manufacturer')); + + if (empty($manufacturer)) + $error_array['manufacturer'] = 'Invalid manufacturer selected.'; + else + $row->setManufacturer($manufacturer); + + // custom validation for battery model + $model = $em->getRepository(BatteryModel::class) + ->find($req->request->get('model')); + + if (empty($model)) + $error_array['model'] = 'Invalid model selected.'; + else + $row->setModel($model); + + // custom validation for battery size + $size = $em->getRepository(BatterySize::class) + ->find($req->request->get('size')); + + if (empty($size)) + $error_array['size'] = 'Invalid size selected.'; + else + $row->setSize($size); + + // custom validation for vehicles + $vehicles = $req->request->get('vehicles'); + + if (!empty($vehicles)) { + foreach ($vehicles as $vehicle_id) { + $vehicle = $em->getRepository(Vehicle::class)->find($vehicle_id); + + if (!empty($vehicle)) { + $row->addVehicle($vehicle); + } + } } // validate $errors = $validator->validate($row); - // initialize error list - $error_array = []; - // add errors to list foreach ($errors as $error) { $error_array[$error->getPropertyPath()] = $error->getMessage(); @@ -224,7 +265,7 @@ class BatteryController extends BaseController // get row data $em = $this->getDoctrine()->getManager(); - $row = $em->getRepository(Role::class)->find($id); + $row = $em->getRepository(Battery::class)->find($id); // make sure this row exists if (empty($row)) @@ -248,36 +289,70 @@ class BatteryController extends BaseController // get row data $em = $this->getDoctrine()->getManager(); - $row = $em->getRepository(Role::class)->find($id); + $row = $em->getRepository(Battery::class)->find($id); // make sure this row exists if (empty($row)) throw $this->createNotFoundException('The item does not exist'); // set and save values - $row->setID($req->request->get('id')) - ->setName($req->request->get('name')); + $row->setProductCode($req->request->get('prod_code')) + ->setWarrantyPersonal($req->request->get('warr_personal')) + ->setWarrantyCommercial($req->request->get('warr_commercial')) + ->setReserveCapacity($req->request->get('res_capacity')) + ->setLength($req->request->get('length')) + ->setWidth($req->request->get('width')) + ->setHeight($req->request->get('height')) + ->setTotalHeight($req->request->get('total_height')) + ->setSellingPrice($req->request->get('sell_price')) + ->clearVehicles(); - // don't update acl attributes for super user since they don't need it - if (!$row->isSuperAdmin()) - { - // clear first - $row->clearACLAttributes(); + // initialize error list + $error_array = []; - // then add - $acl_attribs = $req->request->get('acl'); - foreach ($acl_attribs as $acl_key) - { - $row->addACLAccess($acl_key); + // custom validation for battery manufacturer + $manufacturer = $em->getRepository(BatteryManufacturer::class) + ->find($req->request->get('manufacturer')); + + if (empty($manufacturer)) + $error_array['manufacturer'] = 'Invalid manufacturer selected.'; + else + $row->setManufacturer($manufacturer); + + // custom validation for battery model + $model = $em->getRepository(BatteryModel::class) + ->find($req->request->get('model')); + + if (empty($model)) + $error_array['model'] = 'Invalid model selected.'; + else + $row->setModel($model); + + // custom validation for battery size + $size = $em->getRepository(BatterySize::class) + ->find($req->request->get('size')); + + if (empty($size)) + $error_array['size'] = 'Invalid size selected.'; + else + $row->setSize($size); + + // custom validation for vehicles + $vehicles = $req->request->get('vehicles'); + + if (!empty($vehicles)) { + foreach ($vehicles as $vehicle_id) { + $vehicle = $em->getRepository(Vehicle::class)->find($vehicle_id); + + if (!empty($vehicle)) { + $row->addVehicle($vehicle); + } } } // validate $errors = $validator->validate($row); - // initialize error list - $error_array = []; - // add errors to list foreach ($errors as $error) { $error_array[$error->getPropertyPath()] = $error->getMessage(); @@ -309,7 +384,7 @@ class BatteryController extends BaseController // get row data $em = $this->getDoctrine()->getManager(); - $row = $em->getRepository(Role::class)->find($id); + $row = $em->getRepository(Battery::class)->find($id); if (empty($row)) throw $this->createNotFoundException('The item does not exist'); diff --git a/src/Controller/VehicleController.php b/src/Controller/VehicleController.php index 4597e69e..bc6ad490 100644 --- a/src/Controller/VehicleController.php +++ b/src/Controller/VehicleController.php @@ -160,9 +160,9 @@ class VehicleController extends BaseController $row = new Vehicle(); // set and save values - $row->setMake($req->request->get('make')); - $row->setModelYearFrom($req->request->get('model_year_from')); - $row->setModelYearTo($req->request->get('model_year_to')); + $row->setMake($req->request->get('make')) + ->setModelYearFrom($req->request->get('model_year_from')) + ->setModelYearTo($req->request->get('model_year_to')); // initialize error list $error_array = []; @@ -173,16 +173,15 @@ class VehicleController extends BaseController if (empty($manufacturer)) $error_array['manufacturer'] = 'Invalid manufacturer selected.'; - else { + else $row->setManufacturer($manufacturer); - // validate - $errors = $validator->validate($row); + // validate + $errors = $validator->validate($row); - // add errors to list - foreach ($errors as $error) { - $error_array[$error->getPropertyPath()] = $error->getMessage(); - } + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); } // check if any errors were found @@ -241,9 +240,9 @@ class VehicleController extends BaseController throw $this->createNotFoundException('The item does not exist'); // set and save values - $row->setMake($req->request->get('make')); - $row->setModelYearFrom($req->request->get('model_year_from')); - $row->setModelYearTo($req->request->get('model_year_to')); + $row->setMake($req->request->get('make')) + ->setModelYearFrom($req->request->get('model_year_from')) + ->setModelYearTo($req->request->get('model_year_to')); // validate $errors = $validator->validate($row); diff --git a/src/Controller/VehicleManufacturerController.php b/src/Controller/VehicleManufacturerController.php index 493600f1..15dd7a07 100644 --- a/src/Controller/VehicleManufacturerController.php +++ b/src/Controller/VehicleManufacturerController.php @@ -257,7 +257,7 @@ class VehicleManufacturerController extends BaseController $response->send(); } - public function getVehicles(Request $req, $id) + public function getVehicles(Request $req) { if (!$this->isGranted('battery.add') && !$this->isGranted('battery.update')) { $exception = $this->createAccessDeniedException('No access.'); @@ -266,12 +266,27 @@ class VehicleManufacturerController extends BaseController // get row data $em = $this->getDoctrine()->getManager(); - $row = $em->getRepository(VehicleManufacturer::class)->find($id); + $row = $em->getRepository(VehicleManufacturer::class)->find($req->request->get('id')); if (empty($row)) throw $this->createNotFoundException('The item does not exist'); - // get vehicles - return $row->getVehicles(); + // build vehicles array + $vehicles = []; + + foreach ($row->getVehicles() as $vehicle) { + $vehicles[] = [ + 'id' => $vehicle->getID(), + 'mfg_name' => $vehicle->getManufacturer()->getName(), + 'make' => $vehicle->getMake(), + 'model_year_from' => $vehicle->getModelYearFrom(), + 'model_year_to' => $vehicle->getModelYearTo() + ]; + } + + // response + return $this->json([ + 'data' => $vehicles + ]); } } diff --git a/src/Entity/Battery.php b/src/Entity/Battery.php index 21408536..88383206 100644 --- a/src/Entity/Battery.php +++ b/src/Entity/Battery.php @@ -5,10 +5,12 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * @ORM\Entity * @ORM\Table(name="battery") + * @UniqueEntity("prod_code") */ class Battery { @@ -59,60 +61,69 @@ class Battery // product code /** - * @ORM\Column(type="string", length=80) + * @ORM\Column(type="string", length=80, unique=true) + * @Assert\NotBlank() */ protected $prod_code; // warranty personal /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $warr_personal; // warranty commercial /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $warr_commercial; // reserve capacity /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $res_capacity; // length /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $length; // width /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $width; // height /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $height; // total height /** * @ORM\Column(type="smallint") + * @Assert\NotBlank() */ protected $total_height; // selling price /** - * @ORM\Column(type="decimal", precision=7, scale=2) + * @ORM\Column(type="decimal", precision=7, scale=2, nullable=true) */ protected $sell_price; public function __construct() { + $this->vehicles = new ArrayCollection(); $this->cust_vehicles = new ArrayCollection(); } @@ -154,15 +165,21 @@ class Battery return $this->size; } - public function setVehicle($vehicle) + public function addVehicle(Vehicle $vehicle) { - $this->vehicle = $vehicle; + $this->vehicles->add($vehicle); return $this; } - public function getVehicle() + public function clearVehicles() { - return $this->vehicle; + $this->vehicles->clear(); + return $this; + } + + public function getVehicles() + { + return $this->vehicles; } public function setProductCode($prod_code) diff --git a/src/Entity/BatteryManufacturer.php b/src/Entity/BatteryManufacturer.php index 9cd44bf6..2d6bd21e 100644 --- a/src/Entity/BatteryManufacturer.php +++ b/src/Entity/BatteryManufacturer.php @@ -71,7 +71,7 @@ class BatteryManufacturer // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) - $str_batteries[] = $this->getName() . " " . $battery->getModel()->getName() . " " . $battery->getSize()->getName(); + $str_batteries[] = $this->getProductCode(); return $str_batteries; } diff --git a/src/Entity/BatteryModel.php b/src/Entity/BatteryModel.php index 678c2592..86f3b666 100644 --- a/src/Entity/BatteryModel.php +++ b/src/Entity/BatteryModel.php @@ -71,7 +71,7 @@ class BatteryModel // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) - $str_batteries[] = $battery->getManufacturer()->getName() . " " . $battery->getModel()->getName() . " " . $this->getName(); + $str_batteries[] = $this->getProductCode(); return $str_batteries; } diff --git a/src/Entity/BatterySize.php b/src/Entity/BatterySize.php index 79045124..a847e252 100644 --- a/src/Entity/BatterySize.php +++ b/src/Entity/BatterySize.php @@ -71,7 +71,7 @@ class BatterySize // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) - $str_batteries[] = $battery->getManufacturer()->getName() . " " . $battery->getModel()->getName() . " " . $this->getName(); + $str_batteries[] = $this->getProductCode(); return $str_batteries; } diff --git a/src/Entity/Vehicle.php b/src/Entity/Vehicle.php index 4a53a9dd..bae6148e 100644 --- a/src/Entity/Vehicle.php +++ b/src/Entity/Vehicle.php @@ -133,7 +133,7 @@ class Vehicle // has to return set of strings because symfony is trying to move away from role objects $str_batteries = []; foreach ($this->batteries as $battery) - $str_batteries[] = $battery->getManufacturer()->getName() . " " . $battery->getModel()->getName() . " " . $battery->getSize()->getName(); + $str_batteries[] = $this->getProductCode(); return $str_batteries; } diff --git a/src/Entity/VehicleManufacturer.php b/src/Entity/VehicleManufacturer.php index 2c59cbfa..48de14b0 100644 --- a/src/Entity/VehicleManufacturer.php +++ b/src/Entity/VehicleManufacturer.php @@ -68,11 +68,6 @@ class VehicleManufacturer public function getVehicles() { - // has to return set of strings because symfony is trying to move away from role objects - $str_vehicles = []; - foreach ($this->vehicles as $vehicle) - $str_vehicles[$vehicle->getID()] = $vehicle->getMake() . " " . $vehicle->getYearFrom() . "-" . $vehicle->getYearTo(); - - return $str_vehicles; + return $this->vehicles; } } diff --git a/templates/battery/form.html.twig b/templates/battery/form.html.twig index 29187178..74629ffc 100644 --- a/templates/battery/form.html.twig +++ b/templates/battery/form.html.twig @@ -32,30 +32,194 @@ -
+
-
- -
- +
+
+

+ Product Information +

- -
- +
+ +
+ + + Unique identifier for this product +
+ +
+ + +
+
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+
+

+ Warranty +

+
+
+ +
+ + + In months +
+ +
+ + + In months +
+
+
+
+
+

+ Specifications +

+
+
+ +
+ + + In millimeters (mm) +
+ +
+ + + In millimeters (mm) +
+ +
+ + + In millimeters (mm) +
+
+
+ +
+ + + In millimeters (mm) +
+ +
+ + + In minutes +
+
+
+
+
+
+
+
+
+
+
+
+

+ Vehicle Compatibility +

+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ +
+
+
+
+
+
+
@@ -64,7 +228,7 @@
- Cancel + Cancel
@@ -81,13 +245,23 @@ $(function() { $("#row-form").submit(function(e) { var form = $(this); + var formdata = form.serialize(); e.preventDefault(); + // add vehicle data + vdata = ''; + $.each(vehicleRows, function(index, vehicle) { + vdata += "&vehicles%5B%5D=" + vehicle.id; + }); + + // append to form data + formdata += vdata; + $.ajax({ method: "POST", url: form.prop('action'), - data: form.serialize() + data: formdata }).done(function(response) { // remove all error classes removeErrors(); @@ -96,7 +270,7 @@ text: 'Your changes have been saved!', type: 'success', onClose: function() { - window.location.href = "{{ url('role_list') }}"; + window.location.href = "{{ url('battery_list') }}"; } }); }).fail(function(response) { @@ -141,6 +315,160 @@ $("[data-field]").removeClass('has-danger'); $(".form-control-feedback[data-field]").addClass('hide'); } + + // initialize vehicle arrays + var mfgVehicles = []; + var vehicleRows = []; + var vehicleIds = []; + + {% if row is defined %} + {% for vehicle in row.getVehicles() %} + vrow = { + id: "{{ vehicle.getID() }}", + mfg_name: "{{ vehicle.getManufacturer().getName() }}", + make: "{{ vehicle.getMake() }}", + model_year_from: "{{ vehicle.getModelYearFrom() }}", + model_year_to: "{{ vehicle.getModelYearTo() }}" + }; + + vehicleRows.push(vrow); + vehicleIds.push("{{ vehicle.getID() }}"); + {% endfor %} + {% endif %} + + // update vehicle list when changing manufacturer + $("#vmfg").change(function() { + var id = $(this).val(); + var vehiclefield = $("#vehicle"); + var btn = $("#btn-add-vehicle"); + + // no id specified + if (!id) { + vehiclefield.html('').prop('disabled', true); + btn.prop('disabled', true); + return true; + } + + mfgVehicles = []; + + // get vehicles for this manufacturer + $.ajax({ + method: "POST", + url: "{{ url('vmfg_vehicles') }}", + data: {id: id} + }).done(function(response) { + if (response.data) { + var html = ''; + + $.each(response.data, function(index, vehicle) { + html += ''; + }); + + vehiclefield.html(html).prop('disabled', false); + btn.prop('disabled', false); + mfgVehicles = response.data; + } else { + vehiclefield.html('').prop('disabled', true); + btn.prop('disabled', true); + } + }) + }); + + // add a vehicle to the table + $("#btn-add-vehicle").click(function() { + var id = $("#vehicle").val(); + var index = $("#vehicle").find(":selected").data('index'); + + if (vehicleIds.indexOf(id) !== -1) { + swal({ + title: 'Whoops', + text: 'This vehicle is already on the list.', + type: 'warning' + }); + + return true; + } + + // add vehicle to arrays + vehicleIds.push(id); + vehicleRows.push(mfgVehicles[index]); + + // refresh the data table + table.originalDataSet = vehicleRows; + table.reload(); + }); + + // remove vehicle from table + $(document).on('click', '.btn-delete', function(e) { + var btn = $(this); + var id = $(this).data('id'); + + $.each(vehicleRows, function(index, vehicle) { + if (vehicle.id == id) { + vehicleRows.splice(index, 1); + return false; + } + }); + + // remove from vehicle ids + vehicleIds.splice(vehicleIds.indexOf(id), 1); + + // reload table + table.row(btn.parents('tr')).remove(); + table.originalDataSet = vehicleRows; + table.reload(); + }); + + // data table + var options = { + data: { + type: 'local', + source: vehicleRows, + saveState: { + cookie: false, + webstorage: false + } + }, + layout: { + scroll: true + }, + columns: [ + { + field: 'id', + title: 'ID', + width: 30 + }, + { + field: 'mfg_name', + title: 'Manufacturer' + }, + { + field: 'make', + title: 'Make' + }, + { + field: 'model_year_from', + title: 'Year', + template: function (data) { + return data.model_year_from + ' - ' + data.model_year_to; + } + }, + { + field: 'Actions', + width: 70, + title: 'Actions', + sortable: false, + overflow: 'visible', + locked: {right: 'xl'}, + template: function (row, index, datatable) { + return ''; + }, + } + ], + pagination: false + }; + + var table = $("#data-vehicles").mDatatable(options); }); {% endblock %} diff --git a/templates/battery/list.html.twig b/templates/battery/list.html.twig index d3cc3cc8..a81f1e5d 100644 --- a/templates/battery/list.html.twig +++ b/templates/battery/list.html.twig @@ -78,13 +78,18 @@ scroll: true }, columns: [ + { + field: 'id', + title: 'ID', + width: 30 + }, { field: 'mfg_name', title: 'Manufacturer', width: 150 }, { - field: 'mdl_name', + field: 'model_name', title: 'Model', width: 150 }, @@ -143,11 +148,11 @@ var actions = ''; if (row.meta.update_url != '') { - actions += ''; + actions += ''; } if (row.meta.delete_url != '') { - actions += ''; + actions += ''; } return actions;