Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 22 additions & 32 deletions assets/js/formset.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ let formset = function() {
let totalFormCounter;
let arr = []

let subTotalComputation = function(){
// Sub-t0tal computation
$('.field-amount').each(function(counter){
arr[counter] = Number( $(this).text() )
});
let subTotal = 0
let totalForm = Number( $('#id_form-TOTAL_FORMS').val() );
for(let counter=0; counter<totalForm; counter++){
subTotal += arr[counter];
}
$('.sub-total').removeAttr('hidden');
$('.sub-total').text(subTotal)
$('input#id_subtotal').val(subTotal);
}

let amountComputation = function(){
// Total amount calculation
Expand All @@ -16,6 +30,7 @@ let formset = function() {

if (!isNaN(total)){
$(this).parent().children('.field-amount').text(total);
subTotalComputation();
}
});
$('.field-rate').on('keydown keyup keypress focusout focus', function() {
Expand All @@ -25,8 +40,10 @@ let formset = function() {

if (!isNaN(total)){
$(this).parent().children('.field-amount').text(total);
subTotalComputation();
}
});
subTotalComputation();
}

// Display created elements
Expand Down Expand Up @@ -55,19 +72,11 @@ let formset = function() {
let removeForm = $(this).parent().parent();
removeForm.remove();
}
subTotalComputation();
});

amountComputation();

// Sub-t0tal computation
$('.field-amount').each(function(counter){
arr[counter] = Number( $(this).text() )
});
let subTotal = 0
for(let counter=0; counter<totalForm; counter++){
subTotal += arr[counter];
}
$('.sub-total').text(subTotal)
amountComputation();
subTotalComputation();
}

// Add order form
Expand Down Expand Up @@ -121,29 +130,10 @@ let formset = function() {
$(this).attr('id', counter) ;
});
}
// Sub-t0tal computation
$('.field-amount').each(function(counter){
arr[counter] = Number( $(this).text() )
});
let subTotal = 0
for(let counter=0; counter<totalForm; counter++){
subTotal += arr[counter];
}
$('.sub-total').text(subTotal)
subTotalComputation();
});

amountComputation();

// Sub-t0tal computation
$('.field-amount').each(function(counter){
arr[counter] = Number( $(this).text() )
});
let subTotal = 0
for(let counter=0; counter<totalForm; counter++){
subTotal += arr[counter];
}
$('.sub-total').text(subTotal)

subTotalComputation();
}
});
};
Expand Down
158 changes: 82 additions & 76 deletions assets/js/invoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ $(function() {
// Display invoice form
$("a.create-invoice").on('click', function(e) {
e.preventDefault();
$("div.invoice-box").empty();
$("div.invoice-box-form").show();
$("#invView").addClass('hidden');;
$("#invForm").removeClass('hidden');
});

// Ajax view invoice
Expand All @@ -14,80 +14,86 @@ $(function() {
let id = $(this).attr('id').toString();

$.ajax({
method: 'GET',
url: "/invoice/ajax/view/"+id+"",
context: $(this),
})
.done(function(response){
let obj = JSON.parse(response.invoice);
method: 'GET',
url: "/invoice/ajax/view/"+id+"",
dataType: 'json',
context: $(this),
success: function (resp) {
let invData = JSON.parse(resp.invoice);
let invItems = JSON.parse(resp.items);

if (invData.length) {
invData = invData[0];
}

let wrapperDiv = $('#invView');
let invForm = $('#invForm');
let invNum = $('#invNum');
let invDesc = $('#invDesc');
let invClient = $('#invClient');
let invPayStat = $('#invPayStat');
let invDueDate = $('#invDueDate');
let invDate = $('#invDate');
let invRem = $('#invRem');
let invSubTotal = $('#invSubTotal');
let invTotal = $('#invTotal');

let itemsTbody = $('#itemsTbody');
let itemsRow = $('#itemsRow');

wrapperDiv.removeClass('hidden');
invForm.addClass('hidden');

// Create invoice details template
for (let data in obj) {
$("div.invoice-box-form").hide()
$("div.invoice-box").empty()
$("div.invoice-box").append(
'<div class="col-md-12">'
+'<br>'
+'<div class="col-md-8"><label>Invoice Info</label></div>'
+'<div class="col-md-4"> '
+'<a href="#" class="btn">Edit</a>'
+'<a href="#">Delete</a>'
+'<a href="#" target="_blank">|Generate PDF|</a>'
+' <a href="#">Send</a>'
+'</div>'
+'<br>'
+'<hr>'
+'</div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Invoice #:</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.invoice_number
+' </div>'
+' </div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Client:</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.client
+' </div>'
+' </div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Item/s :</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.item
+' </div>'
+' </div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Invoice date:</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.invoice_date
+' </div>'
+' </div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Due date:</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.due_date
+' </div>'
+' </div>'
+'<div class="col-md-12">'
+'<div class="col-md-3">'
+' <label >Remarks :</label>'
+' </div>'
+' <div class="col-md-9">'
+obj[data].fields.remarks
+' </div>'
+' </div>'
)
}
});
let paymentStat = '';
if (invData.fields.payment_status == false){
paymentStat = 'unpaid';
} else if (invData.fields.payment_status == true){
paymentStat = 'paid';
}

let invDueDateData = new Date(invData.fields.due_date);
let invDateData = new Date(invData.fields.invoice_date);

let arrInvDate = [];
let arrDueDate = [];
let invoiceDate = '';
let invoiceDueDate = '';
arrInvDate = String(invDateData).split(' ');
arrDueDate = String(invDueDateData).split(' ');
invoiceDate = arrInvDate[1]+' '+arrInvDate[2]+', '+arrInvDate[3];
invoiceDueDate = arrDueDate[1]+' '+arrDueDate[2]+', '+arrDueDate[3];

invNum.text(resp.prefix.toUpperCase()+': '+resp.invoice_number);
invDesc.text(invData.fields.description.charAt(0).toUpperCase()
+ invData.fields.description.slice(1).toLowerCase()
);
invClient.text(resp.client.toLowerCase()
.replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
})
);
invPayStat.text(paymentStat.charAt(0).toUpperCase()+ paymentStat.slice(1).toLowerCase());
invDueDate.text(invoiceDueDate);
invDate.text(invoiceDate);
invRem.text(invData.fields.remarks.charAt(0).toUpperCase()
+ invData.fields.remarks.slice(1).toLowerCase()
);
invSubTotal.text(invData.fields.subtotal);
invTotal.text(invData.fields.subtotal);

if (invItems.length) {
itemsTbody.html('');
for (var i = invItems.length - 1; i >= 0; i--) {
let newRow = itemsRow.clone();
newRow.removeClass('hidden');
newRow.children('.itemDesc').html(invItems[i].fields.description);
newRow.children('.itemQty').html(invItems[i].fields.quantity);
newRow.children('.itemRate').html(invItems[i].fields.rate);
newRow.children('.itemAmount').html(invItems[i].fields.amount);
itemsTbody.append(newRow);
}
}
},
})
});
});
4 changes: 1 addition & 3 deletions invoices/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Meta:
'remarks',
'description',
'payment_status',
'subtotal',
)

