Merge branch '183-rejection-feature-for-hubs' into 'master'
Resolve "Rejection feature for hubs" Closes #183 See merge request jankstudio/resq!216
This commit is contained in:
commit
17e93f26ec
6 changed files with 493 additions and 6 deletions
|
|
@ -170,3 +170,8 @@ jo_open_edit_submit:
|
|||
path: /job-order/{id}/open-edit
|
||||
controller: App\Controller\JobOrderController::openEditSubmit
|
||||
methods: [POST]
|
||||
|
||||
jo_reject_hub:
|
||||
path: /job-order/{id}/reject-hub
|
||||
controller: App\Controller\JobOrderController::rejectHubSubmit
|
||||
methods: [POST]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use App\Ramcar\ModeOfPayment;
|
|||
use App\Ramcar\TransactionOrigin;
|
||||
use App\Ramcar\JOEventType;
|
||||
use App\Ramcar\FacilitatedType;
|
||||
use App\Ramcar\JORejectionReason;
|
||||
|
||||
use App\Entity\JobOrder;
|
||||
use App\Entity\BatteryManufacturer;
|
||||
|
|
@ -25,6 +26,7 @@ use App\Entity\Promo;
|
|||
use App\Entity\Rider;
|
||||
use App\Entity\Battery;
|
||||
use App\Entity\JOEvent;
|
||||
use App\Entity\JORejection;
|
||||
|
||||
use App\Service\InvoiceCreator;
|
||||
use App\Service\MapTools;
|
||||
|
|
@ -899,6 +901,12 @@ class JobOrderController extends BaseController
|
|||
$this->fillDropdownParameters($params);
|
||||
$this->fillFormTags($params);
|
||||
|
||||
// get rejections
|
||||
$rejections = $obj->getHubRejections();
|
||||
|
||||
// get rejection reasons
|
||||
$params['rejection_reasons'] = JORejectionReason::getCollection();
|
||||
|
||||
// get closest hubs
|
||||
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
|
||||
|
||||
|
|
@ -930,6 +938,19 @@ class JobOrderController extends BaseController
|
|||
// counters
|
||||
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
|
||||
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
|
||||
|
||||
// check for rejection
|
||||
$hub['flag_rejected'] = false;
|
||||
$hub_id = $hub['hub']->getID();
|
||||
|
||||
foreach ($rejections as $robj)
|
||||
{
|
||||
if ($robj->getHub()->getID() === $hub_id)
|
||||
{
|
||||
$hub['flag_rejected'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$params['hubs'][] = $hub;
|
||||
}
|
||||
|
|
@ -1505,6 +1526,12 @@ class JobOrderController extends BaseController
|
|||
$this->fillDropdownParameters($params);
|
||||
$this->fillFormTags($params);
|
||||
|
||||
// get rejections
|
||||
$rejections = $obj->getHubRejections();
|
||||
|
||||
// get rejection reasons
|
||||
$params['rejection_reasons'] = JORejectionReason::getCollection();
|
||||
|
||||
// get closest hubs
|
||||
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
|
||||
|
||||
|
|
@ -1538,6 +1565,19 @@ class JobOrderController extends BaseController
|
|||
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
|
||||
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
|
||||
|
||||
// check for rejection
|
||||
$hub['flag_rejected'] = false;
|
||||
$hub_id = $hub['hub']->getID();
|
||||
|
||||
foreach ($rejections as $robj)
|
||||
{
|
||||
if ($robj->getHub()->getID() === $hub_id)
|
||||
{
|
||||
$hub['flag_rejected'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$params['hubs'][] = $hub;
|
||||
}
|
||||
|
||||
|
|
@ -2540,4 +2580,103 @@ class JobOrderController extends BaseController
|
|||
// redirect to list
|
||||
return $this->redirectToRoute('jo_assign');
|
||||
}
|
||||
|
||||
public function rejectHubSubmit(Request $req, ValidatorInterface $validator, $id)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
|
||||
|
||||
// get object data
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$jo = $em->getRepository(JobOrder::class)->find($id);
|
||||
$processor = $jo->getProcessedBy();
|
||||
$user = $this->getUser();
|
||||
|
||||
// check if we're the one processing, return error otherwise
|
||||
if ($processor == null)
|
||||
throw $this->createAccessDeniedException('Not the processor');
|
||||
|
||||
if ($processor != null && $processor->getID() != $user->getID())
|
||||
throw $this->createAccessDeniedException('Not the processor');
|
||||
|
||||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// make sure job order exists
|
||||
if (empty($jo))
|
||||
throw $this->createNotFoundException('The item does not exist');
|
||||
|
||||
// check if hub is set
|
||||
if (empty($req->request->get('hub')))
|
||||
{
|
||||
$error_array['hub'] = 'No hub selected.';
|
||||
}
|
||||
else
|
||||
{
|
||||
// get hub
|
||||
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub'));
|
||||
|
||||
if (empty($hub))
|
||||
{
|
||||
$error_array['hub'] = 'Invalid hub specified.';
|
||||
}
|
||||
}
|
||||
|
||||
// check if this hub has already been rejected on this job order
|
||||
$robj = $em->getRepository(JORejection::class)->findOneBy([
|
||||
'job_order' => $jo,
|
||||
'hub' => $hub
|
||||
]);
|
||||
|
||||
if (!empty($robj))
|
||||
$error_array['hub'] = 'This hub has already been rejected for the current job order.';
|
||||
|
||||
// check if reason is set
|
||||
if (empty($req->request->get('reason')))
|
||||
$error_array['reason'] = 'No reason selected.';
|
||||
else if (!JORejectionReason::validate($req->request->get('reason')))
|
||||
$error_array['reason'] = 'Invalid reason specified.';
|
||||
|
||||
if (empty($error_array))
|
||||
{
|
||||
// coordinates
|
||||
$obj = new JORejection();
|
||||
|
||||
// set and save values
|
||||
$obj->setDateCreate(new DateTime())
|
||||
->setHub($hub)
|
||||
->setUser($this->getUser())
|
||||
->setJobOrder($jo)
|
||||
->setReason($req->request->get('reason'))
|
||||
->setRemarks($req->request->get('remarks'))
|
||||
->setContactPerson($req->request->get('contact_person'));
|
||||
|
||||
// validate
|
||||
$errors = $validator->validate($obj);
|
||||
|
||||
// add errors to list
|
||||
foreach ($errors as $error) {
|
||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// check if any errors were found
|
||||
if (!empty($error_array))
|
||||
{
|
||||
// return validation failure response
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'errors' => $error_array
|
||||
], 422);
|
||||
}
|
||||
|
||||
// validated! save the entity
|
||||
$em->persist($obj);
|
||||
$em->flush();
|
||||
|
||||
// return successful response
|
||||
return $this->json([
|
||||
'success' => 'Changes have been saved!',
|
||||
'request' => $req->request->all()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
148
src/Entity/JORejection.php
Normal file
148
src/Entity/JORejection.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="jo_rejection")
|
||||
*/
|
||||
class JORejection
|
||||
{
|
||||
// unique id
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
// date the entry was created
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
protected $date_create;
|
||||
|
||||
// user who rejected hub
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="User")
|
||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
// hub that was rejected
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Hub")
|
||||
* @ORM\JoinColumn(name="hub_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
protected $hub;
|
||||
|
||||
// job order where hub was rejected
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="JobOrder", inversedBy="hub_rejections")
|
||||
* @ORM\JoinColumn(name="jo_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
protected $job_order;
|
||||
|
||||
// generic reason for this rejection
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
protected $reason;
|
||||
|
||||
// remarks about this rejection
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
*/
|
||||
protected $remarks;
|
||||
|
||||
// contact person of hub about this rejection
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
protected $contact_person;
|
||||
|
||||
public function getID()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getDateCreate()
|
||||
{
|
||||
return $this->date_create;
|
||||
}
|
||||
|
||||
public function setDateCreate(DateTime $date_create)
|
||||
{
|
||||
$this->date_create = $date_create;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHub()
|
||||
{
|
||||
return $this->hub;
|
||||
}
|
||||
|
||||
public function setHub(Hub $hub)
|
||||
{
|
||||
$this->hub = $hub;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJobOrder()
|
||||
{
|
||||
return $this->job_order;
|
||||
}
|
||||
|
||||
public function setJobOrder(JobOrder $job_order)
|
||||
{
|
||||
$this->job_order = $job_order;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReason()
|
||||
{
|
||||
return $this->reason;
|
||||
}
|
||||
|
||||
public function setReason($reason)
|
||||
{
|
||||
$this->reason = $reason;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRemarks()
|
||||
{
|
||||
return $this->remarks;
|
||||
}
|
||||
|
||||
public function setRemarks($remarks)
|
||||
{
|
||||
$this->remarks = $remarks;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactPerson()
|
||||
{
|
||||
return $this->contact_person;
|
||||
}
|
||||
|
||||
public function setContactPerson($contact_person)
|
||||
{
|
||||
$this->contact_person = $contact_person;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
@ -262,6 +262,12 @@ class JobOrder
|
|||
*/
|
||||
protected $facilitated_by;
|
||||
|
||||
// hubs rejected for this job order
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="JORejection", mappedBy="job_order")
|
||||
*/
|
||||
protected $hub_rejections;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->date_create = new DateTime();
|
||||
|
|
@ -776,4 +782,9 @@ class JobOrder
|
|||
{
|
||||
return $this->facilitated_by;
|
||||
}
|
||||
|
||||
public function getHubRejections()
|
||||
{
|
||||
return $this->hub_rejections;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
src/Ramcar/JORejectionReason.php
Normal file
26
src/Ramcar/JORejectionReason.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Ramcar;
|
||||
|
||||
class JORejectionReason extends NameValue
|
||||
{
|
||||
const ADMINISTRATIVE = 'administrative';
|
||||
const NO_STOCK_SALES = 'no_stock_sales';
|
||||
const NO_STOCK_SERVICE = 'no_stock_service';
|
||||
const LINE_NO_ANSWER = 'line_no_answer';
|
||||
const LINE_BUSY = 'line_busy';
|
||||
const NO_RIDER_AVAILABLE = 'no_rider_available';
|
||||
const NO_RIDER_IN_TRANSIT = 'no_rider_in_transit';
|
||||
const REFUSAL = 'refusal';
|
||||
|
||||
const COLLECTION = [
|
||||
'administrative' => 'ADMINISTRATIVE',
|
||||
'no_stock_sales' => 'NO STOCK - SALES',
|
||||
'no_stock_service' => 'NO STOCK - SERVICE',
|
||||
'line_no_answer' => 'LINE NO ANSWER',
|
||||
'line_busy' => 'LINE BUSY',
|
||||
'no_rider_available' => 'NO RIDER - AVAILABLE',
|
||||
'no_rider_in_transit' => 'NO RIDER - IN TRANSIT',
|
||||
'refusal' => 'REFUSAL',
|
||||
];
|
||||
}
|
||||
|
|
@ -561,7 +561,9 @@
|
|||
-->
|
||||
<th class="text-right">Available Riders</th>
|
||||
<th class="text-right">Jobs For Assignment</th>
|
||||
<th>Contact Numbers</th> </tr>
|
||||
<th>Contact Numbers</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="placeholder-row{{ hubs|length > 0 ? ' hide' }}">
|
||||
|
|
@ -581,6 +583,13 @@
|
|||
<td class="text-right">{{ hub.rider_count }}</td>
|
||||
<td class="text-right">{{ hub.jo_count }}</td>
|
||||
<td>{{ hub.hub.getContactNumbers|replace({"\n": ', '}) }}</td>
|
||||
<td>
|
||||
{% if hub.flag_rejected %}
|
||||
<button type="button" class="btn btn-danger btn-disabled" disabled>Rejected</button>
|
||||
{% else %}
|
||||
<button type="button" data-hub-id="{{ hub.hub.getID }}" data-hub-name="{{ hub.hub.getName }}" data-hub-branch="{{ hub.hub.getBranch }}" class="btn-reject btn btn-info">Reject</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
@ -804,7 +813,7 @@
|
|||
<button type="submit" class="btn btn-success">{{ mode == 'update-fulfillment' ? 'Fulfill' : 'Submit' }}</button>
|
||||
{% endif %}
|
||||
{% if ftags.set_map_coordinate and is_granted('joborder.cancel') and not obj.isCancelled %}
|
||||
<a href="{{ url('jo_cancel', {'id': obj.getID}) }}" class="btn btn-danger btn-cancel-job-order">Cancel Job Order</button>
|
||||
<a href="{{ url('jo_cancel', {'id': obj.getID}) }}" class="btn btn-danger btn-cancel-job-order">Cancel Job Order</a>
|
||||
{% endif %}
|
||||
{% if mode != 'create' %}
|
||||
<a href="{{ return_url }}" class="btn btn-secondary">Back</a>
|
||||
|
|
@ -818,6 +827,68 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if mode in ['update-processing', 'update-reassign-hub'] %}
|
||||
<!-- rejection modal -->
|
||||
<div id="modal-rejection" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal-rejection-label" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<form id="hub-reject-form" class="m-form" method="post" action="{{ url('jo_reject_hub', {'id': obj.getID} ) }}">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modal-rejection-label">Reject Hub</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="m-form__section m-form__section--first m-form__section--last">
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-md-6">
|
||||
<label for="hub-reject-name" data-field="hub_name">Hub</label>
|
||||
<input type="text" name="hub_name" id="hub-reject-name" class="form-control m-input" readonly>
|
||||
<div class="form-control-feedback hide" data-field="hub_name"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="hub-reject-branch" data-field="hub_branch">Branch</label>
|
||||
<input type="text" name="hub_branch" id="hub-reject-branch" class="form-control m-input" readonly>
|
||||
<div class="form-control-feedback hide" data-field="hub_branch"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-md-6">
|
||||
<label for="hub-reject-reason" data-field="reason">Reason</label>
|
||||
<select id="hub-reject-reason" class="form-control m-input" name="reason">
|
||||
{% for key, reason in rejection_reasons %}
|
||||
<option value="{{ key }}">{{ reason }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-control-feedback hide" data-field="reason"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="hub-reject-contact-person" data-field="contact_person">Contact Person</label>
|
||||
<input type="text" name="contact_person" id="hub-reject-contact-person" class="form-control m-input">
|
||||
<div class="form-control-feedback hide" data-field="contact_person"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-12">
|
||||
<label for="hub-reject-remarks" data-field="remarks">Remarks</label>
|
||||
<textarea name="remarks" id="hub-reject-remarks" class="form-control m-input" rows="8"></textarea>
|
||||
<div class="form-control-feedback hide" data-field="remarks"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input type="hidden" id="hub-reject-id" name="hub">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Reject</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
|
@ -1009,10 +1080,10 @@ $(function() {
|
|||
});
|
||||
|
||||
// remove all error classes
|
||||
function removeErrors() {
|
||||
$(".form-control-danger").removeClass('form-control-danger');
|
||||
$("[data-field]").removeClass('has-danger');
|
||||
$(".form-control-feedback[data-field]").addClass('hide');
|
||||
function removeErrors(formSelector = '') {
|
||||
$(formSelector + " .form-control-danger").removeClass('form-control-danger');
|
||||
$(formSelector + " [data-field]").removeClass('has-danger');
|
||||
$(formSelector + " .form-control-feedback[data-field]").addClass('hide');
|
||||
}
|
||||
|
||||
// store selected vehicle data
|
||||
|
|
@ -1469,6 +1540,93 @@ $(function() {
|
|||
var ticketTable = $("#data-tickets").mDatatable(ticketOptions);
|
||||
{% endif %}
|
||||
|
||||
{% if mode in ['update-processing', 'update-reassign-hub'] %}
|
||||
// reject hub
|
||||
$(".btn-reject").click(function(e) {
|
||||
var hubID = $(this).data('hub-id');
|
||||
var hubName = $(this).data('hub-name');
|
||||
var hubBranch = $(this).data('hub-branch');
|
||||
|
||||
$("#hub-reject-id").val(hubID);
|
||||
$("#hub-reject-name").val(hubName);
|
||||
$("#hub-reject-branch").val(hubBranch);
|
||||
$("#modal-rejection").modal('show');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// focus on reason field
|
||||
$("#modal-rejection").on('shown.bs.modal', function() {
|
||||
$("#hub-reject-reason").focus();
|
||||
});
|
||||
|
||||
// reset reject form on close modal
|
||||
$("#modal-rejection").on('hidden.bs.modal', function() {
|
||||
$("#hub-reject-contact-person, #hub-reject-remarks").val("");
|
||||
$("#hub-reject-reason").prop('selectedIndex', 0);
|
||||
});
|
||||
|
||||
// submit hub rejection
|
||||
$("#hub-reject-form").submit(function(e) {
|
||||
var form = $(this);
|
||||
var btnSubmit = form.find('[type="submit"]');
|
||||
|
||||
// disable the button
|
||||
btnSubmit.prop('disabled', true).html('<i class="fas fa-spinner fa-spin fa-fw"></i> Please wait');
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: form.prop('action'),
|
||||
data: form.serialize()
|
||||
}).done(function(response) {
|
||||
// set button state
|
||||
var btnReject = $("#hubs-table").find("tr[data-id='" + $("#hub-reject-id").val() + "']").find('.btn-reject');
|
||||
btnReject.removeClass('btn-reject btn-info').addClass('btn-danger btn-disabled').prop('disabled', true).html('Rejected');
|
||||
|
||||
// remove all error classes
|
||||
removeErrors("#hub-reject-form");
|
||||
btnSubmit.prop('disabled', false).html('Reject');
|
||||
|
||||
// hide modal
|
||||
$("#modal-rejection").modal('hide');
|
||||
}).fail(function(response) {
|
||||
if (response.status == 422) {
|
||||
form_in_process = false;
|
||||
var errors = response.responseJSON.errors;
|
||||
var firstfield = false;
|
||||
|
||||
// remove all error classes first
|
||||
removeErrors("#hub-reject-form");
|
||||
btnSubmit.prop('disabled', false).html('Reject');
|
||||
|
||||
// display errors contextually
|
||||
$.each(errors, function(field, msg) {
|
||||
var formfield = form.find("[name='" + field + "'], [data-name='" + field + "']");
|
||||
var label = form.find("label[data-field='" + field + "']");
|
||||
var msgbox = form.find(".form-control-feedback[data-field='" + field + "']");
|
||||
|
||||
// add error classes to bad fields
|
||||
formfield.addClass('form-control-danger');
|
||||
label.addClass('has-danger');
|
||||
msgbox.html(msg).addClass('has-danger').removeClass('hide');
|
||||
|
||||
// check if this field comes first in DOM
|
||||
var domfield = formfield.get(0);
|
||||
|
||||
if (!firstfield || (firstfield && firstfield.compareDocumentPosition(domfield) === 2)) {
|
||||
firstfield = domfield;
|
||||
}
|
||||
});
|
||||
|
||||
// focus on first bad field
|
||||
firstfield.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
// cancel job order
|
||||
$(".btn-cancel-job-order").click(function(e) {
|
||||
var url = $(this).prop('href');
|
||||
|
|
|
|||
Loading…
Reference in a new issue