diff --git a/catalyst/api-bundle/Command/TestCommand.php b/catalyst/api-bundle/Command/TestCommand.php index 03d1fe85..3d03ae0d 100644 --- a/catalyst/api-bundle/Command/TestCommand.php +++ b/catalyst/api-bundle/Command/TestCommand.php @@ -75,6 +75,17 @@ class TestCommand extends Command ]; $api->post('/capi/warranties/' . $id . '/claim', $params); + // add battery + $sku = 'WZMB31QT-CPP00-S'; + $brand_id = '4'; + $size_id = '1'; + $params = [ + 'sku' => $sku, + 'brand_id' => $brand_id, + 'size_id' => $size_id, + ]; + $api->post('/capi/batteries', $params); + /* // plate warranty diff --git a/config/acl.yaml b/config/acl.yaml index f8a5febc..6655e53f 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -211,6 +211,8 @@ access_keys: acls: - id: support.menu label: Menu + - id: general.search + label: Search - id: ticket label: Ticket Access acls: @@ -238,3 +240,13 @@ access_keys: label: Update - id: promo.delete label: Delete + + - id: report + label: Reports + acls: + - id: report.menu + label: Menu + - id: report.reject + label: Rejection Report + - id: report.battery.conflict + label: Battery Conflict Report diff --git a/config/menu.yaml b/config/menu.yaml index 9da352f9..fd870fea 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -118,3 +118,7 @@ main_menu: acl: ticket.list label: Tickets parent: support + - id: general_search + acl: general.search + label: Search + parent: support diff --git a/config/routes/warranty_api.yaml b/config/routes/capi.yaml similarity index 94% rename from config/routes/warranty_api.yaml rename to config/routes/capi.yaml index 85075440..a340041c 100644 --- a/config/routes/warranty_api.yaml +++ b/config/routes/capi.yaml @@ -30,6 +30,12 @@ capi_battery_sizes: controller: App\Controller\CAPI\BatteryController::getSizes methods: [GET] +# add battery +capi_battery_add: + path: /capi/batteries + controller: App\Controller\CAPI\BatteryController::addBattery + methods: [POST] + # vehicle api diff --git a/config/routes/report.yaml b/config/routes/report.yaml new file mode 100644 index 00000000..c8560798 --- /dev/null +++ b/config/routes/report.yaml @@ -0,0 +1,29 @@ +rep_reject_summary_form: + path: /report/rejection_summary + controller: App\Controller\ReportController::rejectSummaryForm + methods: [GET] + +rep_reject_summary_submit: + path: /report/rejection_summary + controller: App\Controller\ReportController::rejectSummarySubmit + methods: [POST] + +rep_reject_detail_form: + path: /report/rejection_detail + controller: App\Controller\ReportController::rejectDetailForm + methods: [GET] + +rep_reject_detail_submit: + path: /report/rejection_detail + controller: App\Controller\ReportController::rejectDetailSubmit + methods: [POST] + +rep_battery_conflict_form: + path: /report/battery_conflict + controller: App\Controller\ReportController::batteryConflictForm + methods: [GET] + +rep_battery_conflict_submit: + path: /report/battery_conflict + controller: App\Controller\ReportController::batteryConflictSubmit + methods: [POST] diff --git a/config/routes/search.yaml b/config/routes/search.yaml new file mode 100644 index 00000000..54bebd51 --- /dev/null +++ b/config/routes/search.yaml @@ -0,0 +1,8 @@ +general_search: + path: /search + controller: App\Controller\SearchController::index + +search_history: + path: /search/history + controller: App\Controller\SearchController::search + methods: [GET] diff --git a/kml/supported_areas.kml b/kml/supported_areas.kml new file mode 100644 index 00000000..aa643fb4 --- /dev/null +++ b/kml/supported_areas.kml @@ -0,0 +1,73 @@ + + + + ResQ Supported Area + + + + + + normal + #poly-000000-1200-77-nodesc-normal + + + highlight + #poly-000000-1200-77-nodesc-highlight + + + + ResQ Supported Area + + Supported Area + #poly-000000-1200-77-nodesc + + + + 1 + + 121.0717128,14.7868868,0 + 121.0222743,14.7895424,0 + 120.9302638,14.6793076,0 + 120.9494899,14.4427135,0 + 121.0250209,14.3735484,0 + 121.0744593,14.5171749,0 + 121.1513636,14.5357864,0 + 121.1884425,14.5809791,0 + 121.2021754,14.6248337,0 + 121.1321376,14.6540653,0 + 121.129391,14.7616569,0 + 121.0717128,14.7868868,0 + + + + + + + + diff --git a/public/assets/css/style.css b/public/assets/css/style.css index ef00d1b7..f8e6318d 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -196,8 +196,102 @@ span.has-danger, top: -0.45rem; } +.input-group .form-control:first-child:not(:last-child):not(:focus):not(.focus) { + border-right: 0; +} + +.input-group .input-group-append + .form-control:not(:focus):not(.focus) { + border-left: 0; +} + +.input-group > .form-control:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .form-control:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group .input-group-append > .input-group-text { + border-color: #ebedf2; + background-color: #f4f5f8; + color: #575962; +} + +.input-group > .input-group-append > .input-group-text { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .input-group-append:not(:last-child) > .input-group-text { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group-text { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: .85rem 1.15rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.25; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: .25rem; +} + +.input-daterange input:last-child { + border-radius: 0 3px 3px 0; +} + +.input-group { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + width: 100%; +} + +.input-daterange { + width: 100%; +} + @media (min-width: 995px) { .modal-lg { max-width: 1024px; } } + +.input-group-append { + margin-left: -1px; +} + +.input-group-prepend, .input-group-append { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.input-group>.input-group-append>.btn, .input-group>.input-group-append>.input-group-text, .input-group>.input-group-prepend:not(:first-child)>.btn, .input-group>.input-group-prepend:not(:first-child)>.input-group-text, .input-group>.input-group-prepend:first-child>.btn:not(:first-child), .input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-icon { + margin-right: .5em; +} diff --git a/src/Command/AdjustLongLatCommand.php b/src/Command/AdjustLongLatCommand.php new file mode 100644 index 00000000..b7e26ad1 --- /dev/null +++ b/src/Command/AdjustLongLatCommand.php @@ -0,0 +1,50 @@ +em = $om; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('joborder:adjust_longlat') + ->setDescription('Separate longitude and latitude from coordinate point.') + ->setHelp('Get longitude and latitude from existing point type coordinate. Separate into individual fields for reports purposes.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + // get entity manager + $em = $this->em; + + $job_orders = $em->getRepository(JobOrder::class)->findAll(); + + // fulfill each + foreach ($job_orders as $jo) + { + $point = $jo->getCoordinates(); + $jo->setCoordinates($point); + } + + $em->flush(); + } +} diff --git a/src/Command/ImportKMLFileCommand.php b/src/Command/ImportKMLFileCommand.php new file mode 100644 index 00000000..4d2e71a2 --- /dev/null +++ b/src/Command/ImportKMLFileCommand.php @@ -0,0 +1,39 @@ +setName('supportedarea:import') + ->setDescription('Extracts map data of the supported area from the KML file and saves to database') + ->setHelp('Gets the coordinates of the supported area and saves to the database') + ->addArgument('file', InputArgument::REQUIRED, 'Path to the KML file'); + } + + public function __construct(KMLFileImporter $importer) + { + $this->importer = $importer; + + parent::__construct(); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $kml_file = $input->getArgument('file'); + + $this->importer->getMapData($kml_file); + } +} diff --git a/src/Command/ImportLegacyJobOrderCommand.php b/src/Command/ImportLegacyJobOrderCommand.php index 8161fbae..7546880b 100644 --- a/src/Command/ImportLegacyJobOrderCommand.php +++ b/src/Command/ImportLegacyJobOrderCommand.php @@ -10,6 +10,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Doctrine\Common\Persistence\ObjectManager; use App\Entity\Warranty; +use App\Entity\Battery; use App\Entity\BatterySize; use App\Entity\BatteryModel; use App\Entity\VehicleManufacturer; @@ -31,6 +32,7 @@ use DateTime; class ImportLegacyJobOrderCommand extends Command { protected $em; + protected $batt_hash; protected $bmodel_hash; protected $bsize_hash; protected $vmfg_hash; @@ -50,6 +52,7 @@ class ImportLegacyJobOrderCommand extends Command $this->loadBatterySizes(); $this->loadVehicleManufacturers(); $this->loadVehicles(); + $this->loadBatteries(); $this->jo_hash = []; @@ -312,7 +315,7 @@ class ImportLegacyJobOrderCommand extends Command continue; // check if battery is found - $found_battery = $this->findBattery($fields[92], $batt_model, $batt_size); + $found_battery = $this->findBattery($fields[92], $batt_model, $batt_size, $sap_code); if (!$found_battery) { // $output->writeln('battery not found - ' . $fields[92]); @@ -399,7 +402,33 @@ class ImportLegacyJobOrderCommand extends Command $line .= '\N,'; // date claim - $line .= '\N'; + $line .= '\N,'; + + // claim id + $line .= '\N,'; + + // sap battery id + if (isset($sap_code)) + $line .= $sap_code . ','; + else + $line .= '\N,'; + // first name + if (isset($fields[20]) && strlen(trim($fields[20])) > 0) + $line .= $fields[20] . ','; + else + $line .= '\N,'; + + // last name + if (isset($fields[22]) && strlen(trim($fields[22])) > 0) + $line .= $fields[22] . ','; + else + $line .= '\N,'; + + // mobile number + if (isset($fields[24]) && strlen(trim($fields[24])) > 0) + $line .= $fields[24] . ','; + else + $line .= '\N'; fwrite($warr_outfile, $line . "\n"); } @@ -769,6 +798,25 @@ class ImportLegacyJobOrderCommand extends Command } } + protected function loadBatteries() + { + $this->batt_hash = []; + + $batts = $this->em->getRepository(Battery::class)->findAll(); + foreach ($batts as $batt) + { + if (($batt->getModel() == null) or ($batt->getSize() == null) or ($batt->getSAPCode() == null)) + { + continue; + } + + $model_id = $batt->getModel()->getID(); + $size_id = $batt->getSize()->getID(); + + $this->batt_hash[$model_id][$size_id] = $batt->getSAPCode(); + } + } + protected function loadVehicleManufacturers() { $this->vmfg_hash = []; @@ -817,16 +865,16 @@ class ImportLegacyJobOrderCommand extends Command return $clean_text; } - protected function findBattery($batt_field, &$batt_model, &$batt_size) - { - // split battery into model and size - // echo "trying match - " . $fields[92] . "\n"; - $res = preg_match("/^(.+)(GOLD|EXCEL|ENDURO|\(Trade-In\))/", $batt_field, $matches); - if (!$res) - { - // echo "no match - " . $fields[92] . "\n"; + protected function findBattery($batt_field, &$batt_model, &$batt_size, &$sap_code) + { + // split battery into model and size + // echo "trying match - " . $batt_field . "\n"; + $res = preg_match("/^(.+)(GOLD|EXCEL|ENDURO|\(Trade-In\))/", $batt_field, $matches); + if (!$res) + { + //echo "no match - " . $fields[92] . "\n"; return false; - } + } if ($matches[2] == '(Trade-In)') return false; @@ -836,29 +884,35 @@ class ImportLegacyJobOrderCommand extends Command // TODO: what to do about (Trade-In) - // check if we have the size - $found_size = $this->simplifyName($matches[1]); - if (!isset($this->bsize_hash[$found_size])) - { - // try legacy battery lookup - $legacy_size = LegacyBattery::translate($found_size); - if ($legacy_size == null) - { - // echo "no size - $found_size\n"; - if (isset($no_sizes[$found_size])) - $no_sizes[$found_size]++; - else - $no_sizes[$found_size] = 1; - return false; - } + // check if we have the size + $found_size = $this->simplifyName($matches[1]); + if (!isset($this->bsize_hash[$found_size])) + { + // try legacy battery lookup + $legacy_size = LegacyBattery::translate($found_size); + if ($legacy_size == null) + { + // echo "no size - $found_size\n"; + if (isset($no_sizes[$found_size])) + $no_sizes[$found_size]++; + else + $no_sizes[$found_size] = 1; + return false; + } - $found_size = $legacy_size; - } + $found_size = $legacy_size; + } $batt_size = $this->bsize_hash[$found_size]; // $batt_size = $found_size; + //get battery using ids of batt_model and batt_size + if (!isset($this->batt_hash[$batt_model][$batt_size])) + return false; + + $sap_code = $this->batt_hash[$batt_model][$batt_size]; + return true; - } + } protected function findVehicle($vmfg_field, $vmake_field, $vmodel_field, &$vehicle) { diff --git a/src/Command/TestGeneralSearchCommand.php b/src/Command/TestGeneralSearchCommand.php new file mode 100644 index 00000000..0696fb86 --- /dev/null +++ b/src/Command/TestGeneralSearchCommand.php @@ -0,0 +1,70 @@ +setName('test:generalsearch') + ->setDescription('Test general search service.') + ->setHelp('Test the general search service.') + ->addArgument('search_term', InputArgument::REQUIRED, 'Search Terms'); + } + + public function __construct(GeneralSearch $search) + { + $this->search = $search; + + parent::__construct(); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $search_term = $input->getArgument('search_term'); + + $results = $this->search->search($search_term); + + echo "legacy job order results: " . count($results['legacy_job_orders']) . "\n"; + + foreach($results['legacy_job_orders'] as $legacy_job_order) + { + echo "Plate Number: " . $legacy_job_order->getPlateNumber() . "\n"; + echo "Mobile Number: " . $legacy_job_order->getCustMobile() . "\n"; + echo "Landline: " . $legacy_job_order->getCustLandline() . "\n"; + echo "Name: " . $legacy_job_order->getCustName() . "\n"; + echo "Last Name: " . $legacy_job_order->getCustLastName() . "\n"; + echo "First Name: " . $legacy_job_order->getCustFirstName() . "\n"; + echo "Middle Name: " . $legacy_job_order->getCustMiddleName() . "\n"; + } + + echo "job order results: " . count($results['job_orders']) . "\n"; + foreach($results['job_orders'] as $job_order) + { + echo "Plate Number: " . $job_order->getCustomerVehicle()->getPlateNumber() . "\n"; + echo "Mobile Number: " . $job_order->getCustomer()->getPhoneMobile() . "\n"; + echo "Landline: " . $job_order->getCustomer()->getPhoneLandline() . "\n"; + echo "Office: " . $job_order->getCustomer()->getPhoneOffice() . "\n"; + echo "Fax: " . $job_order->getCustomer()->getPhoneFax() . "\n"; + echo "Last Name: " . $job_order->getCustomer()->getLastName() . "\n"; + echo "First Name: " . $job_order->getCustomer()->getFirstName() . "\n"; + } + + echo "warranties results: " . count($results['warranties']) . "\n"; + + foreach($results['warranties'] as $warranty) + { + echo "Plate Number: " . $warranty->getPlateNumber() . "\n"; + echo "Mobile Number: " . $warranty->getMobileNumber() . "\n"; + echo "Last Name: " . $warranty->getLastName() . "\n"; + echo "First Name: " . $warranty->getFirstName() . "\n"; + } + } +} diff --git a/src/Command/TestGeofenceCommand.php b/src/Command/TestGeofenceCommand.php new file mode 100644 index 00000000..1397f08f --- /dev/null +++ b/src/Command/TestGeofenceCommand.php @@ -0,0 +1,44 @@ +setName('test:geofence') + ->setDescription('Test geofence tracker service.') + ->setHelp('Test the geofence tracker service.') + ->addArgument('long', InputArgument::REQUIRED, 'Longitude') + ->addArgument('lat', InputArgument::REQUIRED, 'Latitude'); + } + + public function __construct(GeofenceTracker $geo) + { + $this->geo = $geo; + + parent::__construct(); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $long = $input->getArgument('long'); + $lat = $input->getArgument('lat'); + + if ($this->geo->isCovered($long, $lat)) + echo "In geofence\n"; + else + echo "NOT in geofence\n"; + } +} diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index d5fa3b3a..4925cf9b 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -25,6 +25,7 @@ use App\Ramcar\JOEventType; use App\Service\InvoiceCreator; use App\Service\RisingTideGateway; use App\Service\MQTTClient; +use App\Service\GeofenceTracker; use App\Entity\MobileSession; use App\Entity\Customer; @@ -766,7 +767,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function requestJobOrder(Request $req, InvoiceCreator $ic) + public function requestJobOrder(Request $req, InvoiceCreator $ic, GeofenceTracker $geo) { // check required parameters and api key $required_params = [ @@ -793,6 +794,20 @@ class APIController extends Controller // instructions $instructions = $req->request->get('delivery_instructions', ''); + // longitude and latitude + $long = $req->request->get('long'); + $lat = $req->request->get('lat'); + + // geofence + $is_covered = $geo->isCovered($long, $lat); + if (!$is_covered) + { + // TODO: put geofence error message in config file somewhere + $res->setError(true) + ->setErrorMessage('Oops! Our service is limited to Metro Manila only. We will update you as soon as we are able to cover your area'); + return $res->getReturnResponse(); + } + $jo = new JobOrder(); $jo->setSource(TransactionOrigin::MOBILE_APP) @@ -836,9 +851,7 @@ class APIController extends Controller } $jo->setWarrantyClass($warr); - // longitude and latitude - $long = $req->request->get('long'); - $lat = $req->request->get('lat'); + // set coordinates $point = new Point($long, $lat); $jo->setCoordinates($point); diff --git a/src/Controller/BatteryController.php b/src/Controller/BatteryController.php index 317f0f43..48e1dde4 100644 --- a/src/Controller/BatteryController.php +++ b/src/Controller/BatteryController.php @@ -119,6 +119,7 @@ class BatteryController extends BaseController $row['sell_price'] = $orow[0]->getSellingPrice(); $row['warr_private'] = $orow[0]->getWarrantyPrivate(); $row['warr_commercial'] = $orow[0]->getWarrantyCommercial(); + $row['warr_tnv'] = $orow[0]->getWarrantyTnv(); $row['res_capacity'] = $orow[0]->getReserveCapacity(); $row['length'] = $orow[0]->getLength(); $row['width'] = $orow[0]->getWidth(); @@ -181,6 +182,7 @@ class BatteryController extends BaseController ->setSAPCode($req->request->get('sap_code')) ->setWarrantyPrivate($req->request->get('warr_private')) ->setWarrantyCommercial($req->request->get('warr_commercial')) + ->setWarrantyTnv($req->request->get('warr_tnv')) ->setReserveCapacity($req->request->get('res_capacity')) ->setLength($req->request->get('length')) ->setWidth($req->request->get('width')) @@ -303,6 +305,7 @@ class BatteryController extends BaseController ->setSAPCode($req->request->get('sap_code')) ->setWarrantyPrivate($req->request->get('warr_private')) ->setWarrantyCommercial($req->request->get('warr_commercial')) + ->setWarrantyTnv($req->request->get('warr_tnv')) ->setReserveCapacity($req->request->get('res_capacity')) ->setLength($req->request->get('length')) ->setWidth($req->request->get('width')) diff --git a/src/Controller/CAPI/BatteryController.php b/src/Controller/CAPI/BatteryController.php index a8197bab..ec0d65d9 100644 --- a/src/Controller/CAPI/BatteryController.php +++ b/src/Controller/CAPI/BatteryController.php @@ -75,4 +75,72 @@ class BatteryController extends APIController return new APIResponse(true, 'Battery sizes loaded.', $data); } + + public function addBattery(Request $req, EntityManagerInterface $em) + { + // required parameters + $params = [ + 'sku', + 'brand_id', + 'size_id', + ]; + + $msg = $this->checkRequiredParameters($req, $params); + error_log('msg - ' . $msg); + if ($msg) + return new APIResponse(false, $msg); + + $sku = $req->request->get('sku'); + $brand_id = $req->request->get('brand_id'); + $size_id = $req->request->get('size_id'); + + // check if sku already exists + $batt = $em->getRepository(SAPBattery::class)->find($sku); + if ($batt != null) + return new APIResponse(false, 'Battery SKU already exists.'); + + // check if brand exists + $batt_brand = $em->getRepository(SAPBatteryBrand::class)->find($brand_id); + if ($batt_brand == null) + return new APIResponse(false, 'Invalid brand.'); + + // check if size exists + $batt_size = $em->getRepository(SAPBatterySize::class)->find($size_id); + if ($batt_size == null) + return new APIResponse(false, 'Invalid size.'); + + + $new_batt = new SAPBattery(); + $new_batt->setID($sku) + ->setBrand($batt_brand) + ->setSize($batt_size); + + try + { + $em->persist($new_batt); + $em->flush(); + } + catch (UniqueConstraintViolationException $e) + { + return new APIResponse(false, 'Battery SKU already exists.'); + } + + // return the new battery data + $data = [ + 'battery' => $this->generateBatteryData($new_batt), + ]; + + return new APIResponse(true, 'Battery added.', $data); + } + + protected function generateBatteryData(SAPBattery $batt) + { + $data = [ + 'sku' => $batt->getID(), + 'brand' => $batt->getBrand()->getID(), + 'size' => $batt->getSize()->getID(), + ]; + + return $data; + } } diff --git a/src/Controller/CAPI/WarrantyController.php b/src/Controller/CAPI/WarrantyController.php index 3f4433a5..5080f541 100644 --- a/src/Controller/CAPI/WarrantyController.php +++ b/src/Controller/CAPI/WarrantyController.php @@ -97,7 +97,7 @@ class WarrantyController extends APIController $query = $qb->select('w') ->from('App\\Entity\\Warranty', 'w') - ->orderBy('w.serial', $order) + ->orderBy('w.date_create', $order) ->setFirstResult($start) ->setMaxResults($max) ->getQuery(); diff --git a/src/Controller/ReportController.php b/src/Controller/ReportController.php new file mode 100644 index 00000000..800474d7 --- /dev/null +++ b/src/Controller/ReportController.php @@ -0,0 +1,401 @@ +denyAccessUnlessGranted('report.reject', null, 'No access.'); + + $params = $this->initParameters('outlet_list'); + + return $this->render('report/rejection/summary_form.html.twig', $params); + } + + public function rejectSummarySubmit(Request $req) + { + $this->denyAccessUnlessGranted('report.reject', null, 'No access.'); + + // get query builder + $qb = $this->getDoctrine() + ->getRepository(JORejection::class) + ->createQueryBuilder('r'); + + // get dates + $raw_date_start = $req->request->get('date_start'); + $raw_date_end = $req->request->get('date_end'); + + $date_start = DateTime::createFromFormat('m/d/Y', $raw_date_start); + $date_end = DateTime::createFromFormat('m/d/Y', $raw_date_end); + + // build query + $query = $qb->where('r.date_create >= :start') + ->andWhere('r.date_create <= :end') + ->setParameter('start', $date_start->format('Y-m-d') . ' 00:00:00') + ->setParameter('end', $date_end->format('Y-m-d') . ' 23:59:59') + ->getQuery(); + + + // run query + $jors = $query->getResult(); + + // initialize counter + $counter = []; + + // get results + $res = []; + foreach ($jors as $jor) + { + $jo = $jor->getJobOrder(); + $hub = $jor->getHub(); + $hub_id = $hub->getID(); + $hub_name = $hub->getName() . ' - ' . $hub->getBranch(); + + $reason = $jor->getReason(); + + if (!isset($counter[$hub_id])) + $counter[$hub_id] = [ + 'reasons' => [], + 'name' => $hub_name, + ]; + + if (!isset($counter[$hub_id][$reason])) + { + $counter[$hub_id]['reasons'][$reason]['name'] = JORejectionReason::getName($reason); + $counter[$hub_id]['reasons'][$reason]['counter'] = 1; + } + else + { + $counter[$hub_id]['reasons'][$reason]['counter'] += 1; + } + + $res[] = [ + 'jo_id' => $jo->getID(), + 'jo_date_time' => $jo->getDateSchedule(), + 'jor_date_create' => $jo->getDateCreate(), + 'hub' => $hub->getName() . ' - ' . $hub->getBranch(), + 'reason' => JORejectionReason::getName($jor->getReason()), + 'contact' => $jor->getContactPerson(), + 'remarks' => $jor->getRemarks(), + ]; + } + + + // response + $resp = new StreamedResponse(); + $resp->setCallback(function() use ($counter) { + // csv output + $csv_handle = fopen('php://output', 'w+'); + fputcsv($csv_handle, ['Enrollee', 'Reason', 'Count']); + foreach ($counter as $centry) + { + $first = true; + foreach ($centry['reasons'] as $creason) + { + // first line has hub name + if ($first) + { + fputcsv($csv_handle, [ + $centry['name'], + $creason['name'], + $creason['counter'], + ]); + $first = false; + } + else + { + fputcsv($csv_handle, [ + '', + $creason['name'], + $creason['counter'], + ]); + } + } + } + + fclose($csv_handle); + }); + + $filename = 'reject_' . $date_start->format('Ymd') . '_' . $date_end->format('Ymd') . '.csv'; + + $resp->setStatusCode(200); + $resp->headers->set('Content-Type', 'text/csv; charset=utf-8'); + $resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); + + return $resp; + /* + return $this->json([ + 'result' => $res, + 'counter' => $counter, + ]); + */ + } + + public function rejectDetailForm() + { + $this->denyAccessUnlessGranted('report.reject', null, 'No access.'); + + $params = $this->initParameters('outlet_list'); + + return $this->render('report/rejection/detail_form.html.twig', $params); + } + + public function rejectDetailSubmit(Request $req) + { + $this->denyAccessUnlessGranted('report.reject', null, 'No access.'); + + // get query builder + $qb = $this->getDoctrine() + ->getRepository(JORejection::class) + ->createQueryBuilder('r'); + + // get dates + $raw_date_start = $req->request->get('date_start'); + $raw_date_end = $req->request->get('date_end'); + + $date_start = DateTime::createFromFormat('m/d/Y', $raw_date_start); + $date_end = DateTime::createFromFormat('m/d/Y', $raw_date_end); + + // build query + $query = $qb->where('r.date_create >= :start') + ->andWhere('r.date_create <= :end') + ->setParameter('start', $date_start->format('Y-m-d') . ' 00:00:00') + ->setParameter('end', $date_end->format('Y-m-d') . ' 23:59:59') + ->getQuery(); + + + // run query + $jors = $query->getResult(); + + // initialize counter + $counter = []; + + // get results + $res = []; + foreach ($jors as $jor) + { + $jo = $jor->getJobOrder(); + $hub = $jor->getHub(); + $hub_id = $hub->getID(); + $hub_name = $hub->getName() . ' - ' . $hub->getBranch(); + + /* + // check if created by app + $create_user = $jo->getCreatedBy(); + if ($create_user == null) + $create_user_text = 'Application'; + else + $create_user_text = $create_user->getFullName(); + */ + + $reason = $jor->getReason(); + + $res[] = [ + $jo->getID(), + $jo->getDateSchedule()->format('m/d/Y H:i'), + $jor->getDateCreate()->format('m/d/Y H:i'), + $hub->getName() . ' - ' . $hub->getBranch(), + JORejectionReason::getName($jor->getReason()), + $jor->getContactPerson(), + $jor->getRemarks(), + $jor->getUser()->getFullName(), + ServiceType::getName($jo->getServiceType()), + ]; + } + + + // response + $resp = new StreamedResponse(); + $resp->setCallback(function() use ($res) { + // csv output + $csv_handle = fopen('php://output', 'w+'); + fputcsv($csv_handle, [ + 'Order #', + 'Order Date and Time', + 'Date and Time Rejected', + 'Enrollee', + 'Reason', + 'Contact Person', + 'Remarks', + 'Dispatched By', + 'Type of Service', + ]); + foreach ($res as $row) + { + fputcsv($csv_handle, $row); + } + + fclose($csv_handle); + }); + + $filename = 'reject_' . $date_start->format('Ymd') . '_' . $date_end->format('Ymd') . '.csv'; + + $resp->setStatusCode(200); + $resp->headers->set('Content-Type', 'text/csv; charset=utf-8'); + $resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); + + return $resp; + /* + return $this->json([ + 'result' => $res, + 'counter' => $counter, + ]); + */ + } + + public function batteryConflictForm() + { + $this->denyAccessUnlessGranted('report.battery.conflict', null, 'No access.'); + + $params = $this->initParameters('outlet_list'); + + return $this->render('report/battery/batt_conflict_form.html.twig', $params); + } + + public function batteryConflictSubmit(Request $req) + { + $this->denyAccessUnlessGranted('report.battery.conflict', null, 'No access.'); + + // get job order query builder + $job_qb = $this->getDoctrine() + ->getRepository(JobOrder::class) + ->createQueryBuilder('jo'); + + $em = $this->getDoctrine()->getManager(); + + // get dates + $raw_date_start = $req->request->get('date_start'); + $raw_date_end = $req->request->get('date_end'); + + $date_start = DateTime::createFromFormat('m/d/Y', $raw_date_start); + $date_end = DateTime::createFromFormat('m/d/Y', $raw_date_end); + + // build query for job order + $jo_query = $job_qb->where('jo.date_create >= :start') + ->andWhere('jo.date_create <= :end') + ->andWhere('jo.status != :status') + ->setParameter('start', $date_start->format('Y-m-d') . ' 00:00:00') + ->setParameter('end', $date_end->format('Y-m-d') . ' 23:59:59') + ->setParameter('status', JOStatus::CANCELLED) + ->getQuery(); + + + // run queries + $jos = $jo_query->getResult(); + + $batteries = $em->getRepository(Battery::class)->findAll(); + + // create compatibility matrix for battery and vehicle + $comp_matrix = []; + foreach ($batteries as $batt) + { + $vehicles = $batt->getVehicles(); + foreach ($vehicles as $vehicle) + { + $comp_matrix[$batt->getID()][$vehicle->getID()] = true; + } + } + + // go through the job orders to find the conflicts + $results = []; + foreach ($jos as $jo) + { + $invoice_items = $jo->getInvoice()->getItems(); + foreach ($invoice_items as $item) + { + // check if the item is a battery + if ($item->getBattery() != null) + { + $batt_id = $item->getBattery()->getID(); + $vehicle_id = $jo->getCustomerVehicle()->getVehicle()->getID(); + if (isset($comp_matrix[$batt_id][$vehicle_id]) && $comp_matrix[$batt_id][$vehicle_id]) + { + continue; + } + else + { + // get the compatible batteries for the customer vehicle + $batteries = []; + foreach($jo->getCustomerVehicle()->getVehicle()->getBatteries() as $comp_batt) + { + //$batteries[] = [ + // 'mfg_name' => $comp_batt->getManufacturer()->getName(), + // 'model_name' => $comp_batt->getModel()->getName(), + // 'size_name' => $comp_batt->getSize()->getName(), + //]; + $batteries[] = $comp_batt->getManufacturer()->getName() . ' ' . + $comp_batt->getModel()->getName() . ' ' . + $comp_batt->getSize()->getName(); + } + + $results[] = [ + 'jo_id' => $jo->getID(), + 'jo_date_create' => $jo->getDateCreate()->format('m/d/Y H:i'), + 'cus_vehicle_manufacturer' => $jo->getCustomerVehicle()->getVehicle()->getManufacturer()->getName(), + 'cus_vehicle_make' => $jo->getCustomerVehicle()->getVehicle()->getMake(), + 'cus_vehicle_model' => $jo->getCustomerVehicle()->getModelYear(), + 'battery_model_ordered' => $item->getBattery()->getModel()->getName(), + 'battery_size_ordered' => $item->getBattery()->getSize()->getName(), + 'compatible_batt' => implode(', ', $batteries), + ]; + } + } + } + } + + $resp = new StreamedResponse(); + $resp->setCallback(function() use ($results) { + // csv output + $csv_handle = fopen('php://output', 'w+'); + fputcsv($csv_handle, [ + 'Order #', + 'Order Date and Time', + 'Manufacturer', + 'Make', + 'Year', + 'Battery Model', + 'Battery Size', + 'Compatible Batteries' + ]); + foreach ($results as $row) + { + fputcsv($csv_handle, $row); + } + + fclose($csv_handle); + }); + + $filename = 'battery_conflict_' . $date_start->format('Ymd') . '_' . $date_end->format('Ymd') . '.csv'; + + $resp->setStatusCode(200); + $resp->headers->set('Content-Type', 'text/csv; charset=utf-8'); + $resp->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); + + return $resp; + + //return $this->json([ + // 'result' => $results, + //]); + } +} diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php new file mode 100644 index 00000000..1e660e16 --- /dev/null +++ b/src/Controller/SearchController.php @@ -0,0 +1,49 @@ +acl_gen = $acl_gen; + parent::__construct($menu_gen); + } + + public function index() + { + $this->denyaccessUnlessGranted('general.search', null, 'No access.'); + $params = $this->initParameters('general_search'); + $params["mode"] = "form"; + + // response + return $this->render('search/form.html.twig', $params); + } + + public function search(Request $req, GeneralSearch $search) + { + $this->denyAccessUnlessGranted('general.search', null, 'No access.'); + $params = $this->initParameters('general_search'); + + $search_term = $req->query->get('search'); + $results = $search->search($search_term); + + $params['data'] = $results; + $params['search_term'] = $search_term; + $params['mode'] = "results"; + + // response + return $this->render('search/form.html.twig', $params); + } +} diff --git a/src/Entity/Battery.php b/src/Entity/Battery.php index ed0c99ec..e05bff81 100644 --- a/src/Entity/Battery.php +++ b/src/Entity/Battery.php @@ -85,6 +85,13 @@ class Battery */ protected $warr_commercial; + // warranty tnv + /** + * @ORM\Column(type="smallint") + * @Assert\NotBlank() + */ + protected $warr_tnv; + // reserve capacity /** * @ORM\Column(type="smallint") @@ -248,6 +255,17 @@ class Battery return $this->warr_commercial; } + public function setWarrantyTnv($warr_tnv) + { + $this->warr_tnv = $warr_tnv; + return $this; + } + + public function getWarrantyTnv() + { + return $this->warr_tnv; + } + public function setReserveCapacity($res_capacity) { $this->res_capacity = $res_capacity; diff --git a/src/Entity/JobOrder.php b/src/Entity/JobOrder.php index 346319dd..36834cc1 100644 --- a/src/Entity/JobOrder.php +++ b/src/Entity/JobOrder.php @@ -64,6 +64,18 @@ class JobOrder */ protected $coordinates; + // we split up coordinates into long / lat for reports purposes + /** + * @ORM\Column(type="decimal", precision=11, scale=8) + */ + protected $coord_long; + + // we split up coordinates into long / lat for reports purposes + /** + * @ORM\Column(type="decimal", precision=11, scale=8) + */ + protected $coord_lat; + // is it an advanced order (future date) /** * @ORM\Column(type="boolean") @@ -350,6 +362,9 @@ class JobOrder public function setCoordinates(Point $point) { $this->coordinates = $point; + + $this->coord_lat = $point->getLatitude(); + $this->coord_long = $point->getLongitude(); return $this; } diff --git a/src/Entity/LegacyJobOrder.php b/src/Entity/LegacyJobOrder.php index 345fc724..fde4d7ff 100644 --- a/src/Entity/LegacyJobOrder.php +++ b/src/Entity/LegacyJobOrder.php @@ -355,4 +355,345 @@ class LegacyJobOrder { return $this->id; } + + public function setTransDate($trans_date) + { + $this->id = $trans_date; + return $this; + } + + public function getTransDate() + { + return $this->trans_date; + } + + public function setTransType($trans_type) + { + $this->trans_type = $trans_type; + return $this; + } + + public function getTransType() + { + return $this->trans_type; + } + + public function setOrigin($origin) + { + $this->origin = $origin; + return $this; + } + + public function getOrigin() + { + return $this->origin; + } + + public function setCarBrand($car_brand) + { + $this->car_brand = $car_brand; + return $this; + } + + public function getCarBrand() + { + return $this->car_brand; + } + + public function setCarMake($car_make) + { + $this->car_make = $car_make; + return $this; + } + + public function getCarMake() + { + return $this->car_make; + } + + public function setCarModel($car_model) + { + $this->car_model = $car_model; + return $this; + } + + public function getCarModel() + { + return $this->car_model; + } + + public function setCarColor($car_color) + { + $this->car_color = $car_color; + return $this; + } + + public function getCarColor() + { + return $this->car_color; + } + + public function setCustName($cust_name) + { + $this->cust_name = $cust_name; + return $this; + } + + public function getCustName() + { + return $this->cust_name; + } + + public function setCustFirstName($cust_first_name) + { + $this->cust_first_name = $cust_first_name; + return $this; + } + + public function getCustFirstName() + { + return $this->cust_first_name; + } + + public function setCustMiddleName($cust_middle_name) + { + $this->cust_middle_name = $cust_middle_name; + return $this; + } + + public function getCustMiddleName() + { + return $this->cust_middle_name; + } + + public function setCustLastName($cust_last_name) + { + $this->cust_last_name = $cust_last_name; + return $this; + } + + public function getCustLastName() + { + return $this->cust_last_name; + } + + public function setCustContact($cust_contact) + { + $this->cust_contact = $cust_contact; + return $this; + } + + public function getCustContact() + { + return $this->cust_contact; + } + + public function setCustMobile($cust_mobile) + { + $this->cust_mobile = $cust_mobile; + return $this; + } + + public function getCustMobile() + { + return $this->cust_mobile; + } + + public function setCustLandline($cust_landline) + { + $this->cust_landline = $cust_landline; + return $this; + } + + public function getCustLandline() + { + return $this->cust_landline; + } + + public function setDeliveryInstructions($delivery_instructions) + { + $this->delivery_instructions = $delivery_instructions; + return $this; + } + + public function getDeliveryInstructions() + { + return $this->delivery_instructions; + } + + public function setAgentNotes1($agent_notes_1) + { + $this->agent_notes_1 = $agent_notes_1; + return $this; + } + + public function getAgentNotes1() + { + return $this->agent_notes_1; + } + + public function setDeliveryDate($delivery_date) + { + $this->delivery_date = $delivery_date; + return $this; + } + + public function getDeliveryDate() + { + return $this->delivery_date; + } + + public function setDeliveryTime($delivery_time) + { + $this->delivery_time = $delivery_time; + return $this; + } + + public function getDeliveryTime() + { + return $this->delivery_time; + } + + public function setAdvanceOrder($advance_order) + { + $this->advance_order = $advance_order; + return $this; + } + + public function getAdvanceOrder() + { + return $this->advance_order; + } + + public function setStage($stage) + { + $this->stage = $stage; + return $this; + } + + public function getStage() + { + return $this->stage; + } + + public function setCancelReason($cancel_reason) + { + $this->cancel_reason = $cancel_reason; + return $this; + } + + public function getCancelReason() + { + return $this->cancel_reason; + } + + public function setCancelReasonSpecify($cancel_reason_specify) + { + $this->cancel_reason_specify = $cancel_reason_specify; + return $this; + } + + public function getCancelReasonSpecify() + { + return $this->cancel_reason_specify; + } + + public function setPaymentMethod($payment_method) + { + $this->payment_method = $payment_method; + return $this; + } + + public function getPaymentMethod() + { + return $this->payment_method; + } + + public function setPreparedBy($prepared_by) + { + $this->prepared_by = $prepared_by; + return $this; + } + + public function getPreparedBy() + { + return $this->prepared_by; + } + + public function setDispatchTime($dispatch_time) + { + $this->dispatch_time = $dispatch_time; + return $this; + } + + public function getDispatchTime() + { + return $this->dispatch_time; + } + + public function setDispatchDate($dispatch_date) + { + $this->dispatch_date = $dispatch_date; + return $this; + } + + public function getDispatchDate() + { + return $this->dispatch_date; + } + + public function setDispatchBy($dispatch_by) + { + $this->dispatch_by = $dispatch_by; + return $this; + } + + public function getDispatchBy() + { + return $this->dispatch_by; + } + + public function setAddress($address) + { + $this->address = $address; + return $this; + } + + public function getAddress() + { + return $this->address; + } + + public function setLandmark($landmark) + { + $this->landmark = $landmark; + return $this; + } + + public function getLandmark() + { + return $this->landmark; + } + + public function setDatePurchase($date_purchase) + { + $this->date_purchase = $date_purchase; + return $this; + } + + public function getDatePurchase() + { + return $this->date_purchase; + } + + public function setPlateNumber($plate_number) + { + $this->plate_number = $plate_number; + return $this; + } + + public function getPlateNumber() + { + return $this->plate_number; + } } diff --git a/src/Entity/SupportedArea.php b/src/Entity/SupportedArea.php new file mode 100644 index 00000000..0f70c39e --- /dev/null +++ b/src/Entity/SupportedArea.php @@ -0,0 +1,86 @@ +date_create = new DateTime(); + } + + public function getID() + { + return $this->id; + } + + public function setDateCreate(DateTime $date_create) + { + $this->date_create = $date_create; + return $this; + } + + public function getDateCreate() + { + return $this->date_Create; + } + + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function getName() + { + return $this->name; + } + + public function setCoverageArea(Polygon $polygon) + { + $this->coverage_area = $polygon; + + return $this; + } + + public function getCoverageArea() + { + return $this->coverage_area; + } +} + diff --git a/src/Ramcar/JORejectionReason.php b/src/Ramcar/JORejectionReason.php index a07042e6..9dee1217 100644 --- a/src/Ramcar/JORejectionReason.php +++ b/src/Ramcar/JORejectionReason.php @@ -12,6 +12,9 @@ class JORejectionReason extends NameValue const NO_RIDER_AVAILABLE = 'no_rider_available'; const NO_RIDER_IN_TRANSIT = 'no_rider_in_transit'; const REFUSAL = 'refusal'; + const STORE_CLOSED = 'store_closed'; + const NO_CREDIT_CARD = 'no_credit_card'; + const DISCOUNT = 'discount'; const COLLECTION = [ 'administrative' => 'ADMINISTRATIVE', @@ -22,5 +25,8 @@ class JORejectionReason extends NameValue 'no_rider_available' => 'NO RIDER - AVAILABLE', 'no_rider_in_transit' => 'NO RIDER - IN TRANSIT', 'refusal' => 'REFUSAL', + 'store_closed' => 'STORE CLOSED', + 'no_credit_card' => 'NO CREDIT CARD PAYMENT / NO TERMINAL', + 'discount' => 'DISCOUNT', ]; } diff --git a/src/Service/GeneralSearch.php b/src/Service/GeneralSearch.php new file mode 100644 index 00000000..5a5b47ed --- /dev/null +++ b/src/Service/GeneralSearch.php @@ -0,0 +1,68 @@ +em = $em; + } + + public function search($search_term) + { + // query legacy job orders for plate number, name (first, middle, last), phone number(mobile, landline) + $legacy_job_orders = $this->em->createQuery('SELECT l FROM App\Entity\LegacyJobOrder l + WHERE l.plate_number LIKE :search_term + OR l.cust_mobile LIKE :search_term + OR l.cust_landline LIKE :search_term + OR l.cust_name LIKE :search_term + OR l.cust_last_name LIKE :search_term + OR l.cust_middle_name LIKE :search_term + OR l.cust_first_name LIKE :search_term + OR l.cust_contact LIKE :search_term') + ->setParameter('search_term', "%" . $search_term . "%") + ->setMaxResults(SEARCH_MAX_RESULTS) + ->getResult(); + + // query current job orders for plate number, name(first, last), phone number(mobile, landline, office, fax) + // join with customervehicle for plate number. join with customer for name and number + $job_orders = $this->em->createQuery('SELECT jo FROM App\Entity\JobOrder jo + JOIN jo.cus_vehicle cv + JOIN jo.customer c + WHERE cv.plate_number LIKE :search_term + OR c.first_name LIKE :search_term + OR c.last_name LIKE :search_term + OR c.phone_mobile LIKE :search_term + OR c.phone_landline LIKE :search_term + OR c.phone_office LIKE :search_term + OR c.phone_fax LIKE :search_term') + ->setParameter('search_term', "%" . $search_term . "%") + ->setMaxResults(SEARCH_MAX_RESULTS) + ->getResult(); + + // query warranty for plate number, name(first, last), phone number(mobile) + $warranties = $this->em->createQuery('SELECT w FROM App\Entity\Warranty w + WHERE w.plate_number LIKE :search_term + OR w.first_name LIKE :search_term + OR w.last_name LIKE :search_term + OR w.mobile_number LIKE :search_term') + ->setParameter('search_term', "%" . $search_term . "%") + ->setMaxResults(SEARCH_MAX_RESULTS) + ->getResult(); + + $results = array('legacy_job_orders'=>$legacy_job_orders, 'job_orders'=>$job_orders, 'warranties'=>$warranties); + + return $results; + } +} diff --git a/src/Service/GeofenceTracker.php b/src/Service/GeofenceTracker.php new file mode 100644 index 00000000..b2052e02 --- /dev/null +++ b/src/Service/GeofenceTracker.php @@ -0,0 +1,35 @@ +em = $em; + } + + public function isCovered($long, $lat) + { + // see if the point is in any of the polygons + $query = $this->em->createQuery('SELECT count(s) from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true') + ->setParameter('long', $long) + ->setParameter('lat', $lat); + + // number of polygons that contain the point + $count = $query->getSingleScalarResult(); + + if ($count > 0) + return true; + + return false; + } +} diff --git a/src/Service/KMLFileImporter.php b/src/Service/KMLFileImporter.php new file mode 100644 index 00000000..60bcfa54 --- /dev/null +++ b/src/Service/KMLFileImporter.php @@ -0,0 +1,82 @@ +em = $em; + } + + public function getMapData($fh) + { + $placemark_name = ''; + + $reader = new XMLReader(); + $reader->open($fh); + + while($reader->read()) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Placemark") + { + while($reader->read()) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "name") + { + $placemark_name = $reader->readInnerXML(); + } + + if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "coordinates") + { + // each polygon is a new area + $supported_area = new SupportedArea(); + $supported_area->setName($placemark_name); + + $point_array = []; + $coordinates = $reader->readInnerXML(); + + // get each line + $coord_split = explode("\n", $coordinates); + + // go through all the coordinates + foreach ($coord_split as $coord) + { + // skip blank lines + $coord_trim = trim($coord); + if (strlen($coord_trim) <= 0) + continue; + + // echo "$coord_trim\n"; + + $point_split = explode(',', $coord_trim); + + $point_array[] = new Point($point_split[0], $point_split[1]); + } + + $area = new Polygon([new LineString($point_array)]); + $supported_area->setCoverageArea($area); + + // add supported area + $this->em->persist($supported_area); + } + } + } + } + $reader->close(); + + $this->em->flush(); + } +} diff --git a/templates/base.html.twig b/templates/base.html.twig index 84dbcbb4..e61acf78 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -103,53 +103,44 @@ + diff --git a/templates/battery/form.html.twig b/templates/battery/form.html.twig index b0e46cbb..53adb693 100644 --- a/templates/battery/form.html.twig +++ b/templates/battery/form.html.twig @@ -157,6 +157,14 @@
In months +
+ + +
+ In months +
diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 4b528cc0..352ba4e4 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -578,7 +578,7 @@
- + +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + + +{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/report/rejection/detail_form.html.twig b/templates/report/rejection/detail_form.html.twig new file mode 100644 index 00000000..2742c9b7 --- /dev/null +++ b/templates/report/rejection/detail_form.html.twig @@ -0,0 +1,82 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Detailed Rejection Report

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +

+ Select a date range +

+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/report/rejection/form.html.twig b/templates/report/rejection/form.html.twig new file mode 100644 index 00000000..c0676019 --- /dev/null +++ b/templates/report/rejection/form.html.twig @@ -0,0 +1,82 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Rejection Report

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +

+ Select a date range +

+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/report/rejection/summary_form.html.twig b/templates/report/rejection/summary_form.html.twig new file mode 100644 index 00000000..d344a5d6 --- /dev/null +++ b/templates/report/rejection/summary_form.html.twig @@ -0,0 +1,82 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Summary Rejection Report

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +

+ Select a date range +

+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/search/form.html.twig b/templates/search/form.html.twig new file mode 100644 index 00000000..1b61334d --- /dev/null +++ b/templates/search/form.html.twig @@ -0,0 +1,215 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

+ {% if mode == 'form' %} + Search + {% else %} + Search results for "{{ search_term }}" + {% endif %} +

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +

+ Enter a search term +

+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + {% if mode == 'results' %} + +
+
+
+
+
+
+

+ Legacy Job Orders +

+
+
+
+
+ {% if data.legacy_job_orders is empty %} + + {% else %} + + + + + + + + + + + {% for key, result in data.legacy_job_orders %} + + + + + + + {% endfor %} + +
IDLast NameFirst NamePlate Number
{{ result.getID|default("") }}{{ result.getCustLastName|default('') }}{{ result.getCustFirstName|default('') }}{{ result.getPlateNumber|default('') }}
+ {% endif %} +
+
+
+
+ + + +
+
+
+
+
+
+

+ Job Orders +

+
+
+
+
+ {% if data.job_orders is empty %} + + {% else %} + + + + + + + + + + + {% for key, result in data.job_orders %} + + + + + + + {% endfor %} + +
IDLast NameFirst NamePlate Number
{{ result.getID|default("") }}{{ result.getCustomer.getLastName|default("") }}{{ result.getCustomer.getFirstName|default("") }}{{ result.getCustomerVehicle.getPlateNumber|default("") }}
+ {% endif %} +
+
+
+
+ + + + +
+
+
+
+
+
+

+ Warranties +

+
+
+
+
+ {% if data.warranties is empty %} + + {% else %} + + + + + + + + + + + {% for key, result in data.warranties %} + + + + + + + {% endfor %} + +
IDLast NameFirst NamePlate Number
{{ result.getID|default("") }}{{ result.getLastName|default("") }}{{ result.getFirstName|default("") }}{{ result.getPlateNumber|default("") }}
+ {% endif %} +
+
+
+
+ + {% endif %} +
+{% endblock %} diff --git a/utils/battery_warranty/set_tnv_warranty.sql b/utils/battery_warranty/set_tnv_warranty.sql new file mode 100644 index 00000000..28f67d82 --- /dev/null +++ b/utils/battery_warranty/set_tnv_warranty.sql @@ -0,0 +1,2 @@ +update battery as batt inner join battery_model as bmodel on batt.model_id = bmodel.id set batt.warr_tnv=12 where bmodel.name='GOLD'; + diff --git a/utils/legacy_load/import_legacy_data.sql b/utils/legacy_load/import_legacy_data.sql new file mode 100644 index 00000000..0f12390e --- /dev/null +++ b/utils/legacy_load/import_legacy_data.sql @@ -0,0 +1,4 @@ +load data local infile '/tmp/plate_numbers.csv' into table plate_number fields terminated by ','; +load data infile '/tmp/legacy_jo_row.csv' into table legacy_job_order_row fields terminated by ',' enclosed by '"' lines terminated by '\n' (job_order_id, item, qty, price, price_level, status, account, enrollee) set id = null; +load data local infile '/tmp/warranty.csv' into table warranty fields terminated by ',' (bty_model_id, bty_size_id, serial, warranty_class, plate_number, status, date_create, date_purchase, date_expire, date_claim, claim_id, sap_bty_id, first_name, last_name, mobile_number) set id = null; +load data infile '/tmp/legacy_jo.csv' into table legacy_job_order fields terminated by '|' (id, trans_date, trans_type, origin, car_brand, car_make, car_model, car_color, cust_name, cust_first_name, cust_middle_name, cust_last_name, cust_contact, cust_mobile, cust_landline, delivery_instructions, agent_notes_1, delivery_date, delivery_time, advance_order, stage, cancel_reason, cancel_reason_specify, payment_method, prepared_by, dispatch_time, dispatch_date, dispatched_by, address, landmark, date_purchase, plate_number);