Resolve "Rider assignment locking" #812

Merged
jankstudio merged 1 commit from 7-rider-assignment-locking into master 2018-02-16 08:03:28 +00:00
4 changed files with 313 additions and 10 deletions

View file

@ -34,10 +34,8 @@ jo_proc_submit:
jo_assign:
path: /job-order/assigning
controller: App\Controller\JobOrderController::listRows
controller: App\Controller\JobOrderController::listAssigning
methods: [GET]
defaults:
tier: "assign"
jo_assign_rows:
path: /job-order/assigning-rows
@ -59,4 +57,4 @@ jo_assign_submit:
jo_gen_invoice:
path: /job-order/generate-invoice
controller: App\Controller\JobOrderController::generateInvoice
methods: [POST]
methods: [POST]

View file

@ -210,6 +210,13 @@ class JobOrderController extends BaseController
];
}
public function listAssigning()
{
$params = $this->initParameters('jo_assign');
return $this->render('job-order/list.assigning.html.twig', $params);
}
public function listRows($tier)
{
// check which job order tier is being called for and confirm access
@ -300,6 +307,12 @@ class JobOrderController extends BaseController
else
$row['processor'] = $orow->getProcessedBy()->getFullName();
$assignor = $orow->getAssignedBy();
if ($assignor == null)
$row['assignor'] = '';
else
$row['assignor'] = $orow->getAssignedBy()->getFullName();
// add crud urls
$row['meta']['update_url'] = $this->generateUrl($tier_params['edit_route'], ['id' => $row['id']]);
@ -319,6 +332,7 @@ class JobOrderController extends BaseController
$em = $this->getDoctrine()->getManager();
// manual transaction since we're locking
$em->getConnection()->beginTransaction();
try
@ -508,16 +522,53 @@ class JobOrderController extends BaseController
{
$this->denyAccessUnlessGranted('jo_assign.list', null, 'No access.');
$em = $this->getDoctrine()->getManager();
// manual transaction since we're locking
$em->getConnection()->beginTransaction();
$params = $this->initParameters('jo_assign');
$params['mode'] = 'update-assigning';
// get row data
$em = $this->getDoctrine()->getManager();
$obj = $em->getRepository(JobOrder::class)->find($id);
try
{
// get row data
$obj = $em->getRepository(JobOrder::class)->find($id);
// make sure this row exists
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// make sure this row exists
if (empty($obj))
{
$em->getConnection()->rollback();
throw $this->createNotFoundException('The job order does not exist');
}
// check status
if ($obj->getStatus() != JOStatus::RIDER_ASSIGN)
{
$em->getConnection()->rollback();
throw $this->createNotFoundException('The job order does not have an assigning status');
}
// check if we are the assignor
$assignor = $obj->getAssignedBy();
$user = $this->getUser();
if ($assignor != null && $assignor->getID() != $user->getID())
{
$em->getConnection()->rollback();
throw $this->createAccessDeniedException('Not the assignor');
}
// make this user be the assignor
$obj->setAssignedBy($user);
$em->flush();
$em->getConnection()->commit();
}
catch (PessimisticLockException $e)
{
throw $this->createAccessDeniedException('Not the assignor');
}
// get parent associations
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();

View file

@ -0,0 +1,129 @@
{% 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">
Job Orders (Assigning)
</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-12">
<div class="form-group m-form__group row align-items-center">
<div class="col-md-4">
<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">
<span class="m-input-icon__icon m-input-icon__icon--left">
<span><i class="la la-search"></i></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!--begin: Datatable -->
<div id="data-rows"></div>
<!--end: Datatable -->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(function() {
var options = {
data: {
type: 'remote',
source: {
read: {
url: '{{ url('jo_assign_rows') }}',
method: 'POST'
}
},
saveState: {
cookie: false,
webstorage: false
},
pageSize: 10,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
rows: {
beforeTemplate: function (row, data, index) {
if (data.flag_advance) {
$(row).addClass('m-table__row--danger');
}
}
},
columns: [
{
field: 'id',
title: 'JO Number'
},
{
field: 'delivery_address',
title: 'Customer Area'
},
{
field: 'service_type',
title: 'Type of Transaction'
},
{
field: 'date_schedule',
title: 'Scheduled Date'
},
{
field: 'status',
title: 'Status'
},
{
field: 'processor',
title: 'Processor'
},
{
field: 'assignor',
title: 'Assignor'
},
{
field: 'Actions',
width: 110,
title: 'Actions',
sortable: false,
overflow: 'visible',
template: function (row, index, datatable) {
var actions = '<a href="' + row.meta.update_url + '" class="m-portlet__nav-link btn m-btn m-btn--hover-accent m-btn--icon m-btn--icon-only m-btn--pill btn-edit" title="View / Edit"><i class="la la-edit"></i></a>';
return actions;
},
}
],
search: {
onEnter: false,
input: $('#data-rows-search'),
delay: 400
}
};
var table = $("#data-rows").mDatatable(options);
});
</script>
{% endblock %}

View file

@ -0,0 +1,125 @@
{% 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">
Job Orders ({{ tier_name|capitalize }})
</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-12">
<div class="form-group m-form__group row align-items-center">
<div class="col-md-4">
<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">
<span class="m-input-icon__icon m-input-icon__icon--left">
<span><i class="la la-search"></i></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!--begin: Datatable -->
<div id="data-rows"></div>
<!--end: Datatable -->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(function() {
var options = {
data: {
type: 'remote',
source: {
read: {
url: '{{ url(rows_route) }}',
method: 'POST'
}
},
saveState: {
cookie: false,
webstorage: false
},
pageSize: 10,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
rows: {
beforeTemplate: function (row, data, index) {
if (data.flag_advance) {
$(row).addClass('m-table__row--danger');
}
}
},
columns: [
{
field: 'id',
title: 'JO Number'
},
{
field: 'delivery_address',
title: 'Customer Area'
},
{
field: 'service_type',
title: 'Type of Transaction'
},
{
field: 'date_schedule',
title: 'Scheduled Date'
},
{
field: 'status',
title: 'Status'
},
{
field: 'processor',
title: 'Processor'
},
{
field: 'Actions',
width: 110,
title: 'Actions',
sortable: false,
overflow: 'visible',
template: function (row, index, datatable) {
var actions = '<a href="' + row.meta.update_url + '" class="m-portlet__nav-link btn m-btn m-btn--hover-accent m-btn--icon m-btn--icon-only m-btn--pill btn-edit" title="View / Edit"><i class="la la-edit"></i></a>';
return actions;
},
}
],
search: {
onEnter: false,
input: $('#data-rows-search'),
delay: 400
}
};
var table = $("#data-rows").mDatatable(options);
});
</script>
{% endblock %}