implementation de la cotisation

This commit is contained in:
Roven Gabriel 2013-09-11 00:28:40 +02:00
parent 3bb7f266ba
commit f03b3e0104
11 changed files with 518 additions and 37 deletions

View File

@ -7,9 +7,16 @@ room_base_dn = "ou=chambres,"
group_base_dn = "ou=groupes,"
parametres_base_dn = "ou=parametres,"
machine_base_dn = "cn=machines,"
cotisation_member_base_dn = "cn=cotisations,"
ip_reservation_base_dn = "uid=pool_ip," + parametres_base_dn
plugins_base_dn = "uid=plugins," + parametres_base_dn
cotisation_base_dn = "uid=cotisation," + parametres_base_dn
cotisation_annee_base_dn = "uid=annee," + cotisation_base_dn
cotisation_mois_base_dn = "uid=mois," + cotisation_base_dn
extra_base_dn = "uid=paiements-extras," + parametres_base_dn
aurore_dn = "dc=aurore,dc=u-psud,dc=fr"
parametres_aurore_dn = parametres_base_dn + aurore_dn

View File

@ -19,6 +19,8 @@ from operator import itemgetter
from datetime import datetime
import uuid
import re
import ldap
#root = tg.config['application_root_module'].RootController
@ -26,8 +28,6 @@ import re
class EditController(AuthenticatedBaseController):
require_group = groups_enum.admin
""" Controller show qu'on réutilise pour gérer l'affichage """
show = None
""" Controller fils wifi pour gérer le wifi """
wifi = None
@ -42,13 +42,16 @@ class EditController(AuthenticatedBaseController):
add = None
cotisation = None
def __init__(self, new_show):
self.show = new_show
self.wifi = WifiRestController(new_show)
self.machine = MachineController()
self.room = RoomController(new_show)
self.member = MemberModificationController()
self.member = MemberModificationController(new_show)
self.add = MemberAddController()
self.cotisation = CotisationController()
""" Affiche les détails éditables de la chambre """
@ -98,41 +101,87 @@ class MemberAddController(AuthenticatedRestController):
class MemberModificationController(AuthenticatedRestController):
require_group = groups_enum.admin
""" Controller show qu'on réutilise pour gérer l'affichage """
show = None
def __init__(self, new_show):
self.show = new_show
#end def
""" Affiche les détails éditables du membre et de la chambre """
@expose("brie.templates.edit.member")
def get(self, residence, uid):
residence_dn = Residences.get_dn_by_name(self.user, residence)
residence_dn = Residences.get_dn_by_name(self.user, residence)
if residence_dn is None:
raise Exception("unknown residence")
#end if
member = Member.get_by_uid(self.user, residence_dn, uid)
if member is None:
return self.error_no_entry()
self.show.user = self.user
show_values = self.show.member(residence, uid)
room = Room.get_by_member_dn(self.user, residence_dn, member.dn)
machines = Machine.get_machine_tuples_of_member(self.user, member.dn)
groups = Groupes.get_by_user_dn(self.user, residence_dn, member.dn)
rooms = Room.get_rooms(self.user, residence_dn)
if rooms is None:
raise Exception("unable to retrieve rooms")
#end if
rooms = sorted(rooms, key=lambda t:t.cn.first())
return {
"residence" : residence,
"user" : self.user,
"member_ldap" : member,
"room_ldap" : room,
"machines" : machines,
"groups" : groups,
"rooms" : rooms
}
show_values["rooms"] = rooms
cotisations = show_values["cotisations"]
month_names = [
"Janvier",
"Fevrier",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Aout",
"Septembre",
"Octobre",
"Novembre",
"Decembre"
] # SALE FIXME
# FIXME => mettre dans aurore helper
paid_months = []
already_paid = 0
for cotisation in cotisations:
paid_months = (
paid_months +
[int(month) for month in cotisation.get("x-validMonth").all()]
)
already_paid += int(cotisation.get("x-amountPaid").first())
#end for
now = datetime.now()
available_months = CotisationComputes.get_available_months(now.month, 8, paid_months)
year_price = 0
month_price = 0
try:
year_price = int(Cotisation.prix_annee(self.user, residence_dn).cn.first())
month_price = int(Cotisation.prix_mois(self.user, residence_dn).cn.first())
except:
pass
#end try
available_months_prices = []
index = 1
for available_month in available_months:
available_months_prices.append(
(available_month, month_names[available_month - 1], CotisationComputes.price_to_pay(year_price, month_price, already_paid, index))
)
index += 1
#end for
show_values["available_months_prices"] = available_months_prices
extras_available = Cotisation.get_all_extras(self.user, residence_dn)
show_values["extras_available"] = extras_available
return show_values
#end def
@expose()
@ -278,6 +327,141 @@ class MachineAddController(AuthenticatedRestController):
#end def
#end class
class CotisationController(AuthenticatedBaseController):
require_group = groups_enum.admin
add = None
def __init__(self):
self.add = CotisationAddController()
#end class
class CotisationAddController(AuthenticatedRestController):
require_group = groups_enum.admin
def create_cotisation(self, member, time, current_year, residence, residence_dn, member_uid, next_end):
print residence
print member_uid
print next_end
now = datetime.now()
next_month = int(next_end)
if not CotisationComputes.is_valid_month(next_month):
raise Exception("Invalid month") #FIXME
#end if
print "current_year " + str(current_year)
print member.dn
cotisations_existantes = Cotisation.cotisations_of_member(self.user, member.dn, current_year)
paid_months = []
already_paid = 0
for cotisation in cotisations_existantes:
paid_months = (
paid_months +
[int(month) for month in cotisation.get("x-validMonth").all()]
)
already_paid += int(cotisation.get("x-amountPaid").first())
#end for
print paid_months
available_months = CotisationComputes.get_available_months(now.month, next_month, paid_months)
if available_months == []:
return
year_price = 0
month_price = 0
try:
year_price = int(Cotisation.prix_annee(self.user, residence_dn).cn.first())
month_price = int(Cotisation.prix_mois(self.user, residence_dn).cn.first())
except:
pass
#end try
price_to_pay = CotisationComputes.price_to_pay(year_price, month_price, already_paid, len(available_months))
user_info = self.user.attrs.cn.first()
return Cotisation.entry_attr(time, residence, current_year, self.user.attrs.dn, user_info, price_to_pay, available_months)
#end def
def create_extra(self, time, current_year, residence, residence_dn, member_uid, extra_name):
extra_item = Cotisation.get_extra_by_name(self.user, residence_dn, extra_name)
prix = extra_item.cn.first()
user_info = self.user.attrs.cn.first()
return Cotisation.extra_attr(time, residence, current_year, self.user.attrs.dn, user_info, extra_item.uid.first(), prix)
#end def
@expose()
def post(self, residence, member_uid, next_end, extra_name, go_redirect = True):
residence_dn = Residences.get_dn_by_name(self.user, residence)
time = str(datetime.now())
current_year = CotisationComputes.current_year()
member = Member.get_by_uid(self.user, residence_dn, member_uid)
cotisation = None
extra = None
if next_end != "":
cotisation = self.create_cotisation(member, time, current_year, residence, residence_dn, member_uid, next_end)
if extra_name != "":
extra = self.create_extra(time, current_year, residence, residence_dn, member_uid, extra_name)
#end if
if cotisation is None and extra is None:
if go_redirect:
redirect("/edit/member/" + residence + "/" + member_uid)
else:
return
#end if
#end if
folder_dn = ldap_config.cotisation_member_base_dn + member.dn
print folder_dn
year_dn = "cn=" + str(current_year) + "," + folder_dn
try:
folder = Cotisation.folder_attr()
self.user.ldap_bind.add_entry(folder_dn, folder)
except ldap.ALREADY_EXISTS:
pass # OKAY
#end try
try:
year = Cotisation.year_attr(current_year)
self.user.ldap_bind.add_entry(year_dn, year)
except ldap.ALREADY_EXISTS:
pass # OKAY
#end try
if cotisation is not None:
cotisation_dn = "cn=cotisation-" + time + "," + year_dn
print cotisation
self.user.ldap_bind.add_entry(cotisation_dn, cotisation)
#end if
if extra is not None:
extra_dn = "cn=extra-" + time + "," + year_dn
print extra
self.user.ldap_bind.add_entry(extra_dn, extra)
#end if
if go_redirect:
redirect("/edit/member/" + residence + "/" + member_uid)
else:
return
#end if
#end def
#end class
""" Controller REST de gestion des ajouts de machines. """
class MachineDeleteController(AuthenticatedRestController):

