149 lines
5.4 KiB
Python
149 lines
5.4 KiB
Python
# barbacompta - invoicing for dummies
|
|
# Copyright (C) 2019-2020 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from datetime import date, timedelta
|
|
from decimal import Decimal
|
|
|
|
from django import template
|
|
from django.db.models import Sum
|
|
from django.urls import reverse
|
|
|
|
from ...decorators import cache
|
|
from ..models import LigneBanquePop, solde
|
|
|
|
register = template.Library()
|
|
|
|
|
|
def month_before(date):
|
|
if date.month == 1:
|
|
return date.replace(year=date.year - 1, month=12)
|
|
else:
|
|
return date.replace(month=date.month - 1)
|
|
|
|
|
|
@register.inclusion_tag("eo_banque/finances.html")
|
|
@cache
|
|
def finances(month=3):
|
|
dates = [date.today().replace(day=1)]
|
|
for i in range(1, month):
|
|
dates.append(month_before(dates[-1]))
|
|
e = []
|
|
lignes = LigneBanquePop.objects.filter(date_valeur__gte=min(dates), montant__gt=0)
|
|
for d in dates:
|
|
link = reverse('admin:eo_banque_lignebanquepop_changelist')
|
|
lien_date = link + '?date_valeur__year=%s&date_valeur__month=%s' % (d.year, d.month)
|
|
lien_encaissement = link + '?date_valeur__year=%s&date_valeur__month=%s&montant__gt=0' % (
|
|
d.year,
|
|
d.month,
|
|
)
|
|
# encaissement = LigneBanquePop.objects \
|
|
# .filter(date_valeur__year=d.year,
|
|
# date_valeur__month=d.month,montant__gt=0) \
|
|
# .aggregate(Sum('montant'))['montant__sum'] or Decimal('0.00')
|
|
encaissement = Decimal(
|
|
sum(
|
|
ligne.montant
|
|
for ligne in lignes
|
|
if ligne.date_valeur.year == d.year and ligne.date_valeur.month == d.month
|
|
)
|
|
)
|
|
lien_depense = link + '?date_valeur__year=%s&date_valeur__month=%s&montant__lt=0' % (d.year, d.month)
|
|
|
|
depense = LigneBanquePop.objects.filter(
|
|
date_valeur__year=d.year, date_valeur__month=d.month, montant__lt=0
|
|
).aggregate(Sum('montant'))['montant__sum'] or Decimal('0.00')
|
|
|
|
e.append(
|
|
{
|
|
'date': d,
|
|
'lien_date': lien_date,
|
|
'encaissement': encaissement,
|
|
'lien_encaissement': lien_encaissement,
|
|
'depense': depense,
|
|
'lien_depense': lien_depense,
|
|
'solde': encaissement + depense,
|
|
}
|
|
)
|
|
return {'finances': e, 'solde': solde()}
|
|
|
|
|
|
@register.inclusion_tag('eo_banque/total.html', takes_context=True)
|
|
def total(context):
|
|
qs = context["cl"].get_queryset(context["request"])
|
|
ls = [ligne[0] for ligne in qs.values_list("montant")]
|
|
credit = sum(montant for montant in ls if montant > 0)
|
|
debit = sum(montant for montant in ls if montant < 0)
|
|
total = sum(ls)
|
|
return {'credit': credit, 'debit': debit, 'total': total}
|
|
|
|
|
|
def iso_year_start(iso_year):
|
|
"The gregorian calendar date of the first day of the given ISO year"
|
|
fourth_jan = date(iso_year, 1, 4)
|
|
delta = timedelta(fourth_jan.isoweekday() - 1)
|
|
return fourth_jan - delta
|
|
|
|
|
|
def iso_to_gregorian(iso_year, iso_week, iso_day):
|
|
"Gregorian calendar date for the given ISO year, week and day"
|
|
year_start = iso_year_start(iso_year)
|
|
return year_start + timedelta(iso_day - 1, 0, 0, 0, 0, 0, iso_week - 1)
|
|
|
|
|
|
def days(year, month):
|
|
if month == 12:
|
|
last = date(year + 1, 1, 1) - timedelta(days=1)
|
|
else:
|
|
last = date(year, month + 1, 1) - timedelta(days=1)
|
|
return [date(year, month, i) for i in range(1, last.day + 1)]
|
|
|
|
|
|
def weeks(year, month):
|
|
weeks = [day.isocalendar()[0:2] for day in days(year, month)]
|
|
return sorted(set(weeks))
|
|
|
|
|
|
def week_start_and_end(year, month):
|
|
return [
|
|
(week, iso_to_gregorian(year, week, 1), iso_to_gregorian(year, week, 7))
|
|
for year, week in weeks(year, month)
|
|
]
|
|
|
|
|
|
@register.inclusion_tag("admin/date_hierarchy.html")
|
|
def eo_banque_date_hierarchy(cl):
|
|
if cl.date_hierarchy:
|
|
field_name = cl.date_hierarchy
|
|
year_field = "%s__year" % field_name
|
|
month_field = "%s__month" % field_name
|
|
day_field = "%s__day" % field_name
|
|
field_generic = "%s__" % field_name
|
|
field_gte = "%s__gte" % field_name
|
|
field_lte = "%s__lte" % field_name
|
|
year_lookup = cl.params.get(year_field)
|
|
month_lookup = cl.params.get(month_field)
|
|
day_lookup = cl.params.get(day_field)
|
|
|
|
def link(d):
|
|
return cl.get_query_string(d, [field_generic])
|
|
|
|
if year_lookup and month_lookup and not day_lookup:
|
|
choices = []
|
|
for week, week_day_start, week_day_end in week_start_and_end(int(year_lookup), int(month_lookup)):
|
|
url = link({field_gte: week_day_start.isoformat(), field_lte: week_day_end.isoformat()})
|
|
choices.append({'title': 'Semaine %s' % week, 'link': url})
|
|
return {'show': True, 'choices': choices}
|