Add invoice ui elements and form submission to incoming job order form

This commit is contained in:
Ramon Gutierrez 2018-01-17 20:42:09 +08:00
parent 1d4450821d
commit 3132812308
3 changed files with 245 additions and 1 deletions

View file

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

View file

@ -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();

View file

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