View File

@ -40,11 +40,56 @@ class RegistrationController(AuthenticatedBaseController):
rooms = Room.get_rooms(self.user, self.user.residence_dn)
rooms = sorted(rooms, key=lambda t:t.cn.first())
now = datetime.now()
month_names = [
"Janvier",
"Fevrier",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Aout",
"Septembre",
"Octobre",
"Novembre",
"Decembre"
] # SALE FIXME
available_months = CotisationComputes.get_available_months(now.month, 8, [])
year_price = 0
month_price = 0
try:
year_price = int(Cotisation.prix_annee(self.user, self.user.residence_dn).cn.first())
month_price = int(Cotisation.prix_mois(self.user, self.user.residence_dn).cn.first())
except:
pass
#end try
available_months_prices = []
index = 1
already_paid = 0
for available_month in available_months:
available_months_prices.append(
(available_month, month_names[available_month - 1], CotisationComputes.price_to_pay(year_price, month_price, already_paid, index))
)
index += 1
#end for
extras_available = Cotisation.get_all_extras(self.user, self.user.residence_dn)
return {
"user" : self.user,
"residence" : residence,
"rooms" : rooms,
"quick_last" : RegistrationController.quick_last_registrations
"quick_last" : RegistrationController.quick_last_registrations,
"available_months_prices" : available_months_prices,
"extras_available" : extras_available
}
#end class
@ -59,17 +104,20 @@ class NewRegistrationController(AuthenticatedRestController):
@expose()
def post(self, residence, sn, givenName, mail,
room_uid, first_machine_name, first_machine_mac
room_uid, first_machine_name, first_machine_mac,
next_end, extra_name
):
# Initialisation des Users des Controllers Existant appellés
self.member_edit_controller.add.user = self.user
self.member_edit_controller.machine.add.user = self.user
self.member_edit_controller.room.move.user = self.user
self.member_edit_controller.cotisation.add.user = self.user
member_uid = self.member_edit_controller.add.post(residence, givenName, sn, mail, go_redirect = False)
self.member_edit_controller.machine.add.post(residence, member_uid, first_machine_name, first_machine_mac, go_redirect = False)
self.member_edit_controller.room.move.post(residence, member_uid, room_uid, erase = True, go_redirect = False)
self.member_edit_controller.cotisation.add.post(residence, member_uid, next_end, extra_name, go_redirect = False)
member = Member.get_by_uid(self.user, self.user.residence_dn, member_uid)
if member is not None:

