diff --git a/assets/js/custom.js b/assets/js/custom.js deleted file mode 100644 index 61d85cf..0000000 --- a/assets/js/custom.js +++ /dev/null @@ -1,27 +0,0 @@ - - - $(document).ready(function() { - $('input#id_first_name').keyup(function(){ - var f = $(this).val(); - var l = $('input#id_last_name').val() - $('input#id_display_name').val(f+' '+l); - }); - - $('input#id_last_name').keyup(function(){ - var l = $(this).val(); - var f = $('input#id_first_name').val() - $('input#id_display_name').val(f+' '+l); - }); - - if ($( "select#id_item_type").val() == 'fixed'){ - $('input#id_amount').removeAttr("disabled") - }else if($( "select#id_item_type").val() == 'quantity'){ - $('input#id_quantity').removeAttr("disabled") - $('input#id_rate').removeAttr("disabled") - } - - $( "select#items").click(function(){ - var selected = $(this).val(); - $('div#item-pick').append(''+selected+'') - }); - }); \ No newline at end of file diff --git a/assets/js/formset.js b/assets/js/formset.js index 9cdd19e..87fb1d6 100644 --- a/assets/js/formset.js +++ b/assets/js/formset.js @@ -1,140 +1,127 @@ 'use strict'; -let formset = function() { - - let totalForm = Number( $('#id_form-TOTAL_FORMS').val() ); - 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= 0; i--) { +function invoiceView(id) { + // Invoice details + $.ajax({ + method: 'GET', + url: "/invoice/ajax/view/" + id + "", + dataType: 'json', + context: $(this), + success: function(resp) { + + createInvoice(); + + let invData = JSON.parse(resp.invoice); + let invItems = JSON.parse(resp.items); + 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 invURLEdit = $('a[name="invoiceURLEdit"]'); + let totalForm = $('#id_form-TOTAL_FORMS'); + let itemsTbody = $('#itemsTbody'); + let itemsRow = $('#itemsRow'); + let invForm = $('#invForm'); + let invView = $('#invView'); + + if (invData.length) { + invData = invData[0]; + } + + // Display view content + if (invView.hasClass('hidden')) { + invView.removeClass('hidden'); + invForm.addClass('hidden'); + } else { + invView.removeClass('hidden'); + invForm.addClass('hidden'); + } + + 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 = ''; + + // Display data + 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); + + invURLEdit.attr({ + 'href': '/invoice/edit/' + invData.pk + '/' + invItems.length + '/', + 'id': invData.pk, + }); + + if (invItems.length) { + itemsTbody.html(''); + for (var i = 0; i <= invItems.length - 1; i++) { let newRow = itemsRow.clone(); newRow.removeClass('hidden'); newRow.children('.itemDesc').html(invItems[i].fields.description); @@ -91,9 +172,66 @@ $(function() { newRow.children('.itemRate').html(invItems[i].fields.rate); newRow.children('.itemAmount').html(invItems[i].fields.amount); itemsTbody.append(newRow); - } } - }, - }) - }); + } + }, + }) +} + +function createInvoice(id) { + // Create invoice + let invoice = invoiceJS(); + invoice.invoiceForm(); +} + +function addOrder() { + // Add order + formset.addFormSet(); + formset.reIndex(); + formset.displayRemove(); +} + +function deleteRowOrder(id) { + // Delete row order form + $('a#' + id).parent().parent().remove(); + $('#id_form-TOTAL_FORMS').val(formset.totalForm() - 1); + //removeForm.remove(); + formset.reIndex(); + formset.computationSubtotal(); +} + +function qtyCompute(id) { + // Compute amount when qty is change + $('.field-quantity').on('keyup', function(event) { + let rate = $(this).parent().children('.field-rate').children().val(); + let quantity = $(this).children().val(); + let total = parseInt(rate) * parseInt(quantity); + + if (!isNaN(total)) { + $(this).parent().children('.field-amount').children('span').text(total); + $(this).parent().children('.field-amount').children('input').val(total); + } else { + $(this).parent().children('.field-amount').children('span').text(0); + $(this).parent().children('.field-amount').children('input').val(0); + } + formset.computationSubtotal(); + }); +} + +function rateCompute(id) { + // Compute amount when rate is change + $('.field-rate').on('keyup', function(event) { + let rate = $(this).children().val(); + let quantity = $(this).parent().children('.field-quantity').children().val(); + let total = parseInt(rate) * parseInt(quantity); + + if (!isNaN(total)) { + $(this).parent().children('.field-amount').children('span').text(total); + $(this).parent().children('.field-amount').children('input').val(total); + } else { + $(this).parent().children('.field-amount').children('span').text(0); + $(this).parent().children('.field-amount').children('input').val(0); + } + formset.computationSubtotal(); }); +} diff --git a/invoices/forms.py b/invoices/forms.py index ad9bae1..7a19c2b 100644 --- a/invoices/forms.py +++ b/invoices/forms.py @@ -2,7 +2,7 @@ from django import forms from django.conf import settings -from django.forms import BaseFormSet, formset_factory +from django.forms import inlineformset_factory, modelformset_factory from clients.models import Client @@ -36,6 +36,7 @@ def __init__(self,*args, **kwargs): """Invoice needs company for filtering """ self.company = kwargs.pop('company', None) + self.invNumber = kwargs.pop('invNumber', None) return super(InvoiceForm, self).__init__(*args, **kwargs) def clean_invoice_date(self): @@ -62,12 +63,13 @@ def clean_invoice_number(self): """ Invoice number unique together validation """ invoice_number = self.cleaned_data.get('invoice_number') - invoice_number_q = Invoice.objects.filter(invoice_number__exact=invoice_number, - company=self.company - ) + invoice_number_q = Invoice.objects.filter(invoice_number=invoice_number, + company=self.company, + ) if not self.instance : if invoice_number_q.exists(): raise forms.ValidationError("Invoice Number already exists:") + if self.instance.invoice_number != invoice_number: if invoice_number_q.exists(): raise forms.ValidationError("Invoice Number already exists:") @@ -107,19 +109,30 @@ class Meta: model = Item fields = ('description', 'quantity', - 'rate' - ) - - -class BaseItemFormSet(BaseFormSet): - def clean(self): - if any(self.errors): - return - - for count,form in enumerate(self.forms): - if not form.data['form-'+str(count)+'-description']: - raise forms.ValidationError("Description is required!") - if not form.data['form-'+str(count)+'-quantity']: - raise forms.ValidationError("Quantity is required!") - if not form.data['form-'+str(count)+'-rate']: - raise forms.ValidationError("Rate is required!") + 'rate', + 'amount', + ) + +""" Model formset +""" +ItemFormSet = modelformset_factory( + Item, + ItemForm, + extra=0, +) + + +""" Inline formset +""" +ItemInlineFormSet = inlineformset_factory( + Invoice, + Item, + extra = 0, + fields = ('amount', + 'description', + 'quantity', + 'rate', + ), + formset = ItemFormSet, + min_num = 1 , +) \ No newline at end of file diff --git a/invoices/migrations/0001_initial.py b/invoices/migrations/0001_initial.py index 34a1080..b0f60d5 100644 --- a/invoices/migrations/0001_initial.py +++ b/invoices/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0 on 2018-02-14 08:54 +# Generated by Django 2.0 on 2018-02-22 05:25 from django.conf import settings from django.db import migrations, models @@ -11,9 +11,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('users', '0005_remove_company_owner'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('clients', '0010_client_archive'), + ('users', '0005_remove_company_owner'), ] operations = [ @@ -31,6 +31,7 @@ class Migration(migrations.Migration): ('payment_status', models.BooleanField(default=False)), ('pdf', models.FileField(blank=True, null=True, upload_to=invoices.utils.get_invoice_directory)), ('remarks', models.TextField(blank=True, max_length=255, null=True)), + ('subtotal', models.PositiveIntegerField()), ('status', models.CharField(choices=[('draft', 'Draft'), ('sent', 'Sent')], default='draft', max_length=10)), ('client', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='clients.Client')), ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Company')), @@ -44,9 +45,9 @@ class Migration(migrations.Migration): ('amount', models.PositiveIntegerField()), ('date_created', models.DateTimeField(auto_now_add=True)), ('date_updated', models.DateTimeField(auto_now=True)), - ('description', models.CharField(blank=True, max_length=255, null=True)), - ('quantity', models.PositiveIntegerField(blank=True, null=True)), - ('rate', models.PositiveIntegerField(blank=True, null=True)), + ('description', models.CharField(max_length=255)), + ('quantity', models.PositiveIntegerField()), + ('rate', models.PositiveIntegerField()), ('invoice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='invoices.Invoice')), ('owner', models.ForeignKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='items', to=settings.AUTH_USER_MODEL)), ], diff --git a/invoices/migrations/0002_auto_20180223_0221.py b/invoices/migrations/0002_auto_20180223_0221.py new file mode 100644 index 0000000..ef8408c --- /dev/null +++ b/invoices/migrations/0002_auto_20180223_0221.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0 on 2018-02-23 02:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0005_remove_company_owner'), + ('invoices', '0001_initial'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='invoice', + unique_together={('company', 'invoice_number')}, + ), + ] diff --git a/invoices/migrations/0003_auto_20180219_0848.py b/invoices/migrations/0003_auto_20180219_0848.py deleted file mode 100644 index 274be3c..0000000 --- a/invoices/migrations/0003_auto_20180219_0848.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.0 on 2018-02-19 08:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('invoices', '0002_auto_20180219_0339'), - ] - - operations = [ - migrations.AlterField( - model_name='item', - name='quantity', - field=models.PositiveIntegerField(), - ), - migrations.AlterField( - model_name='item', - name='rate', - field=models.PositiveIntegerField(), - ), - ] diff --git a/invoices/migrations/0003_auto_20180223_0832.py b/invoices/migrations/0003_auto_20180223_0832.py new file mode 100644 index 0000000..ad2e009 --- /dev/null +++ b/invoices/migrations/0003_auto_20180223_0832.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0 on 2018-02-23 08:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('invoices', '0002_auto_20180223_0221'), + ] + + operations = [ + migrations.AlterField( + model_name='invoice', + name='subtotal', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/invoices/migrations/0004_auto_20180223_0922.py b/invoices/migrations/0004_auto_20180223_0922.py new file mode 100644 index 0000000..374ddda --- /dev/null +++ b/invoices/migrations/0004_auto_20180223_0922.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0 on 2018-02-23 09:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('invoices', '0003_auto_20180223_0832'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='amount', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/invoices/migrations/0002_auto_20180219_0339.py b/invoices/migrations/0005_auto_20180225_1221.py similarity index 55% rename from invoices/migrations/0002_auto_20180219_0339.py rename to invoices/migrations/0005_auto_20180225_1221.py index 5cb1f42..ba1bb9a 100644 --- a/invoices/migrations/0002_auto_20180219_0339.py +++ b/invoices/migrations/0005_auto_20180225_1221.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0 on 2018-02-19 03:39 +# Generated by Django 2.0 on 2018-02-25 12:21 from django.db import migrations, models @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('invoices', '0001_initial'), + ('invoices', '0004_auto_20180223_0922'), ] operations = [ migrations.AlterField( model_name='item', - name='description', - field=models.CharField(max_length=255), + name='amount', + field=models.PositiveIntegerField(), ), ] diff --git a/invoices/models.py b/invoices/models.py index a3260b0..765deca 100644 --- a/invoices/models.py +++ b/invoices/models.py @@ -29,16 +29,16 @@ class Invoice(models.Model): owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='invoice', - default='' + default='', ) 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() + subtotal = models.PositiveIntegerField(null=True, blank=True) status = models.CharField(max_length=10, choices=STATUS, default='draft') class Meta: - unique_together = ('invoice_number', 'company') + unique_together = ('company', 'invoice_number') def __str__(self): return f"{self.invoice_number}".zfill(9) diff --git a/invoices/urls.py b/invoices/urls.py index 41525ff..7940bd9 100644 --- a/invoices/urls.py +++ b/invoices/urls.py @@ -1,24 +1,21 @@ from django.urls import path from invoices.views import ( - IndexView, - InvoiceListView, - InvoiceView, - InvoiceAddView, - InvoiceEditView, - InvoiceDeleteView, - InvoiceEmailView, - PdfPreview, - MakeInvoiceView, + IndexView, InvoiceAjaxView, + InvoiceView, + InvoiceDeleteView, + InvoiceEmailView, + MakeInvoiceView, + PdfPreview, + UpdateInvoiceForm, ) urlpatterns = [ path('', IndexView.as_view(), name='index'), - path('invoices/', InvoiceListView.as_view(), name='invoices'), - path('invoice/view//', InvoiceView.as_view(), name='invoice_view'), - path('invoice/add/', InvoiceAddView.as_view(), name='invoice_add'), - path('invoice/edit//', InvoiceEditView.as_view(), name='invoice_edit'), + path('invoices/', InvoiceView.as_view(), name='invoices'), + path('invoice/edit///', UpdateInvoiceForm.as_view() + , name='invoice_edit'), path('invoice/delete//', InvoiceDeleteView.as_view(), name='invoice_delete'), path('invoice/send_email//', InvoiceEmailView.as_view(), name='invoice_email'), path('invoice/pdf//', PdfPreview.as_view(), name='invoice_pdf'), diff --git a/invoices/views.py b/invoices/views.py index e039e2d..adb5838 100644 --- a/invoices/views.py +++ b/invoices/views.py @@ -8,6 +8,7 @@ from django.db.models import Q from django.forms import formset_factory from django.http import Http404, HttpResponse, JsonResponse +from django.utils.datastructures import MultiValueDictKeyError from django.shortcuts import render, redirect, get_object_or_404 from django.template.loader import get_template from django.views import View @@ -18,7 +19,11 @@ from clients.models import Client from invoices.mixins import PdfMixin, UserIsOwnerMixin from invoices.models import Invoice, Item -from invoices.forms import BaseItemFormSet, ItemForm, InvoiceForm, InvoiceEmailForm +from invoices.forms import (ItemForm, + ItemInlineFormSet, + InvoiceForm, + InvoiceEmailForm, + ) from users.models import User from xhtml2pdf import pisa @@ -107,39 +112,41 @@ def post(self, *args, **kwargs): return render(self.request, self.template_name, context) -class InvoiceListView(LoginRequiredMixin ,TemplateView): - """Display list of invoice +class InvoiceView(LoginRequiredMixin ,TemplateView): + """Display invoice """ template_name = 'invoices/all_invoice.html' def get(self, *args, **kwargs): - """Display invoices data + """ View invoice info and add invoice """ query = self.request.GET.get("q") if query: - invoices = invoices.filter(invoice_number__icontains=query - ).order_by('-date_updated') + invoices = invoices.filter(invoice_number__icontains=query, + ).order_by('-date_updated') else: - invoices = Invoice.objects.filter(company=self.request.user.company - ).order_by('-date_updated') + invoices = Invoice.objects.filter(company=self.request.user.company, + ).order_by('-date_updated') + + formset = ItemInlineFormSet(queryset = Item.objects.none()) + context = {} context['client_form'] = ClientForm() - ItemFormSet = formset_factory(ItemForm, formset=BaseItemFormSet) - context['formset'] = ItemFormSet() + context['formset'] = formset context['invoices'] = invoices context['invoice_form'] = InvoiceForm() context['invoice_form'].fields['client'].queryset = Client.objects.filter( company=self.request.user.company, archive=False - ).order_by('-date_updated') + ).order_by('-date_updated') return render(self.request, self.template_name, context) def post(self, *args, **kwargs): - """ Get filled invoice form and create + """ Create and Add invoice """ - ItemFormSet = formset_factory(ItemForm, formset=BaseItemFormSet) - formset = ItemFormSet(self.request.POST) invoice_form = InvoiceForm(self.request.POST, company=self.request.user.company) + formset = ItemInlineFormSet(self.request.POST, queryset = Item.objects.none()) + context = {} if invoice_form.is_valid() and formset.is_valid(): # Save invoice @@ -156,56 +163,131 @@ def post(self, *args, **kwargs): latest = 0 item_id = latest + 1 - # Save item/s - for count,form in enumerate(formset): - item_form = ItemForm() - item_id = item_id + count - item = item_form.save(commit=False) - item.id = item_id - item.invoice = invoice + # Save item/s + items = formset.save(commit=False) + for count,item in enumerate(items): + item.id = item_id+count item.owner = self.request.user - item.description = form.data['form-'+str(count)+'-description'] - item.quantity = form.data['form-'+str(count)+'-quantity'] - item.rate = form.data['form-'+str(count)+'-rate'] - item.amount = int(item.rate) * int(item.quantity) + item.invoice = invoice item.save() messages.success(self.request, 'Invoice is successfully Added') return redirect('invoices') else: - invoices = Invoice.objects.filter(company=self.request.user.company - ).order_by('-date_updated') - context = {} + invoices = Invoice.objects.filter(company=self.request.user.company, + ).order_by('-date_updated') + context['invoices'] = invoices context['invoice_form'] = invoice_form context['invoice_form'].fields['client'].queryset = Client.objects.filter( company=self.request.user.company, archive=False - ).order_by('-date_updated') - context['formset'] = ItemFormSet(self.request.POST) + ).order_by('-date_updated') + context['formset'] = formset context['client_form'] = ClientForm(self.request.POST) return render(self.request, self.template_name, context) return render(self.request, self.template_name, context) -class InvoiceView(UserIsOwnerMixin, TemplateView): - """View invoice information +class UpdateInvoiceForm(UserIsOwnerMixin, TemplateView): + """ Update form """ - template_name = 'invoices/view_invoice.html' + template_name = 'invoices/all_invoice.html' def get(self, *args, **kwargs): - """Display pdf in browser - """ - invoice = get_object_or_404(Invoice, id=kwargs['invoice_id']) - context = super().get_context_data(**kwargs) - context['logo'] = f"{settings.MEDIA_ROOT}{invoice.company.logo}" - context['invoice'] = invoice + query = self.request.GET.get("q") + if query: + invoices = invoices.filter(invoice_number__icontains=query, + ).order_by('-date_updated') + else: + invoices = Invoice.objects.filter(company=self.request.user.company, + ).order_by('-date_updated') + + invoice = get_object_or_404(Invoice, pk=kwargs['invoice_id']) + item = ItemForm(instance=invoice) + formset = ItemInlineFormSet(queryset = item.instance.item_set.all(), ) + + context = {} + context['formset'] = formset + context['invoices'] = invoices + context['invoice_form'] = InvoiceForm(instance=invoice) + context['invoice_form'].fields['client'].queryset = Client.objects.filter( + company=self.request.user.company, + archive=False + ).order_by('-date_updated') return render(self.request, self.template_name, context) + def post(self, *args, **kwargs): + + invoice = get_object_or_404(Invoice, pk=kwargs['invoice_id']) + invoice_form = InvoiceForm(self.request.POST, + company=self.request.user.company, + instance=invoice, + ) + item = ItemForm(instance=invoice) + queryset = item.instance.item_set.all() + formset = ItemInlineFormSet(self.request.POST, queryset = queryset, ) + context = {} + + if invoice_form.is_valid() and formset.is_valid(): + invoice = invoice_form.save(commit=False) + invoice.owner = self.request.user + invoice.company = self.request.user.company + invoice.save() + + # Check latet item id + try: + latest = Item.objects.latest('id') + item_id = latest.id + 1 + except: + latest = 0 + item_id = latest + 1 + + data_id = [] + q_id = item.instance.item_set.all().values_list('id', flat=True) + formset_id = [form_id['id'] for form_id in q_id.values()] + items = formset.save(commit=False) + total_form = formset.data['form-TOTAL_FORMS'] + + # Identify remove form + if int(total_form) < q_id.count(): + # Get the remained form + for count in range(q_id.count()): + try: + data_id.append( int(formset.data[f'form-{count}-id']) ) + except MultiValueDictKeyError as e: + print(f"data id variable not exists: {e}") + # Delete item in the database + for form_id in formset_id: + if form_id not in data_id: + item = get_object_or_404(Item, pk=form_id) + item.delete() + + # save item + for count,item in enumerate(items): + item.id = item_id+count + item.owner = self.request.user + item.invoice = invoice + item.save() + messages.success(self.request, 'Invoice is successfully Updated') + return redirect('invoices') + else: + invoices = Invoice.objects.filter(company=self.request.user.company, + ).order_by('-date_updated') + context['invoices'] = invoices + context['invoice_form'] = invoice_form + context['invoice_form'].fields['client'].queryset = Client.objects.filter( + company=self.request.user.company, + archive=False + ).order_by('-date_updated') + context['formset'] = formset + context['client_form'] = ClientForm(self.request.POST) + return render(self.request, self.template_name, context) + return render(self.request, self.template_name, context=context) + class InvoiceAjaxView(UserIsOwnerMixin, View): """View invoice information """ - def get(self, *args, **kwargs): """Display invoice details """ @@ -225,81 +307,6 @@ def get(self, *args, **kwargs): return JsonResponse(data, safe = False, status=200) - -class InvoiceAddView(LoginRequiredMixin,TemplateView): - """Adding invoice - """ - template_name = 'invoices/update_invoice.html' - - def get(self, *args, **kwargs): - """Display invoice form - """ - context = {} - context['invoice_form'] = InvoiceForm() - context['invoice_form'].fields['client'].queryset = Client.objects.filter( - company=self.request.user.company - ) - return render(self.request, self.template_name, context) - - def post(self, *args, **kwargs): - """Get filled invoice form and create - """ - invoice_form = InvoiceForm(self.request.POST, company=self.request.user.company) - if invoice_form.is_valid() : - invoice = invoice_form.save(commit=False) - invoice.owner = self.request.user - invoice.company = self.request.user.company - invoice.save() - messages.success(self.request, 'Invoice is successfully Added') - return redirect('invoices') - else: - context = {} - context['invoice_form'] = invoice_form - context['invoice_form'].fields['client'].queryset = Client.objects.filter( - company=self.request.user.company - ) - return render(self.request, self.template_name, context) - - - -class InvoiceEditView(UserIsOwnerMixin,TemplateView): - """Editing invoice - """ - template_name = 'invoices/update_invoice.html' - - def get(self, *args, **kwargs): - """Display invoice form - """ - invoice = get_object_or_404(Invoice, pk=kwargs['invoice_id']) - context = {} - context['invoice_form'] = InvoiceForm(instance=invoice) - context['invoice_form'].fields['client'].queryset = Client.objects.filter( - company=self.request.user.company - ) - return render(self.request, self.template_name, context) - - def post(self, *args, **kwargs): - """Get filled invoice form and create invoice - """ - invoice = get_object_or_404(Invoice, pk=kwargs['invoice_id']) - invoice_form = InvoiceForm(self.request.POST, - instance=invoice, - company=self.request.user.company - ) - if invoice_form.is_valid() : - invoice_form.save() - messages.success(self.request, 'Invoice is successfully updated') - return redirect('invoices') - else: - context = {} - context['invoice_form'] = InvoiceForm(self.request.POST) - context['invoice_form'].fields['client'].queryset = Client.objects.filter( - company=self.request.user.company - ) - return render(self.request, self.template_name, context) - - - class InvoiceDeleteView(UserIsOwnerMixin,TemplateView): """Delete invoice """ @@ -312,7 +319,6 @@ def get(self, *args, **kwargs): return redirect('invoices') - class PdfPreview(UserIsOwnerMixin, PdfMixin, View): """ Pdf preview """ @@ -327,7 +333,6 @@ def get(self, *args, **kwargs): return HttpResponse(pdf, content_type='application/pdf') - class InvoiceEmailView(UserIsOwnerMixin, PdfMixin, TemplateView): """Email an invoice """ @@ -376,9 +381,4 @@ def post(self, *argrs, **kwargs): context['email_form'] = email_form context['company_email'] = invoice.owner.email context['send_email'] = invoice.client.email - return render(self.request, self.template_name, context) - - - - - + return render(self.request, self.template_name, context) \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index dd38a91..72ec97b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,7 @@ {% load staticfiles user_tag %} + Invoice @@ -8,18 +9,20 @@ - + + - +
+ {% if request.user.is_authenticated %} +
+ {% block content_auth %} {% endblock %} +
+ {% endif %} {% if not request.user.is_authenticated %} +
+ {% block content_not_auth %} {% endblock %} +
+ {% endif %} +
- - - - - + + + + - - - - -{% block js %} +{% block js %} {% endblock %} - \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index d5040b9..fa85786 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,14 +2,10 @@ {% load widget_tweaks %} {% load client_tag %} - {% block content_not_auth %} -

Welcome Page


+

Welcome Page


{% endblock %} - - - {% block content_auth %} {% if messages %}
@@ -22,7 +18,6 @@
{% endif %} -

My invoices

@@ -40,12 +35,10 @@

My invoices

- - {% for invoice in invoices %}
  • - +
       {{ invoice.client.client_company|title }} | diff --git a/templates/invoices/all_invoice.html b/templates/invoices/all_invoice.html index b969968..8ccc825 100644 --- a/templates/invoices/all_invoice.html +++ b/templates/invoices/all_invoice.html @@ -1,50 +1,58 @@ -{% extends 'base.html' %} -{% load widget_tweaks %} -{% block content_auth %} +{% extends 'base.html' %} +{% load staticfiles widget_tweaks %} +{% block content_auth %} {% if messages %} {% endif %} +
    -

    Invoice

    - {% if not invoices %} - No invoices yet - {% endif %} - {% for invoice in invoices %} -
    -
    - -
    -
    -
    {{ invoice.client.client_company|title }}
    -
    {{ invoice.client.get_prefix|upper }}: {{ invoice }}
    -
    {{ invoice.due_date|date:"M d, Y" }}
    -
    +
    +

    Invoice

    + {% if not invoices %} + No invoices yet + {% endif %} + + {% for invoice in invoices %} +
    +
    +
    {{ invoice.client.client_company|title }}
    +
    {{ invoice.client.get_prefix|upper }}: {{ invoice }}
    +
    {{ invoice.due_date|date:"M d, Y" }}
    +
    {% if invoice.status == 'sent' %} - |{{ invoice.status|title }} + |{{ invoice.status|title }} {% elif invoice.status == 'draft' %} - |{{ invoice.status|title }} + |{{ invoice.status|title }} {% endif %} -
    +
    +
    + {% endfor %}
    - {% endfor %} -
    -
    -