#NEWLINE# @ login_required #NEWLINE# @ transaction . atomic #NEWLINE# def create_invoice( request ) : #NEWLINE# #INDENT# pk = request . GET . get ( 'project' , None ) #NEWLINE# to_date = request . GET . get ( 'to_date' , None ) #NEWLINE# if ( not ( pk and to_date ) ) : #NEWLINE# #INDENT# raise Http404 #NEWLINE# #UNINDENT# from_date = request . GET . get ( 'from_date' , None ) #NEWLINE# if ( not request . user . has_perm ( 'crm.generate_project_invoice' ) ) : #NEWLINE# #INDENT# return HttpResponseForbidden ( 'Forbidden' ) #NEWLINE# #UNINDENT# try : #NEWLINE# #INDENT# to_date = utils . add_timezone ( datetime . datetime . strptime ( invoice_form , '%Y-%m-%d' ) ) #NEWLINE# if from_date : #NEWLINE# #INDENT# from_date = utils . add_timezone ( datetime . datetime . strptime ( from_date , '%Y-%m-%d' ) ) #NEWLINE# #UNINDENT# #UNINDENT# except ( ValueError , OverflowError ) : #NEWLINE# #INDENT# raise Http404 #NEWLINE# #UNINDENT# project = get_object_or_404 ( Project , pk = pk ) #NEWLINE# initial = { #NEWLINE# #INDENT# 'project' : project , #NEWLINE# 'user' : request . user , #NEWLINE# 'from_date' : from_date , #NEWLINE# 'to_date' : to_date , #NEWLINE# #UNINDENT# } #NEWLINE# entries_query = { #NEWLINE# #INDENT# 'status' : Entry . APPROVED , #NEWLINE# 'end_time__lt' : ( to_date + relativedelta ( days = 1 ) ) , #NEWLINE# 'project__id' : project . id , #NEWLINE# #UNINDENT# } #NEWLINE# if from_date : #NEWLINE# #INDENT# entries_query . update ( { #NEWLINE# #INDENT# 'end_time__gte' : from_date , #NEWLINE# #UNINDENT# } ) #NEWLINE# #UNINDENT# invoice_form = InvoiceForm ( ( request . POST or None ) , initial = initial ) #NEWLINE# if ( request . POST and invoice_form . is_valid ( ) ) : #NEWLINE# #INDENT# entries = Entry . no_join . filter ( ** entries_query ) #NEWLINE# if entries . exists ( ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# entries . select_for_update ( nowait = True ) #NEWLINE# #UNINDENT# except DatabaseError : #NEWLINE# #INDENT# messages . add_message ( request , messages . ERROR , 'Lock error trying to get entries' ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# invoice = invoice_form . save ( ) #NEWLINE# Entry . no_join . filter ( pk__in = entries ) . update ( status = invoice . status , entry_group = invoice ) #NEWLINE# messages . add_message ( request , messages . INFO , 'Invoice created' ) #NEWLINE# return HttpResponseRedirect ( reverse ( 'view_invoice' , args = [ invoice . pk ] ) ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# messages . add_message ( request , messages . ERROR , 'No entries for invoice' ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# entries = Entry . objects . filter ( ** entries_query ) #NEWLINE# entries = entries . order_by ( 'start_time' ) #NEWLINE# if ( not entries ) : #NEWLINE# #INDENT# raise Http404 #NEWLINE# #UNINDENT# #UNINDENT# billable_entries = entries . filter ( activity__billable = True ) . select_related ( ) #NEWLINE# nonbillable_entries = entries . filter ( activity__billable = False ) . select_related ( ) #NEWLINE# return render ( request , 'timepiece/invoice/create.html' , { #NEWLINE# #INDENT# 'invoice_form' : invoice_form , #NEWLINE# 'billable_entries' : billable_entries , #NEWLINE# 'nonbillable_entries' : nonbillable_entries , #NEWLINE# 'project' : project , #NEWLINE# 'billable_totals' : HourGroup . objects . summaries ( billable_entries ) , #NEWLINE# 'nonbillable_totals' : HourGroup . objects . summaries ( nonbillable_entries ) , #NEWLINE# 'from_date' : from_date , #NEWLINE# 'to_date' : to_date , #NEWLINE# #UNINDENT# } )