diff --git a/config/routes/customer.yaml b/config/routes/customer.yaml index 39a2f9a0..89d361f5 100644 --- a/config/routes/customer.yaml +++ b/config/routes/customer.yaml @@ -7,6 +7,16 @@ customer_rows: controller: App\Controller\CustomerController::rows methods: [POST] +customer_vehicle_search: + path: /customers/vehicles + controller: App\Controller\CustomerController::getCustomerVehicles + methods: [GET] + +customer_vehicle_info: + path: /customers/vehicle-info + controller: App\Controller\CustomerController::getCustomerVehicleInfo + methods: [GET] + customer_create: path: /customers/create controller: App\Controller\CustomerController::addForm @@ -31,4 +41,3 @@ customer_delete: path: /customers/{id} controller: App\Controller\CustomerController::destroy methods: [DELETE] - diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml new file mode 100644 index 00000000..a048ef2c --- /dev/null +++ b/config/routes/job_order.yaml @@ -0,0 +1,19 @@ +jo_in: + path: /job-order/incoming + controller: App\Controller\JobOrderController::incomingForm + methods: [GET] + +jo_proc: + path: /job-order/processing + controller: App\Controller\JobOrderController::processingForm + methods: [GET] + +jo_in_submit: + path: /job-order/incoming + controller: App\Controller\JobOrderController::incomingSubmit + methods: [POST] + +jo_proc_submit: + path: /job-order/processing + controller: App\Controller\JobOrderController::processingSubmit + methods: [POST] diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 418fae62..1fcf51dd 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -30,6 +30,21 @@ span.has-danger, margin-left: 10px; } +.flex-row.m-form__heading { + align-items: center; + justify-content: flex-start; +} + +.flex-row.m-form__heading label { + margin-bottom: 0; +} + +.flex-row.m-form__heading > * + * { + border-left: 1px solid #EBEDF2; + margin-left: 16px; + padding-left: 16px; +} + .form-group-inner { padding-left: 0 !important; padding-right: 0 !important; @@ -66,6 +81,11 @@ span.has-danger, border-radius: 100%; } +.select2-selection { + font-size: 1rem !important; + font-weight: 300 !important; +} + @media (min-width: 995px) { .modal-lg { max-width: 1024px; diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php index 57b1971e..baec3191 100644 --- a/src/Controller/CustomerController.php +++ b/src/Controller/CustomerController.php @@ -537,6 +537,156 @@ class CustomerController extends BaseController return range($start_year, date("Y") + 1); } + public function getCustomerVehicles(Request $req) + { + if (!$this->isGranted('jo_in.list')) { + $exception = $this->createAccessDeniedException('No access.'); + throw $exception; + } + + // get search term + $term = $req->query->get('search'); + + // get querybuilder + $qb = $this->getDoctrine() + ->getRepository(CustomerVehicle::class) + ->createQueryBuilder('q'); + + // build expression now since we're reusing it + $vehicle_label = $qb->expr()->concat('q.plate_number', $qb->expr()->literal(' - '), 'c.first_name', $qb->expr()->literal(' '), 'c.last_name'); + + // count total records + $tquery = $qb->select('COUNT(q)') + ->join('q.customer', 'c'); + + // add filters to count query + if (!empty($term)) { + $tquery->where($vehicle_label . ' LIKE :filter') + ->setParameter('filter', '%' . $term . '%'); + } + + $total = $tquery->getQuery() + ->getSingleScalarResult(); + + // pagination vars + $page = $req->query->get('page') ?? 1; + $perpage = 20; + $offset = ($page - 1) * $perpage; + $pages = ceil($total / $perpage); + $has_more_pages = $page < $pages ? true : false; + + // build main query + $query = $qb->select('q') + ->addSelect($vehicle_label . ' as vehicle_label') + ->addSelect('c.first_name as cust_first_name') + ->addSelect('c.last_name as cust_last_name'); + + // add filters if needed + if (!empty($term)) { + $query->where($vehicle_label . ' LIKE :filter') + ->setParameter('filter', '%' . $term . '%'); + } + + // get rows + $obj_rows = $query->orderBy('q.plate_number', 'asc') + ->setFirstResult($offset) + ->setMaxResults($perpage) + ->getQuery() + ->getResult(); + + // build vehicles array + $vehicles = []; + + foreach ($obj_rows as $vehicle) { + $vehicles[] = [ + 'id' => $vehicle[0]->getID(), + 'text' => $vehicle['vehicle_label'] + ]; + } + + // response + return $this->json([ + 'success' => true, + 'results' => $vehicles, + 'pagination' => [ + 'more' => $has_more_pages + ] + ]); + } + + public function getCustomerVehicleInfo(Request $req) + { + $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); + + // get id + $id = $req->query->get('id'); + + // get row data + $em = $this->getDoctrine()->getManager(); + $obj = $em->getRepository(CustomerVehicle::class)->find($id); + + // make sure this row exists + if (empty($obj)) { + return $this->json([ + 'success' => false, + 'error' => 'The item does not exist' + ]); + } + + $customer = $obj->getCustomer(); + $vehicle = $obj->getVehicle(); + $battery = $obj->getCurrentBattery(); + + // get all mobile numbers + $mobile_numbers = []; + + foreach ($customer->getMobileNumbers() as $number) { + $mobile_numbers[] = $number->getID(); + } + + // build response + $row = [ + 'customer' => [ + 'id' => $customer->getID(), + 'first_name' => $customer->getFirstName(), + 'last_name' => $customer->getLastName(), + 'mobile_numbers' => $mobile_numbers + ], + 'vehicle' => [ + 'id' => $vehicle->getID(), + 'mfg_name' => $vehicle->getManufacturer()->getName(), + 'make' => $vehicle->getMake(), + 'model_year_from' => $vehicle->getModelYearFrom(), + 'model_year_to' => $vehicle->getModelYearTo(), + 'model_year' => $obj->getModelYear(), + 'color' => $obj->getColor(), + //'plate_number' => $obj->getPlateNumber(), + //'fuel_type' => $obj->getFuelType(), + //'status_condition' => $obj->getStatusCondition(), + ] + ]; + + if (!empty($battery)) { + $row['battery'] = [ + 'id' => $battery->getID(), + 'mfg_name' => $battery->getManufacturer()->getName(), + 'model_name' => $battery->getModel()->getName(), + 'size_name' => $battery->getSize()->getName(), + 'prod_code' => $battery->getProductCode(), + 'warranty_code' => $obj->getWarrantyCode(), + 'warranty_expiration' => $obj->getWarrantyExpiration() ? $obj->getWarrantyExpiration()->format("d M Y") : "", + 'has_motolite_battery' => $obj->hasMotoliteBattery(), + 'is_active' => $obj->isActive() + ]; + } + + // response + return $this->json([ + 'success' => true, + 'data' => $row + ]); + } + // 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'])) { diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php new file mode 100644 index 00000000..5e0e36e5 --- /dev/null +++ b/src/Controller/JobOrderController.php @@ -0,0 +1,75 @@ +acl_gen = $acl_gen; + parent::__construct($menu_gen); + } + + public function incomingForm() + { + $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); + + $params = $this->initParameters('jo_in'); + $params['obj'] = new JobOrder(); + $params['mode'] = 'create'; + + $em = $this->getDoctrine()->getManager(); + + // get parent associations + $params['customers'] = $em->getRepository(Customer::class)->findAll(); + $params['outlet'] = $em->getRepository(Outlet::class)->findAll(); + $params['rider'] = $em->getRepository(Rider::class)->findAll(); + $params['service_types'] = ServiceType::getCollection(); + $params['statuses'] = JOStatus::getCollection(); + + // response + return $this->render('job-order/incoming.html.twig', $params); + } + + public function incomingSubmit(Request $req) + { + $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); + + // create new row + $em = $this->getDoctrine()->getManager(); + $row = new JobOrder(); + + // TODO: Validation, handling of job order + + // DEBUG: Get all variables + error_log(print_r($req->request->all(), true)); + + // DEBUG: Fake error array + $error_array = []; + + // DEBUG: Error response for now + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } +} diff --git a/src/Entity/JobOrder.php b/src/Entity/JobOrder.php index 58166417..c4f3c9c1 100644 --- a/src/Entity/JobOrder.php +++ b/src/Entity/JobOrder.php @@ -113,6 +113,18 @@ class JobOrder */ protected $status; + // delivery instructions + /** + * @ORM\Column(type="text", nullable=true) + */ + protected $delivery_instructions; + + // agent notes + /** + * @ORM\Column(type="text", nullable=true) + */ + protected $agent_notes; + public function __construct() { $this->date_create = new DateTime(); @@ -258,4 +270,37 @@ class JobOrder { return $this->source; } + + public function setStatus($status) + { + $this->status = $status; + return $this; + } + + public function getStatus() + { + return $this->status; + } + + public function setDeliveryInstructions($delivery_instructions) + { + $this->delivery_instructions = $delivery_instructions; + return $this; + } + + public function getDeliveryInstructions() + { + return $this->delivery_instructions; + } + + public function setAgentNotes($agent_notes) + { + $this->agent_notes = $agent_notes; + return $this; + } + + public function getAgentNotes() + { + return $this->agent_notes; + } } diff --git a/templates/job-order/incoming.html.twig b/templates/job-order/incoming.html.twig new file mode 100644 index 00000000..1ac54cc5 --- /dev/null +++ b/templates/job-order/incoming.html.twig @@ -0,0 +1,440 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +