Merge branch '182-history-search' into 'master'

Resolve "History search"

Closes #182

See merge request jankstudio/resq!227
This commit is contained in:
Kendrick Chan 2019-03-18 12:46:19 +00:00
commit 66be264ae8
9 changed files with 710 additions and 0 deletions

View file

@ -211,6 +211,8 @@ access_keys:
acls:
- id: support.menu
label: Menu
- id: general.search
label: Search
- id: ticket
label: Ticket Access
acls:

View file

@ -118,3 +118,7 @@ main_menu:
acl: ticket.list
label: Tickets
parent: support
- id: general_search
acl: general.search
label: Search
parent: support

View file

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

View file

@ -0,0 +1,70 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Service\GeneralSearch;
class TestGeneralSearchCommand extends Command
{
protected function configure()
{
$this->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";
}
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace App\Controller;
use App\Ramcar\BaseController;
use App\Service\GeneralSearch;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Menu\Generator as MenuGenerator;
use App\Access\Generator as ACLGenerator;
class SearchController extends BaseController
{
protected $acl_gen;
public function __construct(MenuGenerator $menu_gen, ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
parent::__construct($menu_gen);
}
public function index()
{
$this->denyaccessUnlessGranted('general.search', null, 'No access.');
$params = $this->initParameters('general_search');
// response
return $this->render('search/list.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;
return $this->render('search/results.html.twig', $params);
}
}

View file

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

View file

@ -0,0 +1,68 @@
<?php
namespace App\Service;
use App\Entity\LegacyJobOrder;
use App\Entity\JobOrder;
use App\Entity\Warranty;
use Doctrine\ORM\EntityManagerInterface;
define("SEARCH_MAX_RESULTS", "20");
class GeneralSearch
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->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;
}
}

View file

@ -0,0 +1,60 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- BEGIN: Subheader -->
<div class="m-subheader">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title">
Search
</h3>
</div>
</div>
</div>
<!-- END: Subheader -->
<div class="m-content">
<!--Begin::Section-->
<div class="row">
<div class="col-xl-12">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__body">
<div class="m-form m-form--label-align-right m--margin-top-20 m--margin-bottom-30">
<div class="row align-items-center">
<div class="col-xl-8 order-2 order-xl-1">
<div class="form-group m-form__group row align-items-center">
<div class="col-md-4">
<form action= "{{ url('search_history') }}" method="get" onsubmit="handle">
<div class="m-input-icon m-input-icon--left">
<input type="text" class="form-control m-input m-input--solid" placeholder="Search..." id="data-rows-search" name="search" >
<span class="m-input-icon__icon m-input-icon__icon--left">
<span><i class="la la-search"></i></span>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!--begin: Datatable -->
<div id="data-rows">
</div>
<!--end: Datatable -->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function handle(e)
{
e.preventDefault();
}
</script>
{% endblock %}

View file

@ -0,0 +1,113 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- BEGIN: Subheader -->
<div class="m-subheader">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title">
Search
</h3>
</div>
</div>
</div>
<!-- END: Subheader -->
<div class="m-content">
<!--Begin::Section-->
<div class="row">
<div class="col-xl-12">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__body">
<div class="m-form m-form--label-align-right m--margin-top-20 m--margin-bottom-30">
<div class="row align-items-center">
<div class="col-xl-8 order-2 order-xl-1">
<div class="form-group m-form__group row align-items-center">
<div class="col-md-4">
<form action= "{{ url('search_history') }}" method="get" onsubmit="handle">
<div class="m-input-icon m-input-icon--left">
<input type="text" class="form-control m-input m-input--solid" placeholder="Search..." id="data-rows-search" name="search" >
<span class="m-input-icon__icon m-input-icon__icon--left">
<span><i class="la la-search"></i></span>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!--begin: Datatable -->
<div id="data-rows">
<p> Legacy Job Orders </p>
<table>
{% if data.legacy_job_orders is empty %}
<td colspan=100> No records for legacy job orders </td>
{% else %}
<th> ID </th>
<th> Last Name </th>
<th> Plate Number </th>
{% for key, result in data.legacy_job_orders %}
<tr>
<td> {{ result.getID }} </td>
<td> {{ result.getCustLastName | default('') }} </td>
<td> {{ result.getCustFirstNamei | default('') }} </td>
<td> {{ result.getPlateNumber | default('') }} </td>
</tr>
{% endfor %}
{% endif %}
</table>
<p> Job Orders </p>
<table>
{% if data.job_orders is empty %}
<td colspan=100> No records for job orders </td>
{% else %}
<th> ID </th>
<th> Last Name </th>
<th> Plate Number </th>
{% for result in data.job_orders %}
<tr>
<td> {{ result.getID }} </td>
<td> {{ result.getCustomer.getLastName }} </td>
<td> {{ result.getCustomer.getFirstName }}</td>
<td> {{ result.getCustomerVehicle.getPlateNumber }}</td>
</tr>
{% endfor %}
{% endif %}
</table>
<p> Warranties </p>
<table>
{% if data.warranties is empty %}
<td colspan=100> No records for warranties </td>
{% else %}
<th> ID </th>
<th> Last Name </th>
<th> Plate Number </th>
{% for result in data.warranties %}
<tr>
<td> {{ result.getID }} </td>
<td> {{ result.getLastName }} </td>
<td> {{ result.getFirstName }} </td>
<td> {{ result.getPlateNumber }} </td>
</tr>
{% endfor %}
{% endif %}
</table>
</div>
<!--end: Datatable -->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function handle(e)
{
e.preventDefault();
}
</script>
{% endblock %}