View File

@ -38,13 +38,30 @@ class ShowController(AuthenticatedBaseController):
groups = Groupes.get_by_user_dn(self.user, residence_dn, member.dn)
year = CotisationComputes.current_year()
cotisations = Cotisation.cotisations_of_member(self.user, member.dn, year)
extras = Cotisation.extras_of_member(self.user, member.dn, year)
cotisations_mois = []
already_paid = 0
for cotisation in cotisations:
cotisations_mois = (cotisations_mois +
[(cotisation, int(month)) for month in cotisation.get("x-validMonth").all()]
)
already_paid += int(cotisation.get("x-amountPaid").first())
#end for
return {
"residence" : residence,
"user" : self.user,
"member_ldap" : member,
"room_ldap" : room,
"machines" : machines,
"groups" : groups
"groups" : groups,
"cotisations" : cotisations,
"cotisations_mois" : cotisations_mois,
"extras" : extras,
"cotisation_paid" : already_paid
}
#end def

View File

@ -1,4 +1,5 @@
from brie.config import ldap_config
import datetime
class Residences:
@ -29,4 +30,69 @@ class Residences:
return user_session.ldap_bind.search(ldap_config.liste_residence_dn, "(objectClass=groupOfUniqueNames)")
#end def
#end class
class CotisationComputes:
@staticmethod
def current_year():
now = datetime.datetime.now()
if now.year > 8:
return now.year + 1
return now.year
#end def
@staticmethod
def get_available_months(start, end, paid_months = []):
next_months_available = []
if start > 12 or end > 12:
raise Exception("invalid start or end")
if start > 8 and end > 8:
next_months_available = range(start, end + 1)
elif start > 8:
next_months_available = range(start, 13) + range(1, end + 1 )
elif start <= 8 and end < 9:
next_months_available = range(start, 9)
else:
raise Exception("invalid start and end")
#end if
if paid_months == []:
return next_months_available
print next_months_available
available_months = [
month
for month in next_months_available
if month not in paid_months
]
return available_months
#end def
@staticmethod
def is_valid_month(month):
now = datetime.datetime.now()
if now.month > 8:
return (month >= now.month and month < 13) or (month >= 1 and month < 9)
else:
return month >= now.month and month < 9
#end if
#end def
@staticmethod
def price_to_pay(year_price, month_price, already_paid, number_months_to_pay):
months_price = number_months_to_pay * month_price
print "already paid : " + str(already_paid)
print "months price : " + str(months_price)
if already_paid + months_price > 50:
months_price = max(0, 50 - already_paid)
return months_price
#end def
#end class

