"CMB - display details in JO" #1310

Merged
korina.cordero merged 8 commits from 432-cmb-display-details-in-jo into 424-cmb-release 2020-07-07 11:39:40 +00:00
5 changed files with 296 additions and 86 deletions

View file

@ -102,10 +102,17 @@ class AnalyticsController extends Controller
*/
public function forecastSubmit(EntityManagerInterface $em, Request $req)
{
$today = new DateTime();
$hub_list = $req->request->get('hub_ids', []);
$distances = $req->request->get('distances', []);
$today = DateTime::createFromFormat('d M Y', $req->request->get('date'));
$month = $today->format('m');
$time_start = $req->request->get('time_from');
$time_end = $req->request->get('time_to');
$date_from = DateTime::createFromFormat('d M Y', $req->request->get('date_from'));
$date_to = DateTime::createFromFormat('d M Y', $req->request->get('date_to'));
// error_log(print_r($hub_list, true));
// $hub_list = [ 6, 4, 36, 7, 8, 126, 127, 18, 12, 9, 60, 10, 21, 135 ];
@ -119,7 +126,7 @@ class AnalyticsController extends Controller
$hub = $em->getRepository(Hub::class)->find($hub_id);
$coords = $hub->getCoordinates();
$hub_data[$hub_id] = $this->generateHubData($em, $hub, $dist, $today, $overlaps);
$hub_data[$hub_id] = $this->generateHubData($em, $hub, $dist, $date_from, $date_to, $time_start, $time_end, $overlaps);
$hub_coverage[] = [
'longitude' => $coords->getLongitude(),
@ -143,8 +150,9 @@ class AnalyticsController extends Controller
foreach ($hub_data as $hub_id => $one_hub)
{
$c_weekday = $one_hub['c_weekday'];
$chart_weekday = $this->generateWeekdayData($c_weekday, $today, $overlaps);
$chart_all_weekdays = $this->generateAllWeekData($c_weekday, $today, $overlaps);
$chart_all_weekdays = $this->generateAllWeekData($c_weekday, $overlaps);
// figure out the rider schedules based on the max hour values
$scheduler_data = $chart_all_weekdays['scheduler_data'];
@ -153,18 +161,16 @@ class AnalyticsController extends Controller
$total_jos = 0;
// run scheduler
// check if 2018 data is available
if (isset($scheduler_data['2018'][$month]))
{
// send 2018 + month data
$sched_res = $this->runScheduler($scheduler_data['2018'][$month]);
// error_log(print_r($scheduler_data, true));
// tally total JOs for the month
foreach ($scheduler_data['2018'][$month] as $sday_data)
foreach ($sday_data as $shour_data)
$total_jos += $shour_data;
}
// run scheduler
$sched_res = $this->runScheduler($scheduler_data);
// tally total JOs for the month
foreach ($scheduler_data as $sday_data)
foreach ($sday_data as $shour_data)
$total_jos += $shour_data;
/*
else
{
$sched_res = [
@ -172,6 +178,10 @@ class AnalyticsController extends Controller
'total_riders' => 0,
];
}
*/
// error_log(print_r($chart_all_weekdays, true));
// agggregate weekday data
$i = 0;
@ -244,7 +254,7 @@ class AnalyticsController extends Controller
// error_log(print_r($args, true));
// error_log('running...' . $sched_script);
error_log('running...' . $sched_script);
$proc = new Process($args);
$proc->run();
@ -253,7 +263,7 @@ class AnalyticsController extends Controller
error_log('SCHEDULER DID NOT RUN PROPERLY');
$res = $proc->getOutput();
// error_log($res);
error_log($res);
// segregate into weekdays
@ -321,17 +331,14 @@ class AnalyticsController extends Controller
return $data;
}
protected function generateHubData($em, $hub, $distance_limit, DateTime $today, &$overlaps)
protected function generateHubData($em, $hub, $distance_limit, DateTime $date_start, DateTime $date_end, $time_start, $time_end, &$overlaps)
{
$date_start = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-01 00:00:00');
$date_end = new DateTime();
// get hub to analyze
// $hub = $em->getRepository(Hub::class)->find($hub_id);
$conn = $em->getConnection();
// get job order data (job orders within coverage area)
$jos = $this->generateJobOrderData($conn, $hub, $distance_limit);
$jos = $this->generateJobOrderData($conn, $hub, $distance_limit, $date_start, $date_end, $time_start, $time_end);
// initialize counters
$c_weekday = [];
@ -360,21 +367,22 @@ class AnalyticsController extends Controller
$c_day[$year][$month][$day]++;
// weekday
if (!isset($c_weekday[$year][$month][$weekday][$hour]))
if (!isset($c_weekday[$weekday][$hour]))
{
$c_weekday[$year][$month][$weekday][$hour]['total'] = 0;
$c_weekday[$year][$month][$weekday][$hour]['count'] = 0;
$c_weekday[$year][$month][$weekday][$hour]['jos'] = [];
$c_weekday[$weekday][$hour]['total'] = 0;
$c_weekday[$weekday][$hour]['count'] = 0;
$c_weekday[$weekday][$hour]['jos'] = [];
}
$c_weekday[$year][$month][$weekday][$hour]['total']++;
$c_weekday[$year][$month][$weekday][$hour]['jos'][$jo_id] = $jo_id;
$c_weekday[$weekday][$hour]['total']++;
$c_weekday[$weekday][$hour]['jos'][$jo_id] = $jo_id;
if (!isset($c_week_count[$year][$month][$week][$weekday][$hour]))
// make a count of number of weeks, so we can take average
if (!isset($c_week_count[$week][$weekday][$hour]))
{
// error_log('week detected - ' . $week);
$c_week_count[$year][$month][$week][$weekday][$hour] = 1;
$c_weekday[$year][$month][$weekday][$hour]['count']++;
$c_week_count[$week][$weekday][$hour] = 1;
$c_weekday[$weekday][$hour]['count']++;
}
// track overlaps (jo that can be handled by more than one hub)
@ -404,19 +412,35 @@ class AnalyticsController extends Controller
return $params;
}
protected function generateJobOrderData($conn, $hub, $distance_limit)
protected function generateJobOrderData($conn, $hub, $distance_limit, DateTime $date_start, DateTime $date_end, $time_start, $time_end)
{
$hub_coord = $hub->getCoordinates();
// create query
// formula to convert to km is 111195 * st_distance
$sql = "select id, round(st_distance(coordinates, Point(:lng, :lat)) * 111195) as dist, date_schedule from job_order where st_distance(coordinates, Point(:lng, :lat)) * 111195 <= :distance_limit and status <> 'cancelled' order by date_schedule asc";
$sql = "select id, round(st_distance(coordinates, Point(:lng, :lat)) * 111195) as dist, date_schedule from job_order where st_distance(coordinates, Point(:lng, :lat)) * 111195 <= :distance_limit and status <> 'cancelled' and date_schedule >= :date_start and date_schedule <= :date_end";
// check if time is specified
if (!empty($time_start))
$sql .= ' and time(date_schedule) >= :time_start';
if (!empty($time_end))
$sql .= ' and time(date_schedule) <= :time_end';
$sql .= " order by date_schedule asc";
$stmt = $conn->prepare($sql);
$stmt->bindValue('lng', $hub_coord->getLongitude());
$stmt->bindValue('lat', $hub_coord->getLatitude());
$stmt->bindValue('distance_limit', $distance_limit);
// $stmt->bindValue('date_start', $date_start->format('Y-m-d H:i:s'));
// $stmt->bindValue('date_end', $date_end->format('Y-m-d H:i:s'));
$stmt->bindValue('date_start', $date_start->format('Y-m-d H:i:s'));
$stmt->bindValue('date_end', $date_end->format('Y-m-d H:i:s'));
if (!empty($time_start))
$stmt->bindValue('time_start', $time_start);
if (!empty($time_end))
$stmt->bindValue('time_end', $time_end);
$stmt->execute();
$jos = $stmt->fetchAll();
@ -461,7 +485,7 @@ class AnalyticsController extends Controller
return $chart_year;
}
protected function generateAllWeekData($all_weekday_data, $today, $overlaps)
protected function generateAllWeekData($all_weekday_data, $overlaps)
{
$data = [];
@ -470,53 +494,56 @@ class AnalyticsController extends Controller
for ($i = 0; $i < 24; $i++)
$hours[] = sprintf('%02d', $i);
$month = $today->format('m');
$year_data = [];
// TODO: substitute this
$year_data = $all_weekday_data;
$scheduler_data = [];
/*
error_log('----------------------------------------------------------------------');
error_log(print_r($all_weekday_data, true));
error_log('----------------------------------------------------------------------');
*/
// gather maximum for each hour
foreach ($this->weekdays as $weekday)
{
foreach ($all_weekday_data as $year => $year_data)
// go through the hours
foreach ($hours as $hour)
{
// go through the hours
foreach ($hours as $hour)
$id = $hour + 0;
if (!isset($data[$id]))
$data[$id] = [
'hour' => $hour,
];
// get hour data
$prefix = $weekday;
if (isset($year_data[$weekday][$hour]))
{
$id = $hour + 0;
if (!isset($data[$id]))
$data[$id] = [
'hour' => $hour,
];
// calculate the rider value for each JO and use that score as basis
$total_rv = $this->calculateTotalRiderValue($year_data[$weekday][$hour]['jos'], $overlaps);
$rv_average = ceil($total_rv / $year_data[$weekday][$hour]['count']);
// get hour data
$year_id = 'y' . $year;
$prefix = $year_id . '_' . $weekday;
if (isset($year_data[$month][$weekday][$hour]))
$data[$id][$prefix] = $year_data[$weekday][$hour]['total'];
$data[$id][$prefix . '_count'] = $year_data[$weekday][$hour]['count'];
$data[$id][$prefix . '_average'] = ceil($year_data[$weekday][$hour]['total'] / $year_data[$weekday][$hour]['count']);
$data[$id][$prefix . '_rv_average'] = $rv_average;
// assign scheduler data
$scheduler_data[$weekday][$hour] = $rv_average;
}
else
{
if (!isset($scheduler_data[$weekday][$hour]))
{
// calculate the rider value for each JO and use that score as basis
$total_rv = $this->calculateTotalRiderValue($year_data[$month][$weekday][$hour]['jos'], $overlaps);
$rv_average = ceil($total_rv / $year_data[$month][$weekday][$hour]['count']);
$data[$id][$prefix] = $year_data[$month][$weekday][$hour]['total'];
$data[$id][$prefix . '_count'] = $year_data[$month][$weekday][$hour]['count'];
$data[$id][$prefix . '_average'] = ceil($year_data[$month][$weekday][$hour]['total'] / $year_data[$month][$weekday][$hour]['count']);
$data[$id][$prefix . '_rv_average'] = $rv_average;
// assign scheduler data
$scheduler_data[$year][$month][$weekday][$hour] = $rv_average;
}
else
{
if (!isset($scheduler_data[$year][$month][$weekday][$hour]))
{
$data[$id][$prefix . '_rv_average'] = 0;
$scheduler_data[$year][$month][$weekday][$hour] = 0;
}
$data[$id][$prefix . '_rv_average'] = 0;
$scheduler_data[$weekday][$hour] = 0;
}
}
}
}
$data['scheduler_data'] = $scheduler_data;
// error_log(print_r($data, true));

View file

@ -1487,6 +1487,60 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
$params['jo_service_charges'] = $sc_array;
// get odometer
$odometer = $obj->getMeta('odometer');
$params['odometer'] = $odometer;
// get customer email used in JO
$email = $obj->getMeta('customer_email');
$params['email'] = $email;
// get images if any
$jo_extra = $obj->getJOExtra();
$pic_array = [];
if ($jo_extra != null)
{
$b_speed_img = $jo_extra->getBeforeSpeedImageFilename();
$a_speed_img = $jo_extra->getAfterSpeedImageFilename();
$b_plate_img = $jo_extra->getBeforePlateNumImageFilename();
$a_plate_img = $jo_extra->getAfterPlateNumImageFilename();
$b_batt_img = $jo_extra->getBeforeBattImageFilename();
$a_batt_img = $jo_extra->getAfterBattImageFilename();
$b_other_images = $jo_extra->getBeforeOtherImages();
$a_other_images = $jo_extra->getAfterOtherImages();
$cust_signature = $jo_extra->getCustomerSignature();
if ($b_speed_img != null)
$pic_array['before_speed_img'] = $b_speed_img;
if ($a_speed_img != null)
$pic_array['after_speed_img'] = $a_speed_img;
if ($b_plate_img != null)
$pic_array['before_plate_img'] = $b_plate_img;
if ($a_plate_img != null)
$pic_array['after_plate_img'] = $a_plate_img;
if ($b_batt_img != null)
$pic_array['before_batt_img'] = $b_batt_img;
if ($a_batt_img != null)
$pic_array['after_batt_img'] = $a_batt_img;
foreach($b_other_images as $b_img)
{
$pic_array['b_other_images'][] = $b_img;
}
foreach ($a_other_images as $a_img)
{
$pic_array['a_other_images'][] = $a_img;
}
$params['signature'] = $cust_signature;
}
$params['jo_pictures'] = $pic_array;
$this->fillDropdownParameters($params);
$this->fillFormTags($params);

View file

@ -31,16 +31,42 @@
<div class="m-portlet__body">
<div class="form-group m-form__group row no-border">
<div class="col-lg-6">
<label data-field="date">Date</label>
<div class="input-group date dp">
<input type="text" name="date" id="date" class="form-control m-input" value="{{ "now"|date('d M Y') }}" readonly placeholder="Select a date" >
<span class="input-group-addon">
<i class="la la-calendar glyphicon-th"></i>
</span>
</div>
<div class="form-control-feedback hide" data-field="date"></div>
</div>
<div class="col-lg-6">
<label data-field="time_from">Restrict Time From</label>
<div class="input-group">
<input type="time" name="time_from" id="time_from" class="form-control m-input" value="">
</div>
<div class="form-control-feedback hide" data-field="date_from"></div>
</div>
<div class="col-lg-6">
<label data-field="time_to">Restrict Time To</label>
<div class="input-group">
<input type="time" name="time_to" id="time_to" class="form-control m-input" value="">
</div>
<div class="form-control-feedback hide" data-field="date_from"></div>
</div>
</div>
<div class="form-group m-form__group row no-border">
<div class="col-lg-6">
<label data-field="date_from">Date From</label>
<div class="input-group date dp">
<input type="text" name="date_from" id="date_from" class="form-control m-input" value="{{ "now"|date('d M Y') }}" readonly placeholder="Select a date" >
<span class="input-group-addon">
<i class="la la-calendar glyphicon-th"></i>
</span>
</div>
<div class="form-control-feedback hide" data-field="date_from"></div>
</div>
<div class="col-lg-6">
<label data-field="date_to">Date To</label>
<div class="input-group date dp">
<input type="text" name="date_to" id="date_to" class="form-control m-input" value="{{ "now"|date('d M Y') }}" readonly placeholder="Select a date" >
<span class="input-group-addon">
<i class="la la-calendar glyphicon-th"></i>
</span>
</div>
<div class="form-control-feedback hide" data-field="date_to"></div>
</div>
</div>
{% for hub_id in default_hubs %}

View file

@ -330,49 +330,49 @@ var lmon = chart2.series.push(new am4charts.LineSeries());
lmon.name = "Monday";
lmon.stroke = am4core.color("#003f5c");
lmon.strokeWidth = 2;
lmon.dataFields.valueY = "y2018_Monday_rv_average";
lmon.dataFields.valueY = "Monday_rv_average";
lmon.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Tuesday";
l.stroke = am4core.color("#374c80");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Tuesday_rv_average";
l.dataFields.valueY = "Tuesday_rv_average";
l.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Wednesday";
l.stroke = am4core.color("#7a5195");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Wednesday_rv_average";
l.dataFields.valueY = "Wednesday_rv_average";
l.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Thursday";
l.stroke = am4core.color("#bc5090");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Thursday_rv_average";
l.dataFields.valueY = "Thursday_rv_average";
l.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Friday";
l.stroke = am4core.color("#ef5675");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Friday_rv_average";
l.dataFields.valueY = "Friday_rv_average";
l.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Saturday";
l.stroke = am4core.color("#ff764a");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Saturday_rv_average";
l.dataFields.valueY = "Saturday_rv_average";
l.dataFields.categoryX = "hour";
var l = chart2.series.push(new am4charts.LineSeries());
l.name = "Sunday";
l.stroke = am4core.color("#ffa600");
l.strokeWidth = 2;
l.dataFields.valueY = "y2018_Sunday_rv_average";
l.dataFields.valueY = "Sunday_rv_average";
l.dataFields.categoryX = "hour";
{% endfor %}

View file

@ -492,6 +492,109 @@
</div>
</div>
{% if mode in ['onestep-edit'] %}
<div class="m-form__seperator m-form__seperator--dashed"></div>
<div class="m-form__section">
<div class="m-form__heading">
<h3 class="m-form__heading-title">
Other Information
</h3>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-3">
<label data-field="odometer">Odometer Reading</label>
<input type="text" name="odometer" id="odometer" class="form-control m-input other_info_field" value="{{ odometer }}" disabled>
</div>
<div class="col-lg-3">
<label data-field="email">Email Address</label>
<input type="text" name="email" id="email" class="form-control m-input other_info_field" value="{{ email }}" disabled>
</div>
<div class="col-lg-3">
<label> Customer Signature </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ signature }}');" ></div>
</div>
</div>
<div class="form-group m-form__group row">
<div class="col-lg-12">
<label> Pictures Before Service</label>
</div>
{% for key, picture in jo_pictures %}
{% if key == 'before_speed_img' %}
<div class="col-lg-2">
<label> Speedometer before Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% if key == 'before_plate_img' %}
<div class="col-lg-2">
<label> Plate Number before Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% if key == 'before_batt_img' %}
<div class="col-lg-2">
<label> Battery before Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="form-group m-form__group row">
<div class="col-lg-12">
<label> Other Images before Service</label>
</div>
{% for key, picture in jo_pictures %}
{% if key == 'b_other_images' %}
{% for pic in jo_pictures['b_other_images'] %}
<div class="col-lg-2">
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ pic }}');" ></div>
</div>
{% endfor %}
{% endif %}
{% endfor %}
</div>
<div class="form-group m-form__group row">
<div class="col-lg-12">
<label> Pictures After Service</label>
</div>
{% for key, picture in jo_pictures %}
{% if key == 'after_speed_img' %}
<div class="col-lg-2">
<label> Speedometer after Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% if key == 'after_plate_img' %}
<div class="col-lg-2">
<label> Plate Number after Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% if key == 'after_batt_img' %}
<div class="col-lg-2">
<label> Battery after Service </label>
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ picture }}');" ></div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="form-group m-form__group row">
<div class="col-lg-12">
<label> Other Images after Service</label>
</div>
{% for key, picture in jo_pictures %}
{% if key == 'a_other_images' %}
{% for pic in jo_pictures['a_other_images'] %}
<div class="col-lg-2">
<div class="portrait-box" style="background-image: url('{{ '/uploads/jo_extra/' ~ pic }}');" ></div>
</div>
{% endfor %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="m-form__seperator m-form__seperator--dashed"></div>
<div class="m-form__section" id="sc-section">
<div class="m-form__heading">