From f03b3e0104496c37c3928d8051a2a95f16cf3b7e Mon Sep 17 00:00:00 2001 From: Roven Gabriel Date: Wed, 11 Sep 2013 00:28:40 +0200 Subject: [PATCH] implementation de la cotisation --- Brie/brie/config/ldap_config.py | 7 + Brie/brie/controllers/edit.py | 238 ++++++++++++++++-- Brie/brie/controllers/registration.py | 54 +++- Brie/brie/controllers/show.py | 19 +- Brie/brie/lib/aurore_helper.py | 66 +++++ Brie/brie/model/ldap.py | 107 ++++++++ Brie/brie/templates/edit/cotisation-edit.html | 23 ++ Brie/brie/templates/edit/member.html | 13 + Brie/brie/templates/registration/index.html | 7 +- Brie/brie/templates/show/cotisation.html | 20 ++ Brie/brie/templates/show/member.html | 1 + 11 files changed, 518 insertions(+), 37 deletions(-) create mode 100644 Brie/brie/templates/edit/cotisation-edit.html create mode 100644 Brie/brie/templates/show/cotisation.html diff --git a/Brie/brie/config/ldap_config.py b/Brie/brie/config/ldap_config.py index 64a3613..844134c 100644 --- a/Brie/brie/config/ldap_config.py +++ b/Brie/brie/config/ldap_config.py @@ -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 diff --git a/Brie/brie/controllers/edit.py b/Brie/brie/controllers/edit.py index 59a677c..5599c5e 100644 --- a/Brie/brie/controllers/edit.py +++ b/Brie/brie/controllers/edit.py @@ -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): diff --git a/Brie/brie/controllers/registration.py b/Brie/brie/controllers/registration.py index 29e43fa..2f01cab 100644 --- a/Brie/brie/controllers/registration.py +++ b/Brie/brie/controllers/registration.py @@ -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: diff --git a/Brie/brie/controllers/show.py b/Brie/brie/controllers/show.py index 127d1a5..ff4607b 100644 --- a/Brie/brie/controllers/show.py +++ b/Brie/brie/controllers/show.py @@ -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 diff --git a/Brie/brie/lib/aurore_helper.py b/Brie/brie/lib/aurore_helper.py index 709563d..769e672 100644 --- a/Brie/brie/lib/aurore_helper.py +++ b/Brie/brie/lib/aurore_helper.py @@ -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 diff --git a/Brie/brie/model/ldap.py b/Brie/brie/model/ldap.py index e70a668..408cb05 100644 --- a/Brie/brie/model/ldap.py +++ b/Brie/brie/model/ldap.py @@ -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 diff --git a/Brie/brie/templates/edit/cotisation-edit.html b/Brie/brie/templates/edit/cotisation-edit.html new file mode 100644 index 0000000..eb5452c --- /dev/null +++ b/Brie/brie/templates/edit/cotisation-edit.html @@ -0,0 +1,23 @@ + +
+ Cotiser jusqu'à + +
+
+ Acheter extra + +
+ diff --git a/Brie/brie/templates/edit/member.html b/Brie/brie/templates/edit/member.html index 3c3c143..6e7be13 100644 --- a/Brie/brie/templates/edit/member.html +++ b/Brie/brie/templates/edit/member.html @@ -37,5 +37,18 @@ + +
+
+ + + + +
+ + +
+ +
diff --git a/Brie/brie/templates/registration/index.html b/Brie/brie/templates/registration/index.html index b60cb3a..053d6e8 100644 --- a/Brie/brie/templates/registration/index.html +++ b/Brie/brie/templates/registration/index.html @@ -50,12 +50,7 @@
COTISATION -
-
- Mois fin - TODO -
-
+
diff --git a/Brie/brie/templates/show/cotisation.html b/Brie/brie/templates/show/cotisation.html new file mode 100644 index 0000000..2937b4f --- /dev/null +++ b/Brie/brie/templates/show/cotisation.html @@ -0,0 +1,20 @@ + +
+ COTISATION +
+ Mois cotisés + ${mois} +
+
+ Total + ${cotisation_paid} € +
+
+ Extra payés + ${extra.description.first()} (${extra.get("x-amountPaid").first()} €) ; +
+
+ diff --git a/Brie/brie/templates/show/member.html b/Brie/brie/templates/show/member.html index 632be84..8c2d23e 100644 --- a/Brie/brie/templates/show/member.html +++ b/Brie/brie/templates/show/member.html @@ -18,6 +18,7 @@ PAS DE CHAMBRE
${room_view(room_ldap)}
+