View File

@ -3,6 +3,7 @@
from __future__ import absolute_import
from brie.config import ldap_config
import ldap
import datetime
class Member(object):
@ -295,3 +296,109 @@ class Plugins:
#end def
#end class
class Cotisation:
@staticmethod
def entry_attr(time, residence, year, user_dn, user_info, amount_paid, valid_months):
return {
"objectClass" : ["top", "auroreCotisation", "aurorePayment"],
"cn" : "cotisation-" + time,
"x-time" : time,
"description" : "cotisation",
"x-year" : str(year),
"x-residence" : residence,
"x-action-user" : user_dn,
"x-action-user-info" : user_info,
"x-amountPaid" : amount_paid,
"x-validMonth" : valid_months
}
#end def
@staticmethod
def extra_attr(time, residence, year, user_dn, user_info, description, amount_paid):
return {
"objectClass" : ["top", "aurorePayment"],
"cn" : "extra-" + time,
"x-time" : time,
"description" : description,
"x-year" : str(year),
"x-residence" : residence,
"x-action-user" : user_dn,
"x-action-user-info" : user_info,
"x-amountPaid" : amount_paid
}
#end def
@staticmethod
def folder_attr():
return {
"objectClass" : ["organizationalRole", "top"],
"cn" : "cotisations"
}
#end def
@staticmethod
def year_attr(year):
return {
"objectClass" : ["organizationalRole", "top"],
"cn" : str(year)
}
#end def
@staticmethod
def prix_annee(user_session, residence_dn):
dn = ldap_config.cotisation_annee_base_dn + residence_dn
return user_session.ldap_bind.search_dn(dn)
#end def
@staticmethod
def prix_mois(user_session, residence_dn):
dn = ldap_config.cotisation_mois_base_dn + residence_dn
return user_session.ldap_bind.search_dn(dn)
#end def
@staticmethod
def cotisations_of_member(user_session, member_dn, year):
return user_session.ldap_bind.search("cn=" + str(year) + "," + ldap_config.cotisation_member_base_dn + member_dn, "(objectClass=auroreCotisation)")
#end def
@staticmethod
def extras_of_member(user_session, member_dn, year):
return user_session.ldap_bind.search("cn=" + str(year) + "," + ldap_config.cotisation_member_base_dn + member_dn, "(&(objectClass=aurorePayment)(!(objectClass=auroreCotisation)))")
#end def
@staticmethod
def get_all_extras(user_session, residence_dn):
dn = ldap_config.extra_base_dn + residence_dn
return user_session.ldap_bind.search(dn, "(objectClass=organizationalRole)", scope = ldap.SCOPE_ONELEVEL)
#end def
@staticmethod
def get_extra_by_name(user_session, residence_dn, name):
dn = ldap_config.extra_base_dn + residence_dn
return user_session.ldap_bind.search_first(dn, "(uid=" + name + ")")
#end def
@staticmethod
def get_all_payment_by_year(user_session, residence_dn, year):
dn = ldap_config.username_base_dn + residence_dn
return user_session.ldap_bind.search(dn, "(&(objectClass=aurorePayment)(x-year=" + str(year) + "))")
#end def
@staticmethod
def get_all_pending_payments(user_session, residence_dn, year):
dn = ldap_config.username_base_dn + residence_dn
return user_session.ldap_bind.search(dn, "(&(&(objectClass=aurorePayment)(x-year=" + str(year) + "))(!(x-paymentCashed=True)))")
#end def
@staticmethod
def get_pending_payments_of_admin(user_session, residence_dn, user_dn, year):
dn = ldap_config.username_base_dn + residence_dn
return user_session.ldap_bind.search(dn, "(&(&(&(objectClass=aurorePayment)(x-year=" + str(year) + "))(!(x-paymentCashed=True)))(x-action-user=" + user_dn + "))")
#end def
#end class

