def get_context_data(self, **kwargs): context = super(InvoiceEdit, self).get_context_data(**kwargs) invoice_form = InvoiceForm(instance=self.object) context.update({ 'invoice_form': invoice_form, }) return context
def post(self, request, **kwargs): pk = kwargs.get(self.pk_url_kwarg) invoice = get_object_or_404(EntryGroup, pk=pk) self.object = invoice initial = { 'project': invoice.project, 'user': request.user, 'from_date': invoice.start, 'to_date': invoice.end, } invoice_form = InvoiceForm(request.POST, initial=initial, instance=invoice) if invoice_form.is_valid(): invoice_form.save() return HttpResponseRedirect(reverse('view_invoice', kwargs=kwargs)) else: context = super(InvoiceEdit, self).get_context_data(**kwargs) context.update({ 'invoice_form': invoice_form, }) return self.render_to_response(context)
def create_invoice(request): pk = request.GET.get('project', None) to_date = request.GET.get('to_date', None) if not (pk and to_date): raise Http404 from_date = request.GET.get('from_date', None) if not request.user.has_perm('crm.generate_project_invoice'): return HttpResponseForbidden('Forbidden') try: to_date = utils.add_timezone( datetime.datetime.strptime(to_date, '%Y-%m-%d')) if from_date: from_date = utils.add_timezone( datetime.datetime.strptime(from_date, '%Y-%m-%d')) except (ValueError, OverflowError): raise Http404 project = get_object_or_404(Project, pk=pk) initial = { 'project': project, 'user': request.user, 'from_date': from_date, 'to_date': to_date, } entries_query = { 'status': Entry.APPROVED, 'end_time__lt': to_date + relativedelta(days=1), 'project__id': project.id } if from_date: entries_query.update({'end_time__gte': from_date}) invoice_form = InvoiceForm(request.POST or None, initial=initial) if request.POST and invoice_form.is_valid(): entries = Entry.no_join.filter(**entries_query) if entries.exists(): # LOCK the entries until our transaction completes - nobody # else will be able to lock or change them - see # https://docs.djangoproject.com/en/1.4/ref/models/querysets/#select-for-update # (This feature requires Django 1.4.) # If more than one request is trying to create an invoice from # these same entries, then the second one to get to this line will # throw a DatabaseError. That can happen if someone double-clicks # the Create Invoice button. try: entries.select_for_update(nowait=True) except DatabaseError: # Whoops, we lost the race messages.add_message(request, messages.ERROR, "Lock error trying to get entries") else: # We got the lock, we can carry on invoice = invoice_form.save() entries.update(status=invoice.status, entry_group=invoice) messages.add_message(request, messages.INFO, "Invoice created") return HttpResponseRedirect( reverse('view_invoice', args=[invoice.pk])) else: messages.add_message(request, messages.ERROR, "No entries for invoice") else: entries = Entry.objects.filter(**entries_query) entries = entries.order_by('start_time') if not entries: raise Http404 billable_entries = entries.filter(activity__billable=True) \ .select_related() nonbillable_entries = entries.filter(activity__billable=False) \ .select_related() return render( request, 'timepiece/invoice/create.html', { 'invoice_form': invoice_form, 'billable_entries': billable_entries, 'nonbillable_entries': nonbillable_entries, 'project': project, 'billable_totals': HourGroup.objects.summaries(billable_entries), 'nonbillable_totals': HourGroup.objects.summaries(nonbillable_entries), 'from_date': from_date, 'to_date': to_date, })
def create_invoice(request): pk = request.GET.get('project', None) to_date = request.GET.get('to_date', None) if not (pk and to_date): raise Http404 from_date = request.GET.get('from_date', None) if not request.user.has_perm('crm.generate_project_invoice'): return HttpResponseForbidden('Forbidden') try: to_date = utils.add_timezone( datetime.datetime.strptime(to_date, '%Y-%m-%d')) if from_date: from_date = utils.add_timezone( datetime.datetime.strptime(from_date, '%Y-%m-%d')) except (ValueError, OverflowError): raise Http404 project = get_object_or_404(Project, pk=pk) initial = { 'project': project, 'user': request.user, 'from_date': from_date, 'to_date': to_date, } entries_query = { 'status': Entry.APPROVED, 'end_time__lt': to_date + relativedelta(days=1), 'project__id': project.id } if from_date: entries_query.update({'end_time__gte': from_date}) invoice_form = InvoiceForm(request.POST or None, initial=initial) if request.POST and invoice_form.is_valid(): entries = Entry.no_join.filter(**entries_query) if entries.exists(): # LOCK the entries until our transaction completes - nobody # else will be able to lock or change them - see # https://docs.djangoproject.com/en/1.4/ref/models/querysets/#select-for-update # (This feature requires Django 1.4.) # If more than one request is trying to create an invoice from # these same entries, then the second one to get to this line will # throw a DatabaseError. That can happen if someone double-clicks # the Create Invoice button. try: entries.select_for_update(nowait=True) except DatabaseError: # Whoops, we lost the race messages.add_message(request, messages.ERROR, "Lock error trying to get entries") else: # We got the lock, we can carry on invoice = invoice_form.save() entries.update(status=invoice.status, entry_group=invoice) messages.add_message(request, messages.INFO, "Invoice created") return HttpResponseRedirect(reverse('view_invoice', args=[invoice.pk])) else: messages.add_message(request, messages.ERROR, "No entries for invoice") else: entries = Entry.objects.filter(**entries_query) entries = entries.order_by('start_time') if not entries: raise Http404 billable_entries = entries.filter(activity__billable=True) \ .select_related() nonbillable_entries = entries.filter(activity__billable=False) \ .select_related() return render(request, 'timepiece/invoice/create.html', { 'invoice_form': invoice_form, 'billable_entries': billable_entries, 'nonbillable_entries': nonbillable_entries, 'project': project, 'billable_totals': HourGroup.objects .summaries(billable_entries), 'nonbillable_totals': HourGroup.objects .summaries(nonbillable_entries), 'from_date': from_date, 'to_date': to_date, })