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 @@