View File

@ -0,0 +1,23 @@
<html
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude"
py:strip="">
<div>
<span class="item_name">Cotiser jusqu'à</span>
<select name="next_end">
<option value="">&lt;vide&gt;</option>
<py:for each="month, name, price in available_months_prices">
<option value="${month}">${name} - ${price} €</option>
</py:for>
</select>
</div>
<div>
<span class="item_name">Acheter extra</span>
<select name="extra_name">
<option value="">&lt;vide&gt;</option>
<py:for each="extra in extras_available">
<option value="${extra.uid.first()}">${extra.uid.first()} - ${extra.cn.first()} €</option>
</py:for>
</select>
</div>
</html>

View File

@ -37,5 +37,18 @@
</form>
</div>
</div>
<xi:include href="../show/cotisation.html" />
<div class="section">
<form method="post" action="/edit/cotisation/add">
<input type="hidden" name="residence" value="${residence}"/>
<input type="hidden" name="member_uid" value="${member_ldap.uid.first()}"/>
<xi:include href="cotisation-edit.html" />
<div>
<span class="item_name"></span>
<input type="submit" class="button" value="Envoyer" />
</div>
</form>
</div>
</body>
</html>

View File

@ -50,12 +50,7 @@
</div>
<div class="section">
<span class="section_name show_section_name">COTISATION</span>
<div>
<div>
<span class="item_name">Mois fin</span>
<span>TODO</span>
</div>
</div>
<xi:include href="../edit/cotisation-edit.html" />
</div>
<div class="section">
<div>

View File

@ -0,0 +1,20 @@
<html
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude"
py:strip="">
<div class="section">
<span class="section_name show_section_name">COTISATION</span>
<div>
<span class="item_name">Mois cotisés</span>
<span class="button" py:for="cotisation, mois in cotisations_mois" title="${cotisation.get('x-action-user-info').first()} / ${cotisation.get('x-time').first()}">${mois}</span>
</div>
<div>
<span class="item_name">Total</span>
<span>${cotisation_paid} €</span>
</div>
<div>
<span class="item_name">Extra payés</span>
<span py:for="extra in extras">${extra.description.first()} (${extra.get("x-amountPaid").first()} €) ; </span>
</div>
</div>
</html>

View File

@ -18,6 +18,7 @@
<span class="section_name show_section_name" py:when="None">PAS DE CHAMBRE</span>
<div py:otherwise="">${room_view(room_ldap)}</div>
</div>
<xi:include href="cotisation.html" />
<xi:include href="plugins.html" />
</body>
</html>