def __init__(self,*args, **kwargs):
Expand Down Expand Up @@ -117,11 +118,8 @@ def clean(self):

for count,form in enumerate(self.forms):
if not form.data['form-'+str(count)+'-description']:
print("not description")
raise forms.ValidationError("Description is required!")
if not form.data['form-'+str(count)+'-quantity']:
print("not qty")
raise forms.ValidationError("Quantity is required!")
if not form.data['form-'+str(count)+'-rate']:
print("not rate")
raise forms.ValidationError("Rate is required!")
4 changes: 1 addition & 3 deletions invoices/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ class Invoice(models.Model):
payment_status = models.BooleanField( default=False)
pdf = models.FileField(upload_to=get_invoice_directory,null=True, blank=True)
remarks = models.TextField(max_length=255,null=True, blank=True)
subtotal = models.PositiveIntegerField()
status = models.CharField(max_length=10, choices=STATUS, default='draft')

class Meta:
unique_together = ('invoice_number', 'company')

def __str__(self):
return f"{self.invoice_number}"

def get_invoice_number(self):
return f"{self.invoice_number}".zfill(9)


Expand Down
31 changes: 21 additions & 10 deletions invoices/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ def get(self, *args, **kwargs):
"""
query = self.request.GET.get("q")
if query:
invoices = invoices.filter(invoice_number__icontains=query)
invoices = invoices.filter(invoice_number__icontains=query
).order_by('-date_updated')
else:
invoices = Invoice.objects.filter(company=self.request.user.company)
invoices = Invoice.objects.filter(company=self.request.user.company
).order_by('-date_updated')
context = {}
context['client_form'] = ClientForm()
ItemFormSet = formset_factory(ItemForm, formset=BaseItemFormSet)
Expand Down Expand Up @@ -170,7 +172,8 @@ def post(self, *args, **kwargs):
messages.success(self.request, 'Invoice is successfully Added')
return redirect('invoices')
else:
invoices = Invoice.objects.filter(company=self.request.user.company)
invoices = Invoice.objects.filter(company=self.request.user.company
).order_by('-date_updated')
context = {}
context['invoices'] = invoices
context['invoice_form'] = invoice_form
Expand Down Expand Up @@ -204,15 +207,23 @@ class InvoiceAjaxView(UserIsOwnerMixin, View):
"""

def get(self, *args, **kwargs):
"""Display pdf in browser
"""Display invoice details
"""
invoice = get_object_or_404(Invoice, id=kwargs['invoice_id'])
data = serializers.serialize('json', [invoice])
return JsonResponse({'invoice': data,
},
safe = False,
status=200
)
invoice_number = str(invoice)
client = str(invoice.client)
items = Item.objects.filter(invoice=kwargs['invoice_id'])
invoiceData = serializers.serialize('json', [invoice])
itemsData = serializers.serialize('json', items)
data = {
'client': client,
'invoice_number': invoice_number,
'invoice': invoiceData,
'items': itemsData,
'prefix': invoice.client.get_prefix(),
}
return JsonResponse(data, safe = False, status=200)



class InvoiceAddView(LoginRequiredMixin,TemplateView):
Expand Down
Loading