barbacompta/eo_gestion/eo_banque/templatetags/eo_banque.py

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}