denyAccessUnlessGranted('warranty.list', null, 'No access.'); return $this->render('warranty/list.html.twig'); } public function rows(Request $req) { $this->denyAccessUnlessGranted('warranty.list', null, 'No access.'); // get query builder $qb = $this->getDoctrine() ->getRepository(Warranty::class) ->createQueryBuilder('q'); // get datatable params $datatable = $req->request->get('datatable'); // count total records $tquery = $qb->select('COUNT(q)'); // add filters to count query $this->setQueryFilters($datatable, $tquery); $total = $tquery->getQuery() ->getSingleScalarResult(); // 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'); // add filters to query $this->setQueryFilters($datatable, $query); // 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.id', '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['serial'] = $orow->getSerial(); $row['plate_number'] = $orow->getPlateNumber(); $row['warranty_class'] = $orow->getWarrantyClass(); $row['status'] = $orow->getStatus(); $row['is_activated'] = $orow->isActivated(); // add row metadata $row['meta'] = [ 'update_url' => '', ]; // add crud urls if ($this->isGranted('warranty.update')) $row['meta']['update_url'] = $this->generateUrl('warranty_update', ['id' => $row['id']]); $rows[] = $row; } // response return $this->json([ 'meta' => $meta, 'data' => $rows ]); } /** * @Menu(selected="warranty_list") */ public function addForm() { $this->denyAccessUnlessGranted('warranty.add', null, 'No access.'); $params['obj'] = new Warranty(); $params['mode'] = 'create'; // get dropdown parameters $this->fillDropdownParameters($params); // response return $this->render('warranty/form.html.twig', $params); } public function addSubmit(Request $req, ValidatorInterface $validator) { $this->denyAccessUnlessGranted('warranty.add', null, 'No access.'); // create new row $em = $this->getDoctrine()->getManager(); $obj = new Warranty(); $date_purchase = DateTime::createFromFormat('d M Y', $req->request->get('date_purchase')); $date_claim = DateTime::createFromFormat('d M Y', $req->request->get('date_claim')); $date_expire = DateTime::createFromFormat('d M Y', $req->request->get('date_expire')); // set and save values $obj->setSerial($req->request->get('serial')) ->setWarrantyClass($req->request->get('warranty_class')) ->setFirstName($req->request->get('first_name')) ->setLastName($req->request->get('last_name')) ->setMobileNumber($req->request->get('mobile_number')) ->setDatePurchase($date_purchase) ->setClaimedFrom($req->request->get('claim_from')) ->setStatus($req->request->get('status')); if ($date_claim) { $obj->setDateClaim($date_claim); } if ($date_expire) { $obj->setDateExpire($date_expire); } // custom validation for battery model $model = $em->getRepository(BatteryModel::class) ->find($req->request->get('battery_model')); if (empty($model)) $error_array['battery_model'] = 'Invalid model selected.'; else $obj->setBatteryModel($model); // custom validation for battery size $size = $em->getRepository(BatterySize::class) ->find($req->request->get('battery_size')); if (empty($size)) $error_array['battery_size'] = 'Invalid size selected.'; else $obj->setBatterySize($size); // custom validation for SAP battery $sap = $em->getRepository(SAPBattery::class) ->find($req->request->get('sap_battery')); if (empty($sap)) $error_array['sap_battery'] = 'Invalid SAP battery selected.'; else $obj->setSAPBattery($sap); // validate $errors = $validator->validate($obj); $cleaned_plate_number = Warranty::cleanPlateNumber($req->request->get('plate_number')); if (!$cleaned_plate_number) { $error_array['plate_number'] = 'Invalid plate number specified.'; } $obj->setPlateNumber($cleaned_plate_number); // 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($obj); $em->flush(); // return successful response return $this->json([ 'success' => 'Changes have been saved!' ]); } } /** * @Menu(selected="warranty_list") */ public function updateForm($id) { $this->denyAccessUnlessGranted('warranty.update', null, 'No access.'); $params['mode'] = 'update'; // get row data $em = $this->getDoctrine()->getManager(); $obj = $em->getRepository(Warranty::class)->find($id); // make sure this row exists if (empty($obj)) throw $this->createNotFoundException('The item does not exist'); $params['obj'] = $obj; // get dropdown parameters $this->fillDropdownParameters($params); // response return $this->render('warranty/form.html.twig', $params); } public function updateSubmit(Request $req, ValidatorInterface $validator, $id) { $this->denyAccessUnlessGranted('warranty.update', null, 'No access.'); // get row data $em = $this->getDoctrine()->getManager(); $obj = $em->getRepository(Warranty::class)->find($id); // make sure this row exists if (empty($obj)) throw $this->createNotFoundException('The item does not exist'); $date_purchase = DateTime::createFromFormat('d M Y', $req->request->get('date_purchase')); $date_claim = DateTime::createFromFormat('d M Y', $req->request->get('date_claim')); $date_expire = DateTime::createFromFormat('d M Y', $req->request->get('date_expire')); // set and save values $obj->setSerial($req->request->get('serial')) ->setWarrantyClass($req->request->get('warranty_class')) ->setFirstName($req->request->get('first_name')) ->setLastName($req->request->get('last_name')) ->setMobileNumber($req->request->get('mobile_number')) ->setDatePurchase($date_purchase) ->setClaimedFrom($req->request->get('claim_from')) ->setStatus($req->request->get('status')); if ($date_claim) { $obj->setDateClaim($date_claim); } if ($date_expire) { $obj->setDateExpire($date_expire); } // custom validation for battery model $model = $em->getRepository(BatteryModel::class) ->find($req->request->get('battery_model')); if (empty($model)) $error_array['battery_model'] = 'Invalid model selected.'; else $obj->setBatteryModel($model); // custom validation for battery size $size = $em->getRepository(BatterySize::class) ->find($req->request->get('battery_size')); if (empty($size)) $error_array['battery_size'] = 'Invalid size selected.'; else $obj->setBatterySize($size); // custom validation for SAP battery $sap = $em->getRepository(SAPBattery::class) ->find($req->request->get('sap_battery')); if (empty($sap)) $error_array['sap_battery'] = 'Invalid SAP battery selected.'; else $obj->setSAPBattery($sap); // validate $errors = $validator->validate($obj); $cleaned_plate_number = Warranty::cleanPlateNumber($req->request->get('plate_number')); if (!$cleaned_plate_number) { $error_array['plate_number'] = 'Invalid plate number specified.'; } $obj->setPlateNumber($cleaned_plate_number); // 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($obj); $em->flush(); // return successful response return $this->json([ 'success' => 'Changes have been saved!' ]); } } /** * @Menu(selected="warranty_list") */ public function uploadForm() { $this->denyAccessUnlessGranted('warranty.upload', null, 'No access.'); return $this->render('warranty/upload.form.html.twig'); } /** * @Menu(selected="warranty_list") */ public function uploadSubmit(Request $req, EntityManagerInterface $em) { // retrieve temporary info for file $file = $req->files->get('csv_file'); // process the csv file $inv_entries = $this->processWarrantyFile($file, $em); $resp = new StreamedResponse(); $resp->setCallback(function() use($inv_entries) { // csv output $csv_handle = fopen('php://output', 'w+'); fputcsv($csv_handle, [ 'Owner First Name', 'Owner Last Name', 'Owner Email', 'Owner Address', 'Owner Mobile', 'Owner Telephone', 'Vehicle Make', 'Vehicle Model', 'Vehicle Year', 'Vehicle Plate Number', 'Battery Serial Number', 'Battery Sales Invoice', 'Battery Date of Purchase', 'Distributor Name', 'Distributor Address', 'Application Type ID', 'Battery ID', 'Ownership Type', 'Reason Warranty Not Added', ]); foreach ($inv_entries as $row) { fputcsv($csv_handle, $row); } fclose($csv_handle); }); $filename = 'invalid_warranties' . '.csv'; $resp->setStatusCode(200); $resp->headers->set('Content-Type', 'text/csv; charset=utf-8'); $resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); return $resp; } protected function processWarrantyFile(UploadedFile $csv_file, EntityManagerInterface $em) { // attempt to open file try { $fh = fopen($csv_file, "r"); } catch (Exception $e) { throw new Exception('The file "' . $csv_file . '" could be read.'); } // loop through the rows // 0 - Owner First Name // 1 - Owner Last Name // 2 - Owner Email // 3 - Owner Address // 4 - Owner Mobile // 5 - Owner Telephone // 6 - Vehicle Make // 7 - Vehicle Model // 8 - Vehicle Year // 9 - Vehicle Plate Number // 10 - Battery Serial Number // 11 - Battery Sales Invoice // 12 - Battery Date of Purchase // 13 - Distributor Name // 14 - Distributor Address // 15 - Application Type ID // 16 - Battery ID // 17 - Ownership Type $row_num = 0; $invalid_entries = []; while (($fields = fgetcsv($fh)) !== false) { // start processing at row 1, not 0 if ($row_num < 1) { $row_num++; continue; } // get the data $first_name = trim($fields[0]); $last_name = trim($fields[1]); $mobile_number = trim($fields[4]); $plate = trim($fields[9]); $serial = trim($fields[10]); $purchase_date = trim($fields[12]); $battery_id = trim($fields[16]); $plate_number = $this->cleanPlateNumber($plate); // check if purchase_date or plate_number or serial is empty or if // purchase date is valid $date_purchase = DateTime::createFromFormat('d-M-y', $purchase_date); if (empty($purchase_date) || empty($plate_number) || empty($serial) || ($date_purchase == false)) { $reason = ''; if (empty($plate_number)) $reason = $reason . self::PLATE_NUM_EMPTY . ' '; if (empty($serial)) $reason = $reason . self::SERIAL_EMPTY . ' '; if (empty($purchase_date)) $reason = $reason . self::PURCHASE_DATE_EMPTY . ' '; else { if ($date_purchase == false) $reason = $reason . self::PURCHASE_DATE_INVALID . ' '; } // add to invalid_entries $invalid_entries[] = [ 'owner_first_name' => $first_name, 'owner_last_name' => $last_name, 'owner_email' => trim($fields[2]), 'owner_address' => trim($fields[3]), 'owner_mobile' => $mobile_number, 'owner_telephone' => trim($fields[5]), 'vehicle_make' => trim($fields[6]), 'vehicle_model' => trim($fields[7]), 'vehicle_year' => trim($fields[8]), 'vehicle_plate_number' => $plate_number, 'battery_serial_number' => $serial, 'battery_sales_invoice' => trim($fields[11]), 'battery_date_purchase' => $purchase_date, 'distributor_name' => trim($fields[13]), 'distributor_address' => trim($fields[14]), 'application_type_id' => trim($fields[15]), 'battery_id' => $battery_id, 'ownership_type' => trim($fields[17]), 'reason' => $reason, ]; } 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]); if (!empty($warr_results)) { foreach($warr_results as $warr) { // 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 (!empty($battery_id)) { // find battery $battery = $em->getRepository(Battery::class)->find($battery_id); if (!empty($battery)) { // get the battery model and battery size $model_id = $battery->getModel()->getID(); $size_id = $battery->getSize()->getID(); $bty_model = $em->getRepository(BatteryModel::class)->find($model_id); $bty_size = $em->getRepository(BatterySize::class)->find($size_id); if ($bty_model != null) { $warr->setBatteryModel($bty_model); } if ($bty_size != null) { $warr->setBatterySize($bty_size); } $sap_code = $battery->getSAPCode(); if (!empty($sap_code)) { // find sap battery $sap_batt = $em->getRepository(SAPBattery::class)->find($sap_code); if (!empty($sap_batt)) { $warr->setSAPBattery($sap_batt); } } } } } if (empty($warr->getDatePurchase())) { if (!empty($date_purchase)) { $warr->setDatePurchase($date_purchase); } } // TODO: compute expiry date $em->persist($warr); $em->flush(); } } else { // new warranty $warranty = new Warranty(); // get the battery purchased // check battery first. If not found, check sap_battery $battery = $em->getRepository(Battery::class)->find($battery_id); if ($battery != null) { // get the battery model and battery size $model_id = $battery->getModel()->getID(); $size_id = $battery->getSize()->getID(); $bty_model = $em->getRepository(BatteryModel::class)->find($model_id); $bty_size = $em->getRepository(BatterySize::class)->find($size_id); if ($bty_model != null) { $warranty->setBatteryModel($bty_model); } if ($bty_size != null) { $warranty->setBatterySize($bty_size); } } else { // find battery in sap_battery $battery = $em->getRepository(SAPBattery::class)->find($battery_id); if ($battery != null) { // battery is SAPBattery $warranty->setSAPBattery($battery); } } // TODO: compute expiry date // 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(); } } $row_num++; } return $invalid_entries; } protected function fillDropdownParameters(&$params) { $em = $this->getDoctrine()->getManager(); $params['batt_models'] = $em->getRepository(BatteryModel::class)->findAll(); $params['batt_sizes'] = $em->getRepository(BatterySize::class)->findAll(); $params['sap_batts'] = $em->getRepository(SAPBattery::class)->findAll(); $params['warranty_classes'] = WarrantyClass::getCollection(); $params['warranty_statuses'] = WarrantyStatus::getCollection(); } // check if datatable filter is present and append to query protected function setQueryFilters($datatable, &$query) { if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) { $query->where('q.serial LIKE :filter') ->orWhere('q.plate_number LIKE :filter') ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); } } protected function cleanPlateNumber($plate) { // remove spaces and make upper case return strtoupper(str_replace(' ', '', $plate)); } }