Add invoice ui elements and form submission to incoming job order form
This commit is contained in:
parent
1d4450821d
commit
3132812308
3 changed files with 245 additions and 1 deletions
|
|
@ -86,6 +86,30 @@ span.has-danger,
|
|||
font-weight: 300 !important;
|
||||
}
|
||||
|
||||
.table-compact th {
|
||||
font-size: 0.9rem !important;
|
||||
background-color: #F4F3F8;
|
||||
color: #575962;
|
||||
}
|
||||
|
||||
.table-compact > tbody > tr:nth-child(odd) {
|
||||
background-color: #F7F6FA;
|
||||
}
|
||||
|
||||
.table-compact td {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
.table-compact td {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.placeholder-row {
|
||||
background-color: #fff !important;
|
||||
padding: 32px 0 !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 995px) {
|
||||
.modal-lg {
|
||||
max-width: 1024px;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use App\Ramcar\BaseController;
|
|||
use App\Ramcar\ServiceType;
|
||||
use App\Ramcar\JOStatus;
|
||||
use App\Entity\JobOrder;
|
||||
use App\Entity\BatteryManufacturer;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerVehicle;
|
||||
use App\Entity\Outlet;
|
||||
|
|
@ -40,6 +41,7 @@ class JobOrderController extends BaseController
|
|||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
// get parent associations
|
||||
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
||||
$params['customers'] = $em->getRepository(Customer::class)->findAll();
|
||||
$params['outlet'] = $em->getRepository(Outlet::class)->findAll();
|
||||
$params['rider'] = $em->getRepository(Rider::class)->findAll();
|
||||
|
|
|
|||
|
|
@ -226,9 +226,74 @@
|
|||
Invoice
|
||||
</h3>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-3">
|
||||
<label>Amount:</label>
|
||||
<input type="text" id="invoice-amount" class="form-control m-input text-right" value="0.00" disabled>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<label>Tax:</label>
|
||||
<input type="text" id="invoice-tax" class="form-control m-input text-right" value="0.00" disabled>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<label>Discount:</label>
|
||||
<input type="text" id="invoice-discount" class="form-control m-input text-right" value="0.00" disabled>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<label>Final Amount:</label>
|
||||
<input type="text" id="invoice-final-amount" class="form-control m-input text-right" value="0.00" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-12">
|
||||
|
||||
<table id="invoice-table" class="table table-compact m-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item</th>
|
||||
<th class="text-right">Quantity</th>
|
||||
<th>Price Level</th>
|
||||
<th class="text-right">Res Price<br>(w/ Tax)</th>
|
||||
<th class="text-right">Total Price Adj.</th>
|
||||
<th>Final Amount</th>
|
||||
<th>No Trade-in Item?</th>
|
||||
<th>Battery Class</th>
|
||||
<th>Discount Item</th>
|
||||
<th>Percentage</th>
|
||||
<th>Converted Rate<br>(in Decimal)</th>
|
||||
<th class="text-right">Discount Amount</th>
|
||||
<th>Warranty Class</th>
|
||||
<th style="width: 50px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="14" class="placeholder-row">
|
||||
No items to display.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-3">
|
||||
<select class="form-control m-input" id="invoice-bmfg">
|
||||
<option value="">Select a battery manufacturer</option>
|
||||
{% for manufacturer in bmfgs %}
|
||||
<option value="{{ manufacturer.getID() }}">{{ manufacturer.getName() }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<select class="form-control m-input" id="invoice-battery" data-value="" disabled>
|
||||
<option value="">Select a manufacturer first</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-lg-2">
|
||||
<input type="text" id="invoice-quantity" class="form-control m-input text-right" placeholder="Quantity">
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<button type="button" class="btn btn-primary" id="btn-add-to-invoice">Add to Invoice</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -328,6 +393,9 @@ $(function() {
|
|||
var fields = form.serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0];
|
||||
disabled.prop('disabled', true);
|
||||
|
||||
// add invoice items to data
|
||||
fields['invoice_items'] = invoiceItems;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
|
|
@ -485,6 +553,156 @@ $(function() {
|
|||
tp.prop('disabled', true).timepicker('setTime', tp.data('default-value'));
|
||||
}
|
||||
}).change();
|
||||
|
||||
// update battery list when changing manufacturer
|
||||
$("#invoice-bmfg").change(function() {
|
||||
var id = $(this).val();
|
||||
var field = $("#invoice-battery");
|
||||
|
||||
// no id specified
|
||||
if (!id) {
|
||||
field.html('<option value="">Select a manufacturer first</option>').prop('disabled', true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get vehicles for this manufacturer
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ url('bmfg_batteries') }}",
|
||||
data: {id: id}
|
||||
}).done(function(response) {
|
||||
if (response.data.length > 0) {
|
||||
var html = '';
|
||||
|
||||
// TODO: Battery unit price is static for now
|
||||
var unitPrice = 1000;
|
||||
|
||||
$.each(response.data, function(index, battery) {
|
||||
html += '<option value="' + battery.id + '" data-index="' + index + '" data-unit-price="' + unitPrice + '">' + battery.model_name + ' ' + battery.size_name + ' (' + battery.prod_code + ')</option>';
|
||||
});
|
||||
|
||||
field.html(html).prop('disabled', false);
|
||||
} else {
|
||||
field.html('<option value="">No batteries found</option>').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// mask quantity field
|
||||
$("#invoice-quantity").inputmask("mask", {
|
||||
mask: "9999999",
|
||||
placeholder: ""
|
||||
});
|
||||
|
||||
var invoiceItems = [];
|
||||
var invoiceDiscount = 0;
|
||||
var invoiceTax = 0;
|
||||
var invoiceTotal = 0;
|
||||
|
||||
// add to invoice
|
||||
$("#btn-add-to-invoice").click(function() {
|
||||
var bmfg = $("#invoice-bmfg");
|
||||
var battery = $("#invoice-battery");
|
||||
var qty = $("#invoice-quantity");
|
||||
var tbody = $("#invoice-table tbody");
|
||||
var unitPrice = parseFloat(battery.find('option:selected').data('unit-price'));
|
||||
|
||||
if (!bmfg.val() || !battery.val() || !qty.val()) {
|
||||
swal({
|
||||
title: 'Whoops!',
|
||||
text: 'Please fill in all the invoice fields.',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNaN(qty.val())) {
|
||||
swal({
|
||||
title: 'Whoops!',
|
||||
text: 'Invalid quantity specified.',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var qtyVal = parseInt(qty.val());
|
||||
var subtotal = unitPrice * qtyVal;
|
||||
|
||||
// add to invoice array for form submission
|
||||
invoiceItems.push({
|
||||
'battery_manufacturer': bmfg.val(),
|
||||
'battery': battery.val(),
|
||||
'battery_price': unitPrice,
|
||||
'quantity': qtyVal,
|
||||
'subtotal': subtotal
|
||||
});
|
||||
|
||||
// build row html
|
||||
// TODO: Fill with actual data for the rest of the columns
|
||||
var html = '<tr>' +
|
||||
'<td>' + battery.find('option:selected').text() + '</td>' +
|
||||
'<td class="text-right col-quantity">' + qty.val() + '</td>' +
|
||||
'<td>Base Price</td>' + // TODO: static for now
|
||||
'<td class="col-unit-price">' + (Math.round(unitPrice * 100) / 100).toFixed(2) + '</td>' + // TODO: not sure if this is correct since it says w/ tax
|
||||
'<td>0.00</td>' + // TODO: static for now
|
||||
'<td>' + (Math.round(subtotal * 100) / 100).toFixed(2) + '</td>' + // TODO: I assumed this is unit price * qty
|
||||
'<td><span class="m-badge m-badge--success m-badge--wide">Yes</span></td>' + // TODO: static for now
|
||||
'<td>Regular</td>' +
|
||||
'<td></td>' +
|
||||
'<td></td>' +
|
||||
'<td></td>' +
|
||||
'<td class="col-discount"></td>' +
|
||||
'<td></td>' +
|
||||
'<td><button type="button" class="m-portlet__nav-link btn m-btn m-btn--hover-danger m-btn--icon m-btn--icon-only m-btn--pill btn-invoice-delete" title="Delete"><i class="la la-trash"></i></button></td>' +
|
||||
'</tr>';
|
||||
|
||||
// save to invoice table
|
||||
tbody.find('.placeholder-row').addClass('hide');
|
||||
tbody.append(html);
|
||||
|
||||
// add to invoice total and recompute
|
||||
invoiceTotal += subtotal;
|
||||
updateInvoiceFigures();
|
||||
});
|
||||
|
||||
function updateInvoiceFigures() {
|
||||
var amountField = $("#invoice-amount");
|
||||
var taxField = $("#invoice-tax");
|
||||
var discountField = $("#invoice-discount");
|
||||
var finalAmountField = $("#invoice-final-amount");
|
||||
var finalAmount = invoiceTotal + invoiceTax - invoiceDiscount;
|
||||
|
||||
amountField.val(parseFloat(Math.round(invoiceTotal * 100) / 100).toFixed(2));
|
||||
taxField.val(parseFloat(Math.round(invoiceTax * 100) / 100).toFixed(2));
|
||||
discountField.val(parseFloat(Math.round(invoiceDiscount * 100) / 100).toFixed(2));
|
||||
finalAmountField.val(parseFloat(Math.round(finalAmount * 100) / 100).toFixed(2));
|
||||
}
|
||||
|
||||
// remove from invoice table
|
||||
$(document).on("click", ".btn-invoice-delete", function() {
|
||||
var row = $(this).closest('tr');
|
||||
var qty = row.find('.col-quantity').html();
|
||||
var unitPrice = row.find('.col-unit-price').html();
|
||||
|
||||
// set defaults if for whatever reason they are not valid numbers
|
||||
if (isNaN(qty)) {
|
||||
qty = 1;
|
||||
}
|
||||
|
||||
if (isNaN(unitPrice)) {
|
||||
unitPrice = 0;
|
||||
}
|
||||
|
||||
// subtract from totals
|
||||
var subtotal = parseFloat(unitPrice) * parseInt(qty);
|
||||
invoiceTotal -= subtotal;
|
||||
updateInvoiceFigures();
|
||||
|
||||
// remove from table
|
||||
row.remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue