Added support for ProForma bills
This commit is contained in:
parent
287f03ce19
commit
f6045869ac
|
@ -13,8 +13,8 @@ from orchestra.apps.accounts.admin import AccountAdminMixin
|
||||||
from . import settings
|
from . import settings
|
||||||
from .actions import download_bills, view_bill, close_bills, send_bills
|
from .actions import download_bills, view_bill, close_bills, send_bills
|
||||||
from .filters import BillTypeListFilter
|
from .filters import BillTypeListFilter
|
||||||
from .models import (Bill, Invoice, AmendmentInvoice, Fee, AmendmentFee, Budget,
|
from .models import (Bill, Invoice, AmendmentInvoice, Fee, AmendmentFee, ProForma,
|
||||||
BillLine, BudgetLine)
|
BillLine)
|
||||||
|
|
||||||
|
|
||||||
class BillLineInline(admin.TabularInline):
|
class BillLineInline(admin.TabularInline):
|
||||||
|
@ -46,11 +46,6 @@ class BillLineInline(admin.TabularInline):
|
||||||
return super(BillLineInline, self).formfield_for_dbfield(db_field, **kwargs)
|
return super(BillLineInline, self).formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BudgetLineInline(BillLineInline):
|
|
||||||
model = Budget
|
|
||||||
fields = ('description', 'rate', 'amount', 'tax', 'total')
|
|
||||||
|
|
||||||
|
|
||||||
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'number', 'status', 'type_link', 'account_link', 'created_on_display',
|
'number', 'status', 'type_link', 'account_link', 'created_on_display',
|
||||||
|
@ -77,8 +72,8 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
created_on_display = admin_date('created_on')
|
created_on_display = admin_date('created_on')
|
||||||
|
|
||||||
def num_lines(self, bill):
|
def num_lines(self, bill):
|
||||||
return bill.billlines__count
|
return bill.lines__count
|
||||||
num_lines.admin_order_field = 'billlines__count'
|
num_lines.admin_order_field = 'lines__count'
|
||||||
num_lines.short_description = _("lines")
|
num_lines.short_description = _("lines")
|
||||||
|
|
||||||
def display_total(self, bill):
|
def display_total(self, bill):
|
||||||
|
@ -120,8 +115,6 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return [action for action in actions if action.__name__ not in discard]
|
return [action for action in actions if action.__name__ not in discard]
|
||||||
|
|
||||||
def get_inline_instances(self, request, obj=None):
|
def get_inline_instances(self, request, obj=None):
|
||||||
if self.model is Budget:
|
|
||||||
self.inlines = [BudgetLineInline]
|
|
||||||
# Make parent object available for inline.has_add_permission()
|
# Make parent object available for inline.has_add_permission()
|
||||||
request.__bill__ = obj
|
request.__bill__ = obj
|
||||||
return super(BillAdmin, self).get_inline_instances(request, obj=obj)
|
return super(BillAdmin, self).get_inline_instances(request, obj=obj)
|
||||||
|
@ -136,8 +129,8 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(BillAdmin, self).get_queryset(request)
|
qs = super(BillAdmin, self).get_queryset(request)
|
||||||
qs = qs.annotate(models.Count('billlines'))
|
qs = qs.annotate(models.Count('lines'))
|
||||||
qs = qs.prefetch_related('billlines', 'billlines__sublines')
|
qs = qs.prefetch_related('lines', 'lines__sublines')
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
# def change_view(self, request, object_id, **kwargs):
|
# def change_view(self, request, object_id, **kwargs):
|
||||||
|
@ -154,4 +147,4 @@ admin.site.register(Invoice, BillAdmin)
|
||||||
admin.site.register(AmendmentInvoice, BillAdmin)
|
admin.site.register(AmendmentInvoice, BillAdmin)
|
||||||
admin.site.register(Fee, BillAdmin)
|
admin.site.register(Fee, BillAdmin)
|
||||||
admin.site.register(AmendmentFee, BillAdmin)
|
admin.site.register(AmendmentFee, BillAdmin)
|
||||||
admin.site.register(Budget, BillAdmin)
|
admin.site.register(ProForma, BillAdmin)
|
||||||
|
|
|
@ -19,7 +19,7 @@ class BillTypeListFilter(SimpleListFilter):
|
||||||
('amendmentinvoice', _("Amendment invoice")),
|
('amendmentinvoice', _("Amendment invoice")),
|
||||||
('fee', _("Fee")),
|
('fee', _("Fee")),
|
||||||
('fee', _("Amendment fee")),
|
('fee', _("Amendment fee")),
|
||||||
('budget', _("Budget")),
|
('proforma', _("Pro-forma")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
19
orchestra/apps/bills/migrations/0004_auto_20140911_1234.py
Normal file
19
orchestra/apps/bills/migrations/0004_auto_20140911_1234.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0003_bill_total'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bill',
|
||||||
|
name='total',
|
||||||
|
field=models.DecimalField(default=0, max_digits=12, decimal_places=2),
|
||||||
|
),
|
||||||
|
]
|
19
orchestra/apps/bills/migrations/0005_auto_20140911_1234.py
Normal file
19
orchestra/apps/bills/migrations/0005_auto_20140911_1234.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0004_auto_20140911_1234'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='billsubline',
|
||||||
|
old_name='bill_line',
|
||||||
|
new_name='line',
|
||||||
|
),
|
||||||
|
]
|
59
orchestra/apps/bills/migrations/0006_auto_20140911_1238.py
Normal file
59
orchestra/apps/bills/migrations/0006_auto_20140911_1238.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0005_auto_20140911_1234'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='budgetline',
|
||||||
|
name='bill',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='BudgetLine',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='Budget',
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ProForma',
|
||||||
|
fields=[
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'proxy': True,
|
||||||
|
},
|
||||||
|
bases=('bills.bill',),
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='billline',
|
||||||
|
name='auto',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='billline',
|
||||||
|
name='order_billed_until',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='billline',
|
||||||
|
name='order_id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='billline',
|
||||||
|
name='order_last_bill_date',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bill',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(max_length=16, verbose_name='type', choices=[(b'INVOICE', 'Invoice'), (b'AMENDMENTINVOICE', 'Amendment invoice'), (b'FEE', 'Fee'), (b'AMENDMENTFEE', 'Amendment Fee'), (b'PROFORMA', 'Pro forma')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='billline',
|
||||||
|
name='bill',
|
||||||
|
field=models.ForeignKey(related_name=b'lines', verbose_name='bill', to='bills.Bill'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -43,7 +43,7 @@ class Bill(models.Model):
|
||||||
('AMENDMENTINVOICE', _("Amendment invoice")),
|
('AMENDMENTINVOICE', _("Amendment invoice")),
|
||||||
('FEE', _("Fee")),
|
('FEE', _("Fee")),
|
||||||
('AMENDMENTFEE', _("Amendment Fee")),
|
('AMENDMENTFEE', _("Amendment Fee")),
|
||||||
('BUDGET', _("Budget")),
|
('PROFORMA', _("Pro forma")),
|
||||||
)
|
)
|
||||||
|
|
||||||
number = models.CharField(_("number"), max_length=16, unique=True,
|
number = models.CharField(_("number"), max_length=16, unique=True,
|
||||||
|
@ -74,10 +74,6 @@ class Bill(models.Model):
|
||||||
def buyer(self):
|
def buyer(self):
|
||||||
return self.account.invoicecontact
|
return self.account.invoicecontact
|
||||||
|
|
||||||
@property
|
|
||||||
def lines(self):
|
|
||||||
return self.billlines
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_class_type(cls):
|
def get_class_type(cls):
|
||||||
return cls.__name__.upper()
|
return cls.__name__.upper()
|
||||||
|
@ -210,28 +206,22 @@ class AmendmentFee(Bill):
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
class Budget(Bill):
|
class ProForma(Bill):
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
@property
|
|
||||||
def lines(self):
|
|
||||||
return self.budgetlines
|
|
||||||
|
|
||||||
|
class BillLine(models.Model):
|
||||||
class BaseBillLine(models.Model):
|
|
||||||
""" Base model for bill item representation """
|
""" Base model for bill item representation """
|
||||||
bill = models.ForeignKey(Bill, verbose_name=_("bill"),
|
bill = models.ForeignKey(Bill, verbose_name=_("bill"), related_name='lines')
|
||||||
related_name='%(class)ss')
|
|
||||||
description = models.CharField(_("description"), max_length=256)
|
description = models.CharField(_("description"), max_length=256)
|
||||||
rate = models.DecimalField(_("rate"), blank=True, null=True,
|
rate = models.DecimalField(_("rate"), blank=True, null=True,
|
||||||
max_digits=12, decimal_places=2)
|
max_digits=12, decimal_places=2)
|
||||||
amount = models.DecimalField(_("amount"), max_digits=12, decimal_places=2)
|
amount = models.DecimalField(_("amount"), max_digits=12, decimal_places=2)
|
||||||
total = models.DecimalField(_("total"), max_digits=12, decimal_places=2)
|
total = models.DecimalField(_("total"), max_digits=12, decimal_places=2)
|
||||||
tax = models.PositiveIntegerField(_("tax"))
|
tax = models.PositiveIntegerField(_("tax"))
|
||||||
|
amended_line = models.ForeignKey('self', verbose_name=_("amended line"),
|
||||||
class Meta:
|
related_name='amendment_lines', null=True, blank=True)
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return "#%i" % self.number
|
return "#%i" % self.number
|
||||||
|
@ -241,19 +231,6 @@ class BaseBillLine(models.Model):
|
||||||
lines = type(self).objects.filter(bill=self.bill_id)
|
lines = type(self).objects.filter(bill=self.bill_id)
|
||||||
return lines.filter(id__lte=self.id).order_by('id').count()
|
return lines.filter(id__lte=self.id).order_by('id').count()
|
||||||
|
|
||||||
|
|
||||||
class BudgetLine(BaseBillLine):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BillLine(BaseBillLine):
|
|
||||||
order_id = models.PositiveIntegerField(blank=True, null=True)
|
|
||||||
order_last_bill_date = models.DateTimeField(null=True)
|
|
||||||
order_billed_until = models.DateTimeField(null=True)
|
|
||||||
auto = models.BooleanField(default=False)
|
|
||||||
amended_line = models.ForeignKey('self', verbose_name=_("amended line"),
|
|
||||||
related_name='amendment_lines', null=True, blank=True)
|
|
||||||
|
|
||||||
def get_total(self):
|
def get_total(self):
|
||||||
""" Computes subline discounts """
|
""" Computes subline discounts """
|
||||||
subtotal = self.total
|
subtotal = self.total
|
||||||
|
@ -271,7 +248,7 @@ class BillLine(BaseBillLine):
|
||||||
|
|
||||||
class BillSubline(models.Model):
|
class BillSubline(models.Model):
|
||||||
""" Subline used for describing an item discount """
|
""" Subline used for describing an item discount """
|
||||||
bill_line = models.ForeignKey(BillLine, verbose_name=_("bill line"),
|
line = models.ForeignKey(BillLine, verbose_name=_("bill line"),
|
||||||
related_name='sublines')
|
related_name='sublines')
|
||||||
description = models.CharField(_("description"), max_length=256)
|
description = models.CharField(_("description"), max_length=256)
|
||||||
total = models.DecimalField(max_digits=12, decimal_places=2)
|
total = models.DecimalField(max_digits=12, decimal_places=2)
|
||||||
|
@ -284,4 +261,5 @@ class BillSubline(models.Model):
|
||||||
self.line.bill.total = self.line.bill.get_total()
|
self.line.bill.total = self.line.bill.get_total()
|
||||||
self.line.bill.save()
|
self.line.bill.save()
|
||||||
|
|
||||||
|
|
||||||
accounts.register(Bill)
|
accounts.register(Bill)
|
||||||
|
|
|
@ -11,13 +11,14 @@ BILLS_FEE_NUMBER_PREFIX = getattr(settings, 'BILLS_FEE_NUMBER_PREFIX', 'F')
|
||||||
|
|
||||||
BILLS_AMENDMENT_FEE_NUMBER_PREFIX = getattr(settings, 'BILLS_AMENDMENT_FEE_NUMBER_PREFIX', 'B')
|
BILLS_AMENDMENT_FEE_NUMBER_PREFIX = getattr(settings, 'BILLS_AMENDMENT_FEE_NUMBER_PREFIX', 'B')
|
||||||
|
|
||||||
BILLS_BUDGET_NUMBER_PREFIX = getattr(settings, 'BILLS_BUDGET_NUMBER_PREFIX', 'Q')
|
BILLS_PROFORMA_NUMBER_PREFIX = getattr(settings, 'BILLS_PROFORMA_NUMBER_PREFIX', 'P')
|
||||||
|
|
||||||
|
|
||||||
BILLS_DEFAULT_TEMPLATE = getattr(settings, 'BILLS_DEFAULT_TEMPLATE', 'bills/microspective.html')
|
BILLS_DEFAULT_TEMPLATE = getattr(settings, 'BILLS_DEFAULT_TEMPLATE', 'bills/microspective.html')
|
||||||
|
|
||||||
BILLS_FEE_TEMPLATE = getattr(settings, 'BILLS_FEE_TEMPLATE', 'bills/microspective-fee.html')
|
BILLS_FEE_TEMPLATE = getattr(settings, 'BILLS_FEE_TEMPLATE', 'bills/microspective-fee.html')
|
||||||
|
|
||||||
|
BILLS_PROFORMA_TEMPLATE = getattr(settings, 'BILLS_PROFORMA_TEMPLATE', 'bills/microspective-proforma.html')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends 'bills/microspective.html' %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<style type="text/css">
|
||||||
|
{% with color="#2C5899" %}
|
||||||
|
{% include 'bills/microspective.css' %}
|
||||||
|
{% endwith %}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
|
@ -14,7 +14,7 @@
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<div id="logo">
|
<div id="logo">
|
||||||
{% block logo %}
|
{% block logo %}
|
||||||
<div style="border-bottom:5px solid grey; color:grey; font-size:30; margin-right: 20px;">
|
<div style="border-bottom:5px solid {{ color }}; color:{{ color }}; font-size:30; margin-right: 20px;">
|
||||||
YOUR<br>
|
YOUR<br>
|
||||||
LOGO<br>
|
LOGO<br>
|
||||||
HERE<br>
|
HERE<br>
|
||||||
|
|
|
@ -37,9 +37,13 @@ class BillSelectedOrders(object):
|
||||||
self.options = dict(
|
self.options = dict(
|
||||||
billing_point=form.cleaned_data['billing_point'],
|
billing_point=form.cleaned_data['billing_point'],
|
||||||
fixed_point=form.cleaned_data['fixed_point'],
|
fixed_point=form.cleaned_data['fixed_point'],
|
||||||
|
is_proforma=form.cleaned_data['is_proforma'],
|
||||||
create_new_open=form.cleaned_data['create_new_open'],
|
create_new_open=form.cleaned_data['create_new_open'],
|
||||||
)
|
)
|
||||||
|
if int(request.POST.get('step')) != 3:
|
||||||
return self.select_related(request)
|
return self.select_related(request)
|
||||||
|
else:
|
||||||
|
return self.confirmation(request)
|
||||||
self.context.update({
|
self.context.update({
|
||||||
'title': _("Options for billing selected orders, step 1 / 3"),
|
'title': _("Options for billing selected orders, step 1 / 3"),
|
||||||
'step': 1,
|
'step': 1,
|
||||||
|
@ -55,7 +59,7 @@ class BillSelectedOrders(object):
|
||||||
form = BillSelectRelatedForm(request.POST, initial=self.options)
|
form = BillSelectRelatedForm(request.POST, initial=self.options)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
select_related = form.cleaned_data['selected_related']
|
select_related = form.cleaned_data['selected_related']
|
||||||
self.options['selected_related'] = select_related
|
self.queryset = self.queryset | select_related
|
||||||
return self.confirmation(request)
|
return self.confirmation(request)
|
||||||
self.context.update({
|
self.context.update({
|
||||||
'title': _("Select related order for billing, step 2 / 3"),
|
'title': _("Select related order for billing, step 2 / 3"),
|
||||||
|
@ -89,6 +93,5 @@ class BillSelectedOrders(object):
|
||||||
'step': 3,
|
'step': 3,
|
||||||
'form': form,
|
'form': form,
|
||||||
'bills': bills,
|
'bills': bills,
|
||||||
'selected_related_objects': self.options['selected_related']
|
|
||||||
})
|
})
|
||||||
return render(request, self.template, self.context)
|
return render(request, self.template, self.context)
|
||||||
|
|
|
@ -2,42 +2,44 @@ import datetime
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.apps.bills.models import Invoice, Fee, BillLine, BillSubline
|
from orchestra.apps.bills.models import Invoice, Fee, ProForma, BillLine, BillSubline
|
||||||
|
|
||||||
|
|
||||||
class BillsBackend(object):
|
class BillsBackend(object):
|
||||||
def create_bills(self, account, lines):
|
def create_bills(self, account, lines, **options):
|
||||||
invoice = None
|
bill = None
|
||||||
bills = []
|
bills = []
|
||||||
|
create_new = options.get('create_new_open', False)
|
||||||
|
is_proforma = options.get('is_proforma', False)
|
||||||
for line in lines:
|
for line in lines:
|
||||||
service = line.order.service
|
service = line.order.service
|
||||||
if service.is_fee:
|
# Create bill if needed
|
||||||
fee, __ = Fee.objects.get_or_create(account=account, status=Fee.OPEN)
|
if bill is None or service.is_fee:
|
||||||
storedline = fee.lines.create(
|
if is_proforma:
|
||||||
rate=service.nominal_price,
|
if create_new:
|
||||||
amount=line.size,
|
bill = ProForma.objects.create(account=account)
|
||||||
total=line.subtotal, tax=0,
|
|
||||||
description=self.format_period(line.ini, line.end),
|
|
||||||
)
|
|
||||||
self.create_sublines(storedline, line.discounts)
|
|
||||||
bills.append(fee)
|
|
||||||
else:
|
else:
|
||||||
if invoice is None:
|
bill, __ = ProForma.objects.get_or_create(account=account,
|
||||||
invoice, __ = Invoice.objects.get_or_create(account=account,
|
status=ProForma.OPEN)
|
||||||
|
elif service.is_fee:
|
||||||
|
bill = Fee.objects.create(account=account)
|
||||||
|
else:
|
||||||
|
if create_new:
|
||||||
|
bill = Invoice.objects.create(account=account)
|
||||||
|
else:
|
||||||
|
bill, __ = Invoice.objects.get_or_create(account=account,
|
||||||
status=Invoice.OPEN)
|
status=Invoice.OPEN)
|
||||||
bills.append(invoice)
|
bills.append(bill)
|
||||||
description = line.order.description
|
# Create bill line
|
||||||
if service.billing_period != service.NEVER:
|
billine = bill.lines.create(
|
||||||
description += " %s" % self.format_period(line.ini, line.end)
|
|
||||||
storedline = invoice.lines.create(
|
|
||||||
description=description,
|
|
||||||
rate=service.nominal_price,
|
rate=service.nominal_price,
|
||||||
amount=line.size,
|
amount=line.size,
|
||||||
# TODO rename line.total > subtotal
|
|
||||||
total=line.subtotal,
|
total=line.subtotal,
|
||||||
tax=service.tax,
|
tax=service.tax,
|
||||||
|
description=self.get_line_description(line),
|
||||||
)
|
)
|
||||||
self.create_sublines(storedline, line.discounts)
|
self.create_sublines(billine, line.discounts)
|
||||||
|
print bills
|
||||||
return bills
|
return bills
|
||||||
|
|
||||||
def format_period(self, ini, end):
|
def format_period(self, ini, end):
|
||||||
|
@ -47,6 +49,15 @@ class BillsBackend(object):
|
||||||
return ini
|
return ini
|
||||||
return _("{ini} to {end}").format(ini=ini, end=end)
|
return _("{ini} to {end}").format(ini=ini, end=end)
|
||||||
|
|
||||||
|
def get_line_description(self, line):
|
||||||
|
service = line.order.service
|
||||||
|
if service.is_fee:
|
||||||
|
return self.format_period(line.ini, line.end)
|
||||||
|
else:
|
||||||
|
description = line.order.description
|
||||||
|
if service.billing_period != service.NEVER:
|
||||||
|
description += " %s" % self.format_period(line.ini, line.end)
|
||||||
|
return description
|
||||||
|
|
||||||
def create_sublines(self, line, discounts):
|
def create_sublines(self, line, discounts):
|
||||||
for discount in discounts:
|
for discount in discounts:
|
||||||
|
|
|
@ -18,11 +18,15 @@ class BillSelectedOptionsForm(AdminFormMixin, forms.Form):
|
||||||
label=_("fixed point"),
|
label=_("fixed point"),
|
||||||
help_text=_("Deisgnates whether you want the billing point to be an "
|
help_text=_("Deisgnates whether you want the billing point to be an "
|
||||||
"exact date, or adapt it to the billing period."))
|
"exact date, or adapt it to the billing period."))
|
||||||
|
is_proforma = forms.BooleanField(initial=False, required=False,
|
||||||
|
label=_("Pro-forma, billing simulation"),
|
||||||
|
help_text=_("O."))
|
||||||
create_new_open = forms.BooleanField(initial=False, required=False,
|
create_new_open = forms.BooleanField(initial=False, required=False,
|
||||||
label=_("Create a new open bill"),
|
label=_("Create a new open bill"),
|
||||||
help_text=_("Deisgnates whether you want to put this orders on a new "
|
help_text=_("Deisgnates whether you want to put this orders on a new "
|
||||||
"open bill, or allow to reuse an existing one."))
|
"open bill, or allow to reuse an existing one."))
|
||||||
|
|
||||||
|
|
||||||
def selected_related_choices(queryset):
|
def selected_related_choices(queryset):
|
||||||
for order in queryset:
|
for order in queryset:
|
||||||
verbose = '<a href="{order_url}">{description}</a> '
|
verbose = '<a href="{order_url}">{description}</a> '
|
||||||
|
@ -40,6 +44,7 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form):
|
||||||
required=False)
|
required=False)
|
||||||
billing_point = forms.DateField(widget=forms.HiddenInput())
|
billing_point = forms.DateField(widget=forms.HiddenInput())
|
||||||
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
|
is_proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -51,8 +56,7 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form):
|
||||||
|
|
||||||
|
|
||||||
class BillSelectConfirmationForm(AdminFormMixin, forms.Form):
|
class BillSelectConfirmationForm(AdminFormMixin, forms.Form):
|
||||||
# selected_related = forms.ModelMultipleChoiceField(queryset=Order.objects.none(),
|
|
||||||
# widget=forms.HiddenInput(), required=False)
|
|
||||||
billing_point = forms.DateField(widget=forms.HiddenInput())
|
billing_point = forms.DateField(widget=forms.HiddenInput())
|
||||||
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
|
is_proforma = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
|
||||||
|
|
|
@ -316,7 +316,7 @@ class OrderQuerySet(models.QuerySet):
|
||||||
lines = service.handler.generate_bill_lines(orders, **options)
|
lines = service.handler.generate_bill_lines(orders, **options)
|
||||||
bill_lines.extend(lines)
|
bill_lines.extend(lines)
|
||||||
if commit:
|
if commit:
|
||||||
bills += bill_backend.create_bills(account, bill_lines)
|
bills += bill_backend.create_bills(account, bill_lines, **options)
|
||||||
else:
|
else:
|
||||||
bills += [(account, bill_lines)]
|
bills += [(account, bill_lines)]
|
||||||
return bills
|
return bills
|
||||||
|
|
|
@ -60,13 +60,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{{ form.as_table }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ form.as_admin }}
|
{{ form.as_admin }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% for obj in selected_related_objects %}
|
|
||||||
<input type="hidden" name="selected_related" value="{{ obj.pk|unlocalize }}" />
|
|
||||||
{% endfor %}
|
|
||||||
{% for obj in queryset %}
|
{% for obj in queryset %}
|
||||||
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
Loading…
Reference in a new issue