Le repo des sources pour le site web des JM2L
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

2097 line
92 KiB

  1. # -*- coding: utf8 -*-
  2. from pyramid.httpexceptions import HTTPFound, HTTPNotFound, HTTPForbidden
  3. from pyramid.httpexceptions import HTTPBadRequest, HTTPUnauthorized
  4. from pyramid.renderers import render_to_response
  5. from pyramid.view import notfound_view_config, forbidden_view_config
  6. from pyramid.view import view_config
  7. from pyramid.response import Response
  8. from mako.template import Template
  9. from pyramid_mailer.message import Message
  10. from .upload import IMAGEPATH, MediaPath
  11. # Import Web Forms
  12. from .forms import *
  13. # Database access imports
  14. from .models import *
  15. from .helpers import Orga_helpers
  16. from sqlalchemy import func, or_, text, and_
  17. from sqlalchemy.orm import aliased
  18. from os import path, makedirs, listdir
  19. # Usefull tools
  20. from slugify import slugify
  21. from icalendar import Calendar
  22. from pytz import timezone
  23. from icalendar import Event as Evt
  24. from pyramid_mailer.message import Message
  25. # Then, standard libs
  26. import csv
  27. import cStringIO as StringIO
  28. import webhelpers.paginate as paginate
  29. import unicodedata
  30. import datetime
  31. import re
  32. import shutil
  33. import glob
  34. from jm2l.const import CurrentYear
  35. from passlib.hash import argon2
  36. ## =-=- Here, We keep some usefull function -=-=
  37. def remove_accents(input_str):
  38. """ This function is intended to remove all accent from input unicode string """
  39. nkfd_form = unicodedata.normalize('NFKD', input_str)
  40. only_ascii = nkfd_form.encode('ASCII', 'ignore')
  41. return only_ascii
  42. def embeed_video(mime_type, link):
  43. Container = "<video controls='controls' preload='metadata' style='width:60%'>"
  44. Container += "<source type='%s' " % mime_type
  45. Container += "src='%s' />" % link
  46. Container += "</video>"
  47. return Container
  48. @view_config(route_name='Live', renderer="jm2l:templates/Live.mako")
  49. def Live(request):
  50. year = int(request.matchdict.get('year', CurrentYear))
  51. tz = timezone('Europe/Paris')
  52. curtime = datetime.datetime.now().replace(tzinfo=tz, day=28) #, hour=10, minute=00 )
  53. Events = DBSession.query(Event)\
  54. .filter(Event.for_year == year)\
  55. .filter(Event.event_type != 'Stand')\
  56. .filter(and_(Event.start_time <= curtime, Event.end_time >= curtime) )\
  57. .order_by(Event.start_time)
  58. return {'year': year, "DisplayYear": year, 'events':Events, "logged_in":request.authenticated_userid }
  59. ## =-=- Here, We handle ICal requests -=-=
  60. @view_config(route_name='progr_iCal', renderer="string")
  61. def ICal_Progamme_Request(request):
  62. year = int(request.matchdict.get('year', CurrentYear))
  63. # Initialization
  64. # Compute days used by all events matching the specified input year
  65. Events = DBSession.query(Event)\
  66. .filter(Event.for_year == year)\
  67. .filter(Event.event_type != 'Stand')\
  68. .order_by(Event.start_time)
  69. cal = Calendar()
  70. cal.add('prodid', '-//Programme %d//jm2l.linux-azur.org//' % year)
  71. cal.add('version', '2.0')
  72. tz = timezone('Europe/Paris')
  73. for ev in Events:
  74. if ev.event_type:
  75. event = Evt()
  76. event['uid'] = "%d/%d" % ( year, ev.uid )
  77. event.add('summary', ev.name )
  78. event.add('dtstart', ev.start_time.replace(tzinfo=tz) )
  79. event.add('dtend', ev.end_time.replace(tzinfo=tz) )
  80. event.add('created', ev.last_change.replace(tzinfo=tz) )
  81. event.add('description', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  82. event.add('url', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  83. event.add('priority', 5)
  84. for interv in ev.intervenants:
  85. event.add('organizer',
  86. interv.slug,
  87. parameters={
  88. "CN": "%s %s" % (interv.prenom, interv.nom),
  89. "DIR": "https://jm2l.linux-azur.org/user/%s" % interv.slug
  90. }
  91. )
  92. event.add('location', ev.Salle.name)
  93. event.add('categories', ev.event_type)
  94. cal.add_component(event)
  95. request.response.content_type = "text/calendar"
  96. return cal.to_ical()
  97. ## =-=- Here, We handle ICal requests -=-=
  98. @view_config(route_name='progr_dyn_iCal', renderer="string")
  99. def ICal_Progamme_Dyn_Request(request):
  100. year = int(request.matchdict.get('year', CurrentYear))
  101. # Initialization
  102. # Compute days used by all events matching the specified input year
  103. Events = DBSession.query(Event)\
  104. .filter(Event.for_year == year)\
  105. .filter(Event.event_type != 'Stand')\
  106. .order_by(Event.start_time)
  107. cal = Calendar()
  108. cal.add('prodid', '-//Programme %d//jm2l.linux-azur.org//' % year)
  109. cal.add('version', '2.0')
  110. today = datetime.datetime.now()
  111. tz = timezone('Europe/Paris')
  112. event = Evt()
  113. event['uid'] = "%d/%d" % ( year, 100 )
  114. event.add('summary', "Les stands JM2L %s" % year )
  115. event.add('dtstart', datetime.datetime.now().replace(tzinfo=tz, hour=10, minute=00 ) )
  116. event.add('dtend', datetime.datetime.now().replace(tzinfo=tz, hour=18, minute=00 ) )
  117. event.add('created', datetime.datetime.now().replace(tzinfo=tz, hour=10, minute=00 ) )
  118. event.add('description', "https://www.youtube.com/watch?v=91X65eEKxvU&t=6s" )
  119. event.add('location', "http://jm2l.linux-azur.org/img/325.gif" )
  120. event.add('url', "http://jm2l.linux-azur.org/%s/le-programme" % CurrentYear)
  121. event.add('priority', 5)
  122. cal.add_component(event)
  123. TabCorr = {
  124. 135:"Koneko",
  125. 131:"cam-jm2l-a",
  126. 132:"cam-jm2l-b",
  127. 115:"cam-jm2l-e",
  128. 114:"cam-jm2l-f",
  129. 116:"cam-jm2l-g",
  130. 139:"cam-jm2l-y"
  131. }
  132. for i, ev in enumerate(Events):
  133. if ev.event_type:
  134. event = Evt()
  135. event['uid'] = "%d/%d" % ( year, ev.uid )
  136. event.add('summary', ev.name )
  137. event.add('dtstart', ev.start_time.replace(tzinfo=tz, day=today.day, month = today.month, hour=(ev.start_time.hour)%24 ) )
  138. event.add('dtend', ev.end_time.replace(tzinfo=tz, day=today.day, month = today.month, hour=(ev.end_time.hour)%24 ) )
  139. event.add('created', ev.last_change.replace(tzinfo=tz) )
  140. event.add('description', "http://jm2l.linux-azur.org:8080/%s.webm" % TabCorr.get(ev.Salle.phy_salle_id, ev.Salle.phy_salle_id) )
  141. event.add('location', "http://jm2l.linux-azur.org/img/%d.gif" % ev.Salle.phy_salle_id )
  142. event.add('url', "http://www.linux-azur.org/event/%s/%s" % (ev.for_year, ev.slug) )
  143. event.add('priority', 5)
  144. cal.add_component(event)
  145. request.response.content_type = "text/calendar"
  146. return cal.to_ical()
  147. ## =-=- Here, We handle Json requests -=-=
  148. @view_config(route_name='users_json', renderer="json")
  149. def JSON_User_Request(request):
  150. """ Build a JSON answer with active users and pagination handling """
  151. # Check arguments consitency
  152. pageSize = request.params.get('pageSize',"8")
  153. current_page = request.params.get('pageNum',"1")
  154. UserQuery = request.params.get('searchTerm', u"")
  155. # Don't answer to users that aren't logged
  156. if not request.user:
  157. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  158. # Check consistancy of parameters
  159. if pageSize.isdigit() and current_page.isdigit():
  160. current_page = int(current_page)
  161. pageSize = int(pageSize)
  162. else:
  163. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  164. # Query database
  165. Users = DBSession.query(User.uid, User.nom, User.prenom)\
  166. .filter(User.slug.contains( remove_accents(UserQuery) ))
  167. page_url = paginate.PageURL_WebOb(request)
  168. records = paginate.Page(Users, current_page, url=page_url, items_per_page=pageSize)
  169. ListMatchUser = map( lambda u:{"id": u.uid, "text":"%s %s" % ( u.prenom, u.nom )}, records )
  170. return { "Results": ListMatchUser, "Total":records.item_count,
  171. "logged_in":request.authenticated_userid }
  172. @view_config(route_name='tiers_json', renderer="json")
  173. def JSON_Tiers_Request(request):
  174. """ Build a JSON answer with active users and pagination handling """
  175. # Check arguments consitency
  176. pageSize = request.params.get('pageSize',"8")
  177. current_page = request.params.get('pageNum',"1")
  178. TiersQuery = request.params.get('searchTerm', u"")
  179. # Don't answer to users that aren't logged
  180. if not request.user:
  181. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  182. # Check consistancy of parameters
  183. if pageSize.isdigit() and current_page.isdigit():
  184. current_page = int(current_page)
  185. pageSize = int(pageSize)
  186. else:
  187. return HTTPBadRequest('pageSize and pageNum accept only digits.')
  188. # Query database
  189. JTiers = DBSession.query(Tiers.uid, Tiers.name)\
  190. .filter(Tiers.slug.contains( remove_accents(TiersQuery) ))
  191. page_url = paginate.PageURL_WebOb(request)
  192. records = paginate.Page(JTiers, current_page, url=page_url, items_per_page=pageSize)
  193. ListMatchTiers = map( lambda t:{"id": t.uid, "text": t.name }, records )
  194. return { "Results": ListMatchTiers, "Total":records.item_count,
  195. "logged_in":request.authenticated_userid }
  196. @view_config(route_name='progr_json', renderer="json")
  197. def JSON_Progamme_Request(request):
  198. year = int(request.matchdict.get('year', CurrentYear))
  199. # Initialization
  200. DicResult = dict()
  201. # Query database
  202. # Compute days used by all events matching the specified input year
  203. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  204. .filter(Event.for_year == year)\
  205. .filter(Event.event_type != None)\
  206. .group_by(func.strftime('%d', Event.start_time)).all()
  207. for Day in Days:
  208. Events = DBSession.query(Event)\
  209. .filter(Event.for_year == year)\
  210. .filter(Event.event_type != 'Stand')\
  211. .filter(text("strftime('%d', start_time) = :dow")).params(dow=Day.day)\
  212. .order_by(Event.start_time)
  213. ListEv = []
  214. for ev in Events:
  215. if ev.event_type:
  216. ListEv.append( {
  217. "uid":"%d/%d" % ( year, ev.uid ),
  218. "desc":ev.name,
  219. "startDate":ev.start_time.strftime('%Y-%m-%dT%H:%M:%S+01:00'),
  220. "endDate":ev.end_time.strftime('%Y-%m-%dT%H:%M:%S+01:00'),
  221. "placeName":ev.Salle and (ev.Salle.name or "unk") ,
  222. "status":ev.event_type
  223. } )
  224. DicResult[Day.day] = ListEv
  225. return { 'all':DicResult }
  226. @view_config(route_name='timeline_json', renderer="json")
  227. def JSON_TimeLine_Request(request):
  228. year = int(request.matchdict.get('year', CurrentYear))
  229. # Initialization
  230. DicResult = dict()
  231. # Query database
  232. # Compute days used by all events matching the specified input year
  233. Days = DBSession.query( func.strftime('%d', Event.start_time).label('day') )\
  234. .filter(Event.for_year == year)\
  235. .filter(Event.event_type != None)\
  236. .group_by(func.strftime('%d', Event.start_time)).all()
  237. ListEv = []
  238. for Day in Days:
  239. Events = DBSession.query(Event)\
  240. .filter(Event.for_year == year)\
  241. .filter(Event.event_type != 'Stand')\
  242. .filter(text("strftime('%d', start_time) = :dow")).params(dow=Day.day)\
  243. .order_by(Event.start_time)
  244. #ListEv = []
  245. for ev in Events:
  246. if ev.event_type:
  247. CurMedia = ev.video.first() or ""
  248. if CurMedia:
  249. Container = "<video controls='controls' preload='metadata' style='width:60%'>"
  250. Container += "<source type='%s' " % CurMedia.mime_type
  251. Container += "src='%s' />" % CurMedia.get_path
  252. Container += "</video>"
  253. else:
  254. Container = ""
  255. ListEv.append( {
  256. #"uid":"%d/%d" % ( year, ev.uid ),
  257. "headline":'<a href="/event/%s/%s">%s</a>' % (ev.for_year, ev.slug, ev.name),
  258. "startDate":ev.start_time.strftime('%Y,%m,%d,%H,%M'),
  259. "endDate":ev.end_time.strftime('%Y,%m,%d,%H,%M'),
  260. "text": ev.Salle and (ev.Salle.name or "unk"),
  261. #"text":ev.description[:100],
  262. "tags":ev.Salle and (ev.Salle.salle_id or "unk") ,
  263. #"status":ev.event_type,
  264. "asset": {
  265. "media": Container,
  266. "credit": ",".join(["%s %s" % (i.prenom, i.nom) for i in ev.intervenants]),
  267. "caption":"" }
  268. } )
  269. if year==2017:
  270. DicResult = {
  271. "lang":"fr",
  272. "headline":"JM2L 2017",
  273. "type":"default",
  274. "startDate":"2017,11,25,10",
  275. "text":"<i><span class='c1'>10ème Édition</span></i>",
  276. "asset":
  277. {
  278. "media":embeed_video("video/ogg","/resources/2017/Video/JM2L2017_Reportage_FR3.ogv"),
  279. "credit":"Reportage France 3",
  280. "caption":"JM2L 2017"
  281. }
  282. }
  283. elif year==2015:
  284. DicResult = {
  285. "lang":"fr",
  286. "headline":"JM2L 2015",
  287. "type":"default",
  288. "startDate":"2015,11,28,10",
  289. "text":"<i><span class='c1'>9ème Édition</span></i>",
  290. "asset":
  291. {
  292. #"media":"https://www.youtube.com/watch?v=91X65eEKxvU&t=6s",
  293. "media":embeed_video("video/ogg","/resources/2015/Video/jm2l_france3-2015.ogv"),
  294. "credit":"Reportage France 3",
  295. "caption":"JM2L 2015"
  296. }
  297. }
  298. elif year==2011:
  299. DicResult = {
  300. "lang":"fr",
  301. "headline":"JM2L 2011",
  302. "type":"default",
  303. "startDate":"2011,11,25,10",
  304. "text":"<i><span class='c1'>6ème Édition</span></i>",
  305. "asset":
  306. {
  307. "media":"https://www.youtube.com/embed/rcaNeXuAEhs",
  308. "credit":"JM2L",
  309. "caption":"Reportage FR3"
  310. },
  311. }
  312. elif year==2010:
  313. DicResult = {
  314. "lang":"fr",
  315. "headline":"JM2L 2010",
  316. "type":"default",
  317. "text":"<i><span class='c1'>5ème Édition</span></i>",
  318. "asset":
  319. {
  320. "media":embeed_video("video/ogg","/resources/2010/Video/reportages/JM2L2010-PleinSudTV.ogv"),
  321. "credit":"<a href='http://pleinsudtv.com/index.php/casa/affichage-en-vignettes/93-casa-culture/582-les-jm-du-logiciel-libre-2010'>Le reportage Plein-sud TV</a>",
  322. "caption":"JM2L",
  323. }
  324. }
  325. elif year==2007:
  326. DicResult = {
  327. "lang":"fr",
  328. "headline":"JM2L 2007",
  329. "type":"default",
  330. "text":"<i><span class='c1'>2ème Édition</span></i>",
  331. "asset":
  332. {
  333. "media":embeed_video("video/ogg","/resources/2007/Video/20071110-linux.ogv"),
  334. "credit":"<a href='http://pleinsudtv.com/index.php/casa/affichage-en-vignettes/93-casa-culture/245-logiciel-libre-linux-jm2l'>Le reportage Plein-sud TV</a>",
  335. "caption":"JM2L 2007",
  336. }
  337. }
  338. else:
  339. DicResult = {
  340. "lang":"fr",
  341. "headline":"JM2L %d" % year,
  342. "type":"default",
  343. "asset":
  344. {
  345. "media":"",
  346. "credit":"JM2L",
  347. "caption":""
  348. }
  349. }
  350. DicResult["date"] = ListEv
  351. return { 'timeline':DicResult }
  352. ## =-=- Here, We handle HTTP requests - Public Part -=-=
  353. @view_config(route_name='home', renderer="jm2l:templates/NewIndex.mako")
  354. def index_page(request):
  355. year = request.matchdict.get('year')
  356. if year:
  357. year=int(year[:-1])
  358. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  359. if content:
  360. content = content.description
  361. else:
  362. content = ""
  363. if 2004<year<=CurrentYear:
  364. if year==2006:
  365. return {'year': year, 'content':content, 'edition':u"1<sup>ère</sup>" }
  366. elif year==2015:
  367. return {'year': year, 'content':content, 'edition':u"9<sup>ème</sup>" }
  368. elif year==2017:
  369. return {'year': year, 'content':content, 'edition':u"10<sup>ème</sup>" }
  370. else:
  371. edition = year - 2005
  372. return {'year': year, 'content':content, 'edition':u"%d<sup>ème</sup>" % edition }
  373. else:
  374. raise HTTPNotFound()
  375. else:
  376. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==CurrentYear).first().description
  377. TargetDir = "jm2l/static/img/%s/Photos" % (year or CurrentYear)
  378. TargetUrl = "/static/img/%s/Photos/" % (year or CurrentYear)
  379. if path.isdir(TargetDir):
  380. ListPhotos = map(lambda x: TargetUrl + x, listdir(TargetDir))
  381. else:
  382. ListPhotos = []
  383. return {'year': CurrentYear, 'content':content, 'edition':u"10<sup>ème</sup>", 'ListPhotos': ListPhotos}
  384. @view_config(route_name='edit_index', renderer="jm2l:templates/Staff/EditIndex.mako")
  385. def edit_index(request):
  386. year = int(request.matchdict.get('year', CurrentYear))
  387. if not request.user.Staff:
  388. # Don't answer to users that aren't logged
  389. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  390. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  391. form = IndexForm(request.POST, content, meta={'csrf_context': request.session})
  392. if request.method == 'POST' and form.validate():
  393. form.populate_obj(content)
  394. return HTTPFound(location=request.route_url('home', year="%d/" % year))
  395. MainTab = {'home':'active', "logged_in":request.authenticated_userid,
  396. 'form':form, 'DisplayYear':year}
  397. return MainTab
  398. @view_config(route_name='programme', renderer="jm2l:templates/Public/Programme.mako")
  399. def programme(request):
  400. year = int(request.matchdict.get('year'))
  401. if 2006 > year:
  402. return HTTPBadRequest('The first JM2L event was in 2006.')
  403. # Query database about selected Year.
  404. Events = DBSession.query(Event)\
  405. .filter(Event.for_year == year)\
  406. .order_by(Event.start_time)
  407. Days = DBSession.query(func.strftime('%d-%m-%Y', Event.start_time))\
  408. .filter(Event.for_year == year)\
  409. .filter(Event.event_type != None)\
  410. .group_by(func.strftime('%d', Event.start_time)).all()
  411. ListDay = []
  412. for day in Days:
  413. RefDay = datetime.datetime.strptime(day[0],'%d-%m-%Y')
  414. ListDay.append( ( RefDay.strftime('%A %d %b %Y'),
  415. RefDay.strftime('%d') ) )
  416. MainTab = {'programme':'active','DisplayYear':year, \
  417. 'Events':Events, 'Event':Event, 'Days':ListDay, "logged_in":request.authenticated_userid }
  418. return MainTab
  419. @view_config(route_name='presse', renderer="jm2l:templates/Public/Presse.mako")
  420. def static_presse(request):
  421. year = int(request.matchdict.get('year', None))
  422. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  423. MainTab = {'presse':'active', "logged_in":request.authenticated_userid, 'content':content, 'DisplayYear':year}
  424. return MainTab
  425. @view_config(route_name='edit_presse', renderer="jm2l:templates/Staff/EditPresse.mako")
  426. def edit_presse(request):
  427. year = int(request.matchdict.get('year', None))
  428. if request.user is None:
  429. # Don't answer to users that aren't logged
  430. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  431. if not request.user.Staff:
  432. # Don't answer to users that aren't logged
  433. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  434. content = DBSession.query(JM2L_Year).filter(JM2L_Year.year_uid==year).first()
  435. form = DossPresse(request.POST, content, meta={'csrf_context': request.session})
  436. if request.method == 'POST' and form.validate():
  437. form.populate_obj(content)
  438. MainTab = {'presse':'active', "logged_in":request.authenticated_userid, 'form':form, 'DisplayYear':year}
  439. return MainTab
  440. @view_config(route_name='plan', renderer="jm2l:templates/Public/Plan.mako")
  441. def static_plan(request):
  442. session = request.session
  443. session['year'] = CurrentYear
  444. MainTab = {'plan':'active', "logged_in":request.authenticated_userid }
  445. return MainTab
  446. ## =-=- Here, We handle HTTP requests - Staff Logged Part -=-=
  447. @view_config(route_name='list_task', renderer='jm2l:templates/Staff/list.mako')
  448. def list_view(request):
  449. year = int(request.matchdict.get('year', CurrentYear))
  450. if request.user is None:
  451. # Don't answer to users that aren't logged
  452. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  453. if not request.user.Staff:
  454. # Don't answer to users that aren't logged
  455. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  456. DicTask = {}
  457. taskgroup = DBSession.query( TasksArea ).filter( TasksArea.year_uid == year).all()
  458. for grp in taskgroup:
  459. tasks = DBSession.query( Tasks )\
  460. .filter( Tasks.area_uid==grp.uid ) \
  461. .filter( Tasks.year_uid == year) \
  462. .order_by(Tasks.closed, Tasks.due_date).all()
  463. DicTask[grp] = tasks
  464. return {'tasks': DicTask, 'year':year }
  465. @view_config(route_name='list_expenses', renderer='jm2l:templates/Staff/compta.mako')
  466. def expenses(request):
  467. year = int(request.matchdict.get('year', CurrentYear))
  468. if request.user is None:
  469. # Don't answer to users that aren't logged
  470. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  471. if not request.user.Staff:
  472. # Don't answer to users that aren't logged
  473. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  474. output = []
  475. dic_out = {}
  476. for name in glob.glob('jm2l/upload/images/users/*/RIB/*'):
  477. tab_path = name.split('/')
  478. u = User.by_slug(tab_path[4])
  479. if u is None:
  480. continue
  481. if tab_path[6]=='thumbnails' or tab_path[6].endswith('.type'):
  482. continue
  483. if dic_out.get(tab_path[4]) is None:
  484. dic_out[tab_path[4]] = {}
  485. if dic_out[tab_path[4]].get('RIB') is None:
  486. dic_out[tab_path[4]]['RIB'] = {'files':[], 'thumb':[]}
  487. u = User.by_slug(tab_path[4])
  488. if u is None:
  489. dic_out[tab_path[4]]['User'] = {
  490. 'uid':'# NOT FOUND',
  491. 'nom':name,
  492. 'prenom':'# NOT FOUND',
  493. 'slug':'# NOT FOUND'
  494. }
  495. else:
  496. dic_out[tab_path[4]]['User'] = {
  497. 'uid':u.uid,
  498. 'nom':u.nom,
  499. 'prenom':u.prenom,
  500. 'slug':u.slug
  501. }
  502. dic_out[tab_path[4]]['RIB']['files'].append( name )
  503. dic_out[tab_path[4]]['RIB']['thumb'].append( name + ".jpg" )
  504. for name in glob.glob('jm2l/upload/images/users/*/Justif/*'):
  505. tab_path = name.split('/')
  506. u = User.by_slug(tab_path[4])
  507. if u is None:
  508. continue
  509. if tab_path[6]=='thumbnails' or tab_path[6].endswith('.type'):
  510. continue
  511. if dic_out.get(tab_path[4]) is None:
  512. dic_out[tab_path[4]] = {}
  513. if dic_out[tab_path[4]].get('Justif') is None:
  514. dic_out[tab_path[4]]['Justif'] = {'files':[], 'thumb':[]}
  515. u = User.by_slug(tab_path[4])
  516. if u is None:
  517. dic_out[tab_path[4]]['User'] = {
  518. 'uid':'# NOT FOUND',
  519. 'nom':name,
  520. 'prenom':'# NOT FOUND',
  521. 'slug':'# NOT FOUND'
  522. }
  523. else:
  524. dic_out[tab_path[4]]['User'] = {
  525. 'uid':u.uid,
  526. 'nom':u.nom,
  527. 'prenom':u.prenom,
  528. 'slug':u.slug
  529. }
  530. dic_out[tab_path[4]]['Justif']['files'].append( name )
  531. dic_out[tab_path[4]]['Justif']['thumb'].append( name + ".jpg" )
  532. return dict(found=dic_out, year=year )
  533. @view_config(route_name='handle_task', renderer='jm2l:templates/Staff/tasks.mako')
  534. def tasks(request):
  535. year = int(request.matchdict.get('year', CurrentYear))
  536. if request.user is None:
  537. # Don't answer to users that aren't logged
  538. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  539. if not request.user.Staff:
  540. # Don't answer to users that aren't logged
  541. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  542. task_id = request.matchdict.get('task_id')
  543. # Convert the pole_id GET parameter to int or 0
  544. if request.params.get('pole_id') and request.params.get('pole_id').isdigit():
  545. pole_id = int(request.params.get('pole_id'))
  546. else:
  547. pole_id = None
  548. # Get areas from db
  549. Areas = DBSession.query(TasksArea.uid, TasksArea.name) \
  550. .filter(TasksArea.year_uid == year) \
  551. .order_by('name').all()
  552. # Get users from db
  553. Users = DBSession.query(User)\
  554. .filter(User.Staff==1)\
  555. .order_by('nom').all()
  556. if task_id:
  557. TmpTask = Tasks.by_id(int(task_id))
  558. if not TmpTask:
  559. raise HTTPNotFound()
  560. form = EditStaffTasks(request.POST, TmpTask, meta={'csrf_context': request.session})
  561. else:
  562. TmpTask = Tasks()
  563. # Check if the supplied pole_id is in the Areas' range
  564. form = StaffTasks(request.POST, TmpTask, meta={'csrf_context': request.session})
  565. Area = TasksArea.by_id(pole_id)
  566. if Area:
  567. form.area_uid.data = Area.uid
  568. # Put some areas on form
  569. form.area_uid.choices = Areas
  570. # Put some users on form
  571. form.closed_by.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  572. for u in Users]
  573. form.due_date.type = "date"
  574. if request.method=='POST' and form.validate():
  575. form.populate_obj(TmpTask)
  576. TmpTask.closed = False
  577. if not TmpTask.year_uid:
  578. TmpTask.year_uid = year;
  579. if 'uid' in form._fields.keys():
  580. DBSession.merge(TmpTask)
  581. else:
  582. DBSession.add(TmpTask)
  583. DBSession.flush()
  584. return HTTPFound(location=request.route_url('list_task', year=year)+"#"+slugify(TmpTask.area.name))
  585. return {'form':form, 'area':TmpTask.area and slugify(TmpTask.area.name) or '', 'year':year}
  586. @view_config(route_name='handle_pole', renderer='jm2l:templates/Staff/pole.mako')
  587. def tasks_area(request):
  588. year = int(request.matchdict.get('year', CurrentYear))
  589. if request.user is None:
  590. # Don't answer to users that aren't logged
  591. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  592. if not request.user.Staff:
  593. # Don't answer to users that aren't logged
  594. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  595. pole_id = request.matchdict.get('pole_id')
  596. if pole_id:
  597. Pole = TasksArea.by_id(int(pole_id))
  598. if not Pole:
  599. raise HTTPNotFound()
  600. form = EditStaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  601. else:
  602. Pole = TasksArea()
  603. form = StaffArea(request.POST, Pole, meta={'csrf_context': request.session})
  604. if request.method == 'POST' and form.validate():
  605. form.populate_obj(Pole)
  606. if not Pole.year_uid:
  607. Pole.year_uid = year;
  608. if 'uid' in form._fields.keys():
  609. DBSession.merge(Pole)
  610. else:
  611. DBSession.add(Pole)
  612. return HTTPFound(location=request.route_url('list_task', year=year)+"#"+slugify(Pole.name))
  613. return {'form':form, 'year':year }
  614. @view_config(route_name='action_task')
  615. def action_task(request):
  616. year = int(request.matchdict.get('year', CurrentYear))
  617. if request.user is None:
  618. # Don't answer to users that aren't logged
  619. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  620. if not request.user.Staff:
  621. # Don't answer to users that aren't logged
  622. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  623. action = request.matchdict.get('action')
  624. task_id = request.matchdict.get('task_id')
  625. Task = Tasks.by_id(int(task_id))
  626. if action=='close':
  627. Task.closed = True
  628. request.session.flash(('info', u'La tâche a été fermé, Félicitations !'))
  629. DBSession.merge(Task)
  630. if action=='open':
  631. Task.closed = False
  632. request.session.flash(('info', u'La tâche a été ré-ouverte !'))
  633. DBSession.merge(Task)
  634. if action=='delete':
  635. request.session.flash(('info', u'La tâche a été supprimée !'))
  636. DBSession.delete(Task)
  637. return HTTPFound(location=request.route_url('list_task', year=year)+"#"+slugify(Task.area.name))
  638. @view_config(route_name='action_task_area')
  639. def action_task_area(request):
  640. year = int(request.matchdict.get('year', CurrentYear))
  641. if request.user is None:
  642. # Don't answer to users that aren't logged
  643. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  644. if not request.user.Staff:
  645. # Don't answer to users that aren't logged
  646. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  647. action = request.matchdict.get('action')
  648. pole_id = request.matchdict.get('pole_id')
  649. Pole = TasksArea.by_id(int(pole_id))
  650. if not Pole:
  651. raise HTTPNotFound()
  652. if action=='delete':
  653. request.session.flash(('info', u'Le pôle a été supprimé !'))
  654. DBSession.delete(Pole)
  655. return HTTPFound(location=request.route_url('list_task', year=year))
  656. @view_config(route_name='list_salles', renderer='jm2l:templates/Salles/list.mako')
  657. def list_salles(request):
  658. if request.user is None:
  659. # Don't answer to users that aren't logged
  660. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  661. if not request.user.Staff:
  662. # Don't answer to users that aren't logged
  663. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  664. DicSalle = {}
  665. years = DBSession.query( JM2L_Year ).all()
  666. for year in years:
  667. salles = DBSession.query( Salles )\
  668. .filter( Salles.year_uid==year.year_uid )\
  669. .order_by(Salles.name).all()
  670. DicSalle[year] = salles
  671. return {'DicSalle': DicSalle }
  672. @view_config(route_name='list_salles_phy', renderer='jm2l:templates/Salles/list_phy.mako')
  673. def list_salles_phy(request):
  674. if request.user is None:
  675. # Don't answer to users that aren't logged
  676. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  677. if not request.user.Staff:
  678. # Don't answer to users that aren't logged
  679. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  680. salles_phy = DBSession.query( SallePhy )\
  681. .order_by(SallePhy.name).all()
  682. return {'DicSallePhy': salles_phy }
  683. @view_config(route_name='handle_salle', renderer='jm2l:templates/Salles/salle.mako')
  684. def handle_salle(request):
  685. if request.user is None:
  686. # Don't answer to users that aren't logged
  687. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  688. if not request.user.Staff:
  689. # Don't answer to users that aren't logged
  690. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  691. salle_id = request.matchdict.get('salle_id')
  692. if salle_id:
  693. Salle = Salles.by_id(int(salle_id))
  694. if not Salle:
  695. raise HTTPNotFound()
  696. form = EditSalleForm(request.POST, Salle, meta={'csrf_context': request.session})
  697. else:
  698. Salle = Salles()
  699. form = SalleForm(request.POST, Salle, meta={'csrf_context': request.session})
  700. form.year_uid.choices = map(tuple, DBSession.query(JM2L_Year.year_uid, JM2L_Year.year_uid).all())
  701. form.phy_salle_id.choices = map(tuple, DBSession.query(SallePhy.uid, SallePhy.name).all())
  702. if request.method == 'POST' and form.validate():
  703. form.populate_obj(Salle)
  704. if 'uid' in form._fields.keys():
  705. DBSession.merge(Salle)
  706. else:
  707. DBSession.add(Salle)
  708. return HTTPFound(location=request.route_url('list_salles'))
  709. return {'form':form }
  710. @view_config(route_name='handle_salle_phy', renderer='jm2l:templates/Salles/salle_phy.mako')
  711. def handle_salle_phy(request):
  712. if request.user is None:
  713. # Don't answer to users that aren't logged
  714. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  715. if not request.user.Staff:
  716. # Don't answer to users that aren't logged
  717. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  718. salle_id = request.matchdict.get('salle_id')
  719. if salle_id:
  720. Salle = SallePhy.by_id(int(salle_id))
  721. orig_slug = Salle.slug
  722. if not Salle:
  723. raise HTTPNotFound()
  724. form = EditSallePhyForm(request.POST, Salle, meta={'csrf_context': request.session})
  725. else:
  726. Salle = SallePhy()
  727. orig_slug = None
  728. form = SallePhyForm(request.POST, Salle, meta={'csrf_context': request.session})
  729. if request.method == 'POST' and form.validate():
  730. form.populate_obj(Salle)
  731. dest_slug = slugify(Salle.name)
  732. # Do a check in order to move attached files if any
  733. if orig_slug and orig_slug!=dest_slug:
  734. try:
  735. mp = MediaPath().move_mediapath('salle', orig_slug, dest_slug)
  736. except RuntimeError, err:
  737. request.session.flash(('error', u"Le nom de cette salle est déjà utilisé : " + err.message))
  738. return {'form': form}
  739. Salle.slug = slugify(Salle.name)
  740. if 'uid' in form._fields.keys():
  741. DBSession.merge(Salle)
  742. else:
  743. DBSession.add(Salle)
  744. return HTTPFound(location=request.route_url('list_salles'))
  745. return {'form':form }
  746. @view_config(route_name='action_salle')
  747. def action_salle(request):
  748. if request.user is None:
  749. # Don't answer to users that aren't logged
  750. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  751. if not request.user.Staff:
  752. # Don't answer to users that aren't logged
  753. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  754. action = request.matchdict.get('action')
  755. salle_id = request.matchdict.get('salle_id')
  756. Salle = Salles.by_id(int(salle_id))
  757. if not Salle:
  758. raise HTTPNotFound()
  759. if action=='delete':
  760. request.session.flash(('info', u'La Salle a été supprimée !'))
  761. DBSession.delete(Salle)
  762. return HTTPFound(location=request.route_url('list_salles'))
  763. ## =-=- Here, We handle HTTP requests - User Logged Part -=-=
  764. @view_config(route_name='exchange', renderer="jm2l:templates/Logistique/Logistique.mako")
  765. def exchange(request):
  766. modtype = request.matchdict.get('modtype', None)
  767. action = request.matchdict.get('action', None)
  768. uid = int(request.matchdict.get('id', -1))
  769. Exch = Exchange.by_id(uid)
  770. if not Exch:
  771. MainTab = {
  772. 'Exchanges':Exchange,
  773. 'Type':modtype[-1:],
  774. 'reload':True,
  775. 'logged_in':request.authenticated_userid
  776. }
  777. return MainTab
  778. if action in ['delete', 'accept', 'refuse', 'deal']:
  779. if action=='delete': # delete exchange
  780. DBSession.delete(Exch)
  781. elif action=='accept': # accept exchange
  782. Exch.exch_done=True
  783. DBSession.merge(Exch)
  784. elif action=='refuse': # refuse exchange
  785. Exch.exch_done=False
  786. if Exch.exch_state=="Ask":
  787. Exch.provider_id = None
  788. elif Exch.exch_state=="Proposal":
  789. Exch.asker_id = None
  790. DBSession.merge(Exch)
  791. elif action=='deal':
  792. # ask to deal the exchange
  793. if Exch.exch_state=="Ask":
  794. Exch.provider_id = request.user.uid
  795. elif Exch.exch_state=="Proposal":
  796. Exch.asker_id = request.user.uid
  797. # Return javascript to parent page
  798. response = render_to_response('jm2l:templates/modals_js.mako',
  799. {'modtype':modtype, 'action':action},
  800. request=request)
  801. response.content_type = 'text/javascript'
  802. return response
  803. else:
  804. MainTab = {
  805. 'Exchanges':Exchange,
  806. 'Type':modtype[-1:],
  807. 'reload':True,
  808. 'logged_in':request.authenticated_userid
  809. }
  810. return MainTab
  811. @view_config(route_name='miam')
  812. def miam(request):
  813. if request.user is None:
  814. # Don't answer to users that aren't logged
  815. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  816. miam_form = MiamForm(request.POST, request.user, meta={'csrf_context': request.session})
  817. if request.method == 'POST' and miam_form.validate():
  818. FicheSejour = Sejour.by_user(request.user.uid, CurrentYear)
  819. if FicheSejour:
  820. Update=True
  821. else:
  822. FicheSejour = Sejour()
  823. FicheSejour.created = datetime.datetime.now()
  824. Update=False
  825. Repas=0
  826. for num, item in enumerate(['RepasVendredi', 'RepasSamediMidi', 'RepasSamediSoir']):
  827. if request.params.get(item)==u"1":
  828. Repas += 2**num
  829. FicheSejour.repas = Repas
  830. FicheSejour.repas_allerg = request.params.get('Allergies')
  831. FicheSejour.repas_contr = request.params.get('Contraintes')
  832. FicheSejour.user_id = request.user.uid
  833. FicheSejour.for_year = CurrentYear
  834. if Update:
  835. DBSession.merge(FicheSejour)
  836. else:
  837. DBSession.add(FicheSejour)
  838. request.session.flash(('info',u'Votre fiche a été mise à jour avec succès'))
  839. else:
  840. request.session.flash(('error',u'Un problème est survenu'))
  841. return HTTPFound(location='/MesJM2L#Miam')
  842. @view_config(route_name='sejour')
  843. def sejour(request):
  844. if request.user is None:
  845. # Don't answer to users that aren't logged
  846. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  847. if request.method == 'POST':
  848. FicheSejour = Sejour.by_user(request.user.uid, CurrentYear)
  849. if FicheSejour:
  850. Update=True
  851. else:
  852. FicheSejour = Sejour()
  853. FicheSejour.created = datetime.datetime.now()
  854. Update=False
  855. FicheSejour.user_id = request.user.uid
  856. FicheSejour.last_change = datetime.datetime.now()
  857. FicheSejour.for_year = CurrentYear
  858. # Arrival
  859. ArrDate = datetime.datetime.strptime(request.params.get('Arrival:Day'),"%d/%m/%y")
  860. ArrTime = datetime.datetime.strptime(request.params.get('Arrival:Hour'),"%H:%M")
  861. FicheSejour.arrival_time = datetime.datetime.combine(ArrDate.date(), ArrTime.time())
  862. ArrivalCheck=0
  863. for num, item in enumerate(['Arrival:PMR', 'Arrival:Cov', 'Arrival:Bras', 'Arrival:Other']):
  864. if request.params.get(item):
  865. ArrivalCheck += 2**num
  866. FicheSejour.arrival_check = ArrivalCheck
  867. FicheSejour.arrival_text = request.params.get('Arrival:Comment')
  868. FicheSejour.arrival_place = request.params.get('Arrival:Place')
  869. # Departure
  870. DepDate = datetime.datetime.strptime(request.params.get('Departure:Day'),"%d/%m/%y")
  871. DepTime = datetime.datetime.strptime(request.params.get('Departure:Hour'),"%H:%M")
  872. FicheSejour.depart_time = datetime.datetime.combine(DepDate.date(), DepTime.time())
  873. DepartCheck=0
  874. for num, item in enumerate(['Departure:PMR', 'Departure:Cov', 'Departure:Bras', 'Departure:Other']):
  875. if request.params.get(item):
  876. DepartCheck += 2**num
  877. FicheSejour.depart_check = DepartCheck
  878. FicheSejour.depart_text = request.params.get('Departure:Comment')
  879. FicheSejour.depart_place = request.params.get('Departure:Place')
  880. if Update:
  881. DBSession.merge(FicheSejour)
  882. request.session.flash(('info',u'Vos modifications de séjour ont été pris en compte.'))
  883. else:
  884. DBSession.add(FicheSejour)
  885. request.session.flash(('info',u'\\o/ Votre séjour est enregistré ! Complétez la partie Logistique.'))
  886. return HTTPFound(location='/MesJM2L#Sejour')
  887. @view_config(route_name='orga')
  888. def orga(request):
  889. if request.user is None:
  890. # Don't answer to users that aren't logged
  891. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  892. if request.method == 'POST':
  893. FicheSejour = Sejour.by_user(request.user.uid, CurrentYear)
  894. UpdateOrga=False
  895. if FicheSejour:
  896. Update=True
  897. if FicheSejour.orga_part:
  898. UpdateOrga=True
  899. else:
  900. FicheSejour = Sejour()
  901. FicheSejour.created = datetime.datetime.now()
  902. Update=False
  903. FicheSejour.user_id = request.user.uid
  904. FicheSejour.last_change = datetime.datetime.now()
  905. FicheSejour.for_year = CurrentYear
  906. OrgaPart=0
  907. for item in request.params:
  908. try:
  909. nb = int(item[1:])
  910. except:
  911. continue
  912. OrgaPart += 2**nb
  913. FicheSejour.orga_part = OrgaPart
  914. if UpdateOrga:
  915. request.session.flash(('info',u'Vos modifications de participation à l\'organisation ont été pris en compte.'))
  916. else:
  917. request.session.flash(('info',u'\\o/ Votre participation à l\'organisation est enregistrée !'))
  918. if Update:
  919. DBSession.merge(FicheSejour)
  920. else:
  921. DBSession.add(FicheSejour)
  922. return HTTPFound(location='/MesJM2L#Organisation')
  923. @view_config(route_name='vote_logo')
  924. def vote_logo(request):
  925. if request.user is None:
  926. # Don't answer to users that aren't logged
  927. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  928. else:
  929. vote = int(request.matchdict.get('num', -1))
  930. come = request.params.get('come_from')
  931. if vote:
  932. request.user.vote_logo=vote
  933. DBSession.merge(request.user)
  934. request.session.flash(('info',u'Votre vote à été pris en compte.'))
  935. return HTTPFound('/')
  936. else:
  937. request.session.flash(('warning',u"Votre vote n'a été pris en compte."))
  938. if come:
  939. return HTTPFound(location=come)
  940. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  941. @view_config(route_name='list_users_csv', renderer="string")
  942. def list_users_csv(request):
  943. for_year = int(request.matchdict.get('year', CurrentYear))
  944. if request.user is None:
  945. # Don't answer to users that aren't logged
  946. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  947. if not request.user.Staff:
  948. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  949. stmt = (DBSession.query(Sejour).filter(Sejour.for_year==for_year)).subquery()
  950. # stmt_event = (DBSession.query(User_Event).filter()
  951. adalias = aliased(Sejour, stmt)
  952. Data = DBSession.query(User, adalias ) \
  953. .outerjoin(adalias)\
  954. .order_by(User.slug)\
  955. .all()
  956. FileHandle = StringIO.StringIO()
  957. fileWriter = csv.writer(FileHandle, delimiter=',', quotechar='"', quoting=csv.QUOTE_NONNUMERIC)
  958. fileWriter.writerow(["Identifiant_JM2L", "Nom", "Prenom", "Status_%s" % for_year ])
  959. for user, sejour in Data:
  960. tab_identifier = [user.slug, user.nom.encode('utf-8'), user.prenom.encode('utf-8'), '']
  961. if user.is_IntervenantOnYear(CurrentYear):
  962. tab_identifier[3] = "Intervenant"
  963. elif user.Staff:
  964. tab_identifier[3] = "Staff"
  965. elif sejour and sejour.orga_part:
  966. tab_identifier[3] = "Bénévole"
  967. elif sejour:
  968. tab_identifier[3] = "Visiteur"
  969. else:
  970. continue
  971. fileWriter.writerow(tab_identifier)
  972. return Response(app_iter=FileHandle.getvalue(), content_type="text/csv")
  973. @view_config(route_name='list_users', renderer="jm2l:templates/Participant/list_users.mako")
  974. def list_users(request):
  975. for_year = int(request.matchdict.get('year', CurrentYear))
  976. if request.user is None:
  977. # Don't answer to users that aren't logged
  978. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  979. if not request.user.Staff:
  980. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  981. stmt = (DBSession.query(Sejour).filter(Sejour.for_year==for_year)).subquery()
  982. adalias = aliased(Sejour, stmt)
  983. Data = DBSession.query(User, adalias ) \
  984. .outerjoin(adalias)\
  985. .all()
  986. Repas = DBSession.query(Sejour.repas) \
  987. .filter(Sejour.for_year == for_year ) \
  988. .all()
  989. DicRepas = {"Ven":0, "Midi":0, "Soir":0}
  990. for r in Repas:
  991. if r[0] is None:
  992. continue
  993. if (r[0] & 1 == 1): DicRepas["Ven"]+=1
  994. if (r[0] & 2 == 2): DicRepas["Midi"]+=1
  995. if (r[0] & 4 == 4): DicRepas["Soir"]+=1
  996. return { 'Users':Data, 'UserEvent' : User_Event, "DicRepas":DicRepas, "for_year": for_year }
  997. @view_config(route_name='list_orga', renderer="jm2l:templates/Participant/list_orga.mako")
  998. def list_orga(request):
  999. for_year = int(request.matchdict.get('year', CurrentYear))
  1000. if request.user is None:
  1001. # Don't answer to users that aren't logged
  1002. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1003. if not request.user.Staff:
  1004. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  1005. Data = DBSession.query(User, Sejour)\
  1006. .outerjoin(Sejour)\
  1007. .filter(Sejour.for_year == for_year)\
  1008. .all()
  1009. return { 'Users':Data }
  1010. @view_config(route_name='drop_sejour')
  1011. def drop_sejour(request):
  1012. if request.user is None:
  1013. # Don't answer to users that aren't logged
  1014. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1015. # Feed FicheSejour if any
  1016. FicheSejour = Sejour.by_user(request.user.uid, CurrentYear)
  1017. if FicheSejour:
  1018. DBSession.delete(FicheSejour)
  1019. request.session.flash(('warning', u'Votre participation %s a été supprimé avec succès.' % CurrentYear ))
  1020. else:
  1021. raise HTTPNotFound()
  1022. return HTTPFound(location='/MesJM2L#Sejour')
  1023. @view_config(route_name='jm2l', renderer="jm2l:templates/jm2l.mako")
  1024. def jm2l_page(request):
  1025. if request.user is None:
  1026. # Don't answer to users that aren't logged
  1027. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1028. UserNum = request.params.get('user')
  1029. if UserNum:
  1030. profil = User.by_id(int(UserNum))
  1031. if not profil:
  1032. raise HTTPNotFound()
  1033. if not request.user.Staff:
  1034. raise HTTPForbidden(u'Vous n\'avez pas l\'autorité suffisante pour effectuer cette action.')
  1035. else:
  1036. profil = request.user
  1037. FicheSejour = Sejour()
  1038. FicheSejour.created = datetime.datetime.now()
  1039. # Build Form
  1040. profil_form = ProfilForm(request.POST, profil, meta={'csrf_context': request.session})
  1041. miam_form = MiamForm(request.POST, profil, meta={'csrf_context': request.session})
  1042. # Feed FicheSejour if any
  1043. FicheSejour = Sejour.by_user(profil.uid, CurrentYear)
  1044. if FicheSejour:
  1045. if FicheSejour.repas is not None:
  1046. for num, item in enumerate(['RepasVendredi', 'RepasSamediMidi', 'RepasSamediSoir']):
  1047. if FicheSejour.repas & 2**num:
  1048. miam_form._fields[item].data = "1"
  1049. else:
  1050. miam_form._fields[item].data = "0"
  1051. miam_form._fields['Allergies'].data = FicheSejour.repas_allerg
  1052. miam_form._fields['Contraintes'].data = FicheSejour.repas_contr
  1053. if request.method == 'POST' and profil_form.validate():
  1054. ToDelete = list()
  1055. # First, we remove entries no more present
  1056. for obj in profil_form.tiersship.object_data:
  1057. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  1058. profil_form.tiersship.entries )
  1059. if not MatchEntry:
  1060. ToDelete.append(obj)
  1061. # Then, it's time to consider new entries
  1062. for entry in profil_form.tiersship.entries:
  1063. if entry.object_data is None:
  1064. TmpUser = User_Tiers()
  1065. entry.object_data = TmpUser
  1066. profil.tiersship.append(TmpUser)
  1067. profil_form.tiersship.object_data = profil.tiersship
  1068. profil_form.populate_obj(profil)
  1069. # We should remove it as it's not in original data
  1070. for obj in ToDelete:
  1071. #profil.tiersship.remove(obj)
  1072. DBSession.delete(obj)
  1073. profil.last_change = datetime.datetime.utcnow()
  1074. profil.slug = slugify(remove_accents('%s %s' % (profil.prenom, profil.nom)).lower().strip())
  1075. DBSession.merge(profil)
  1076. request.session.flash(('info',u'Votre fiche a été mise à jour avec succès'))
  1077. MainTab = {'participer':'active',
  1078. 'Places':Place.get_list(False),
  1079. 'DBTiers':Tiers,
  1080. 'DBTiersOpt':TiersOpt,
  1081. 'Exchanges':Exchange,
  1082. 'profil_form':profil_form,
  1083. 'miam_form':miam_form,
  1084. 'uprofil':profil,
  1085. 'logged_in':request.authenticated_userid
  1086. }
  1087. return MainTab
  1088. @view_config(route_name='modal', renderer="jm2l:templates/modals.mako")
  1089. def Modal(request):
  1090. year = int(request.matchdict.get('year', None))
  1091. modtype = request.matchdict.get('modtype', None)
  1092. uid = int(request.matchdict.get('id', -1))
  1093. session = request.session
  1094. if modtype=='Password':
  1095. form = UserPasswordForm(request.POST, request.user, meta={'csrf_context': request.session})
  1096. if request.method == 'POST' and form.validate():
  1097. response = render_to_response('jm2l:templates/modals_js.mako',
  1098. {'modtype':modtype},
  1099. request=request)
  1100. request.user.password = argon2.using(rounds=4).hash(form.password.data)
  1101. DBSession.merge(request.user)
  1102. response.content_type = 'text/javascript'
  1103. return response
  1104. if modtype=='UserPicture':
  1105. form = None
  1106. if request.method == 'POST':
  1107. response = render_to_response('jm2l:templates/modals_js.mako',
  1108. {'modtype':modtype},
  1109. request=request)
  1110. response.content_type = 'text/javascript'
  1111. return response
  1112. if modtype=='Place':
  1113. if uid>0:
  1114. place = Place.by_id(uid)
  1115. if not place:
  1116. raise HTTPNotFound()
  1117. form = PlaceUpdateForm(request.POST, place, meta={'csrf_context': request.session})
  1118. else:
  1119. place = Place()
  1120. form = PlaceCreateForm(request.POST, meta={'csrf_context': request.session})
  1121. if request.method == 'POST' and form.validate():
  1122. form.populate_obj(place)
  1123. place.created_by=request.user.uid
  1124. place.slug = slugify(place.name)
  1125. if uid>0:
  1126. DBSession.merge(place)
  1127. else:
  1128. DBSession.add(place)
  1129. response = render_to_response('jm2l:templates/modals_js.mako',
  1130. {'modtype':modtype},
  1131. request=request)
  1132. response.content_type = 'text/javascript'
  1133. return response
  1134. if modtype in ['AskC', 'AskH', 'AskM', 'PropC', 'PropH', 'PropM']:
  1135. if uid>0:
  1136. Exch = Exchange.by_id(uid)
  1137. if not Exch:
  1138. raise HTTPNotFound()
  1139. if modtype in ['AskC','PropC']:
  1140. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  1141. start_place = Exch.Itin.start_place,
  1142. arrival_place = Exch.Itin.arrival_place,
  1143. Hour_start = Exch.start_time.strftime("%H:%M"),
  1144. Day_start = Exch.start_time.strftime("%w"),
  1145. exch_id = uid, meta={'csrf_context': request.session}
  1146. )
  1147. elif modtype in ['AskM','PropM']:
  1148. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  1149. description = Exch.description,
  1150. exch_categ = Exch.exch_categ,
  1151. Hour_start = Exch.start_time.strftime("%H:%M"),
  1152. Day_start = Exch.start_time.strftime("%w"),
  1153. Hour_end = Exch.end_time.strftime("%H:%M"),
  1154. Day_end = Exch.end_time.strftime("%w"),
  1155. exch_id = uid, meta={'csrf_context': request.session}
  1156. )
  1157. elif modtype in ['AskH','PropH']:
  1158. form = globals()["Update%sForm" % modtype](request.POST, Exch,
  1159. description = Exch.description,
  1160. exch_categ = Exch.exch_categ,
  1161. Day_start = Exch.start_time.strftime("%w"),
  1162. exch_id = uid, meta={'csrf_context': request.session}
  1163. )
  1164. # Itinerary, first get itinerary
  1165. if 0:
  1166. form.itin.form.start_place.data = Exch.Itin.start_place
  1167. form.itin.form.arrival_place.data = Exch.Itin.arrival_place
  1168. form.dateform.form.Hour.data = Exch.start_time.strftime("%H:%M")
  1169. form.dateform.form.Day.data = Exch.start_time.strftime("%w")
  1170. form.exch_id.data = uid
  1171. else:
  1172. Exch = Exchange()
  1173. form = globals()["%sForm" % modtype](request.POST, meta={'csrf_context': request.session})
  1174. if modtype in ['AskC', 'PropC']:
  1175. # Put some place on form
  1176. Places = DBSession.query(Place.place_id, Place.display_name)\
  1177. .order_by('name').all()
  1178. form.start_place.choices = Places
  1179. form.arrival_place.choices = Places
  1180. if modtype in ['PropH']:
  1181. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  1182. .filter( Exchange_Cat.exch_type=='H' ).all()
  1183. form.place_id.choices = DBSession.query( Place.place_id, Place.display_name)\
  1184. .filter( Place.created_by==request.user.uid ).all()
  1185. if modtype in ['AskM', 'PropM']:
  1186. form.exch_categ.choices = DBSession.query( Exchange_Cat.cat_id, Exchange_Cat.exch_subtype)\
  1187. .filter( Exchange_Cat.exch_type=='M' ).all()
  1188. if request.method == 'POST' and form.validate():
  1189. # Form has been validated, it's time to create our Exchange
  1190. Exch.for_year = year
  1191. Exch.exch_state = {'Ask':'Ask', 'Prop':'Proposal'}[modtype[:-1]]
  1192. Exch.exch_type = modtype[-1:]
  1193. if modtype in ['AskC', 'PropC']:
  1194. # Itinerary, first Let's see if itinerary exist
  1195. Itinerary = DBSession.query(Itineraire)\
  1196. .filter(Itineraire.start_place==form.start_place.data) \
  1197. .filter(Itineraire.arrival_place==form.arrival_place.data) \
  1198. .filter(Itineraire.tr_voiture==True) \
  1199. .first()
  1200. if not Itinerary: # Not exist yet !
  1201. Itinerary = Itineraire(start_place=form.start_place.data, \
  1202. arrival_place=form.arrival_place.data, \
  1203. tr_voiture=True, \
  1204. created_by=1
  1205. )
  1206. DBSession.add(Itinerary)
  1207. DBSession.flush()
  1208. Exch.itin_id = Itinerary.itin_id
  1209. # Start Time
  1210. StartEvent = DBSession.query(JM2L_Year.start_time).filter(JM2L_Year.year_uid==year).first()
  1211. Week = StartEvent[0].strftime("%W")
  1212. # populate
  1213. form.populate_obj(Exch)
  1214. if modtype in ['AskC', 'PropC']:
  1215. Exch.itin_id = Itinerary.itin_id
  1216. if form._fields.has_key("Hour_start"):
  1217. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  1218. int(form.Day_start.data), form.Hour_start.data), "%Y %W %w %H:%M")
  1219. Exch.start_time = TargetTime
  1220. elif form._fields.has_key("Day_start"):
  1221. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  1222. int(form.Day_start.data)), "%Y %W %w")
  1223. Exch.start_time = TargetTime
  1224. if form._fields.has_key("Hour_end"):
  1225. TargetTime = datetime.datetime.strptime('%d %d %d %s' % (year, int(Week), \
  1226. int(form.Day_end.data), form.Hour_end.data), "%Y %W %w %H:%M")
  1227. Exch.end_time = TargetTime
  1228. elif form._fields.has_key("Day_end"):
  1229. TargetTime = datetime.datetime.strptime('%d %d %d' % (year, int(Week), \
  1230. int(form.Day_end.data)), "%Y %W %w")
  1231. Exch.end_time = TargetTime
  1232. Exch.last_change = datetime.datetime.utcnow()
  1233. if Exch.exch_state=='Ask':
  1234. Exch.asker_id = request.user.uid
  1235. elif Exch.exch_state=='Proposal':
  1236. Exch.provider_id = request.user.uid
  1237. #print vars(form.itin.form)
  1238. if uid>0:
  1239. DBSession.merge(Exch)
  1240. else:
  1241. DBSession.add(Exch)
  1242. response = render_to_response('jm2l:templates/modals_js.mako',
  1243. {'modtype':modtype},
  1244. request=request)
  1245. response.content_type = 'text/javascript'
  1246. return response
  1247. # Fallback to HTML Display with errors
  1248. return {'modtype':modtype, 'form':form, 'update':uid>0,
  1249. 'logged_in':request.authenticated_userid }
  1250. if modtype in ['ShowC', 'ShowH', 'ShowM']:
  1251. if uid>0:
  1252. Exch = Exchange.by_id(uid)
  1253. if not Exch:
  1254. raise HTTPNotFound()
  1255. else:
  1256. raise HTTPNotFound()
  1257. # Show Details around the Current Exchange
  1258. return {'modtype':modtype, 'Exch':Exch, 'logged_in':request.authenticated_userid }
  1259. MainTab = {'modtype':modtype, 'form':form, 'update':uid>0, 'uid':uid,
  1260. 'DisplayYear':year, 'session':session,
  1261. 'logged_in':request.authenticated_userid }
  1262. return MainTab
  1263. @view_config(route_name='participer', renderer="jm2l:templates/Participer.mako")
  1264. def participer(request):
  1265. session = request.session
  1266. session['year'] = CurrentYear
  1267. TmpUsr = User()
  1268. form = UserRegisterForm(request.POST, TmpUsr, meta={'csrf_context': request.session})
  1269. MyLink=None
  1270. if request.method == 'POST' and form.validate():
  1271. # Prepare mailer
  1272. form.populate_obj(TmpUsr)
  1273. TmpUsr.nom = TmpUsr.nom.capitalize()
  1274. TmpUsr.prenom = TmpUsr.prenom.capitalize()
  1275. TmpUsr.slug = slugify(remove_accents('%s %s' % (form.prenom.data, form.nom.data)).lower().strip())
  1276. TmpUsr.password = TmpUsr.my_hash
  1277. if len(TmpUsr.slug):
  1278. CheckExist = DBSession.query(User)\
  1279. .filter(User.slug==TmpUsr.slug)\
  1280. .first()
  1281. else:
  1282. CheckExist=None
  1283. if CheckExist:
  1284. MyLink = CheckExist.my_hash
  1285. NewUser = CheckExist
  1286. else:
  1287. DBSession.add(TmpUsr)
  1288. DBSession.flush()
  1289. MyLink = TmpUsr.my_hash
  1290. NewUser = TmpUsr
  1291. # Send the Welcome Mail
  1292. mailer = request.registry['mailer']
  1293. # Prepare Plain Text Message :
  1294. Mail_template = Template(filename='jm2l/templates/mail_plain.mako')
  1295. mail_plain = Mail_template.render(request=request, User=NewUser, action="Welcome")
  1296. # Prepare HTML Message :
  1297. Mail_template = Template(filename='jm2l/templates/mail_html.mako')
  1298. mail_html = Mail_template.render(request=request, User=NewUser, action="Welcome")
  1299. # Prepare Message
  1300. message = Message(subject="[JM2L] Mon inscription au site web JM2L",
  1301. sender="contact@jm2l.linux-azur.org",
  1302. recipients=[NewUser.mail or TmpUsr.mail],
  1303. body=mail_plain, html=mail_html)
  1304. message.add_bcc("spam@style-python.fr")
  1305. mailer.send(message)
  1306. request.session.flash(('info',u"Un mail vous a été envoyé afin de continuer votre quête !"))
  1307. MainTab = {'programme':'','presse':'', 'plan':'',
  1308. 'participer':'active', 'form':form, "link": MyLink,
  1309. 'logged_in':request.authenticated_userid }
  1310. return MainTab
  1311. @view_config(route_name='year')
  1312. def change_year(request):
  1313. year = int(request.matchdict.get('year', -1))
  1314. session = request.session
  1315. if year>-1:
  1316. session['year'] = year
  1317. return HTTPFound(location='/%s/' % year)
  1318. return HTTPFound(location=request.route_url('home', year=''))
  1319. @view_config(route_name='pict_user', renderer="jm2l:templates/Profil/pict_user.mako")
  1320. def pict_user(request):
  1321. return {"uprofil":request.user}
  1322. @view_config(route_name='pict_salle', renderer="jm2l:templates/Salles/pict_salle.mako")
  1323. def pict_salle(request):
  1324. salle_id = int(request.matchdict.get('salle_id', -1))
  1325. return {"Salles":Salles, "IdSalle":salle_id}
  1326. @view_config(route_name='event', renderer="jm2l:templates/view_event.mako")
  1327. def show_event(request):
  1328. year = int(request.matchdict.get('year', -1))
  1329. event_id = request.matchdict.get('event_id')
  1330. if event_id.isdigit():
  1331. TheEvent = Event.by_id(event_id)
  1332. if TheEvent is None:
  1333. raise HTTPNotFound()
  1334. else:
  1335. TheEvent = Event.by_slug(event_id, year)
  1336. if TheEvent is None:
  1337. raise HTTPNotFound()
  1338. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1339. 'event':TheEvent, 'logged_in':request.authenticated_userid, "Salles":Salles }
  1340. return MainTab
  1341. @view_config(route_name='link_event_user')
  1342. def link_event_user(request):
  1343. """ Get user and add it to current event """
  1344. if request.user is None:
  1345. # Don't answer to users that aren't logged
  1346. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1347. year = int(request.matchdict.get('year', -1))
  1348. form = AddIntervenant(request.POST, meta={'csrf_context': request.session})
  1349. intervention = request.matchdict.get('intervention', None)
  1350. TargetEvent = Event.by_id(form.event_uid.data)
  1351. Exist = User.by_id(form.intervenant.data)
  1352. if not Exist:
  1353. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre intervenant !"))
  1354. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1355. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1356. else:
  1357. TargetUser = Exist
  1358. uev = User_Event(year_uid=year, role=u"Animateur d'un évènement JM2L", user_uid=TargetUser.uid)
  1359. TargetEvent.interventions.append( uev )
  1360. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1361. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1362. @view_config(route_name='link_event_tiers')
  1363. def link_event_tiers(request):
  1364. """ Create user if not exist, add it to current event """
  1365. if request.user is None:
  1366. # Don't answer to users that aren't logged
  1367. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1368. year = int(request.matchdict.get('year', -1))
  1369. form = AddTiers(request.POST, meta={'csrf_context': request.session})
  1370. intervention = request.matchdict.get('intervention', None)
  1371. TargetEvent = Event.by_id(form.event_uid.data)
  1372. Exist = Tiers.by_id(form.tiers.data)
  1373. if not Exist:
  1374. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre entité !"))
  1375. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1376. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1377. else:
  1378. TargetTiers = Exist
  1379. Matching = DBSession.query(Role_Tiers)\
  1380. .filter(Role_Tiers.year_uid==year)\
  1381. .filter(Role_Tiers.tiers_role=="Exposant")\
  1382. .filter(Role_Tiers.tiers_uid==TargetTiers.uid)\
  1383. .filter(Role_Tiers.event_uid==TargetEvent.uid)\
  1384. .all()
  1385. if len(Matching)==0:
  1386. tev = Role_Tiers(year_uid=year, tiers_role="Exposant", tiers_uid=TargetTiers.uid, event_uid=TargetEvent.uid)
  1387. DBSession.add(tev)
  1388. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1389. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1390. @view_config(route_name='delete_link_u')
  1391. def delete_link_event_user(request):
  1392. """ Create user if not exist, add it to current event """
  1393. if request.user is None:
  1394. # Don't answer to users that aren't logged
  1395. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1396. year = int(request.matchdict.get('year', -1))
  1397. intervention = request.matchdict.get('intervention', None)
  1398. TargetEvent = Event.by_id( request.params.get('eid') )
  1399. Exist = User.by_id( request.params.get('uid') )
  1400. if not Exist:
  1401. request.session.flash(('error',u"Une erreur s'est produite lors de votre suppression !"))
  1402. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1403. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1404. else:
  1405. TargetUser = Exist
  1406. Matching = DBSession.query(User_Event)\
  1407. .filter(User_Event.year_uid==year)\
  1408. .filter(User_Event.user_uid==TargetUser.uid)\
  1409. .filter(User_Event.event_uid==TargetEvent.uid)\
  1410. .all()
  1411. if len(Matching)==0:
  1412. request.session.flash(('error',u"Une erreur s'est produite lors de la suppression !"))
  1413. else:
  1414. for item in Matching:
  1415. DBSession.delete(item)
  1416. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1417. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1418. @view_config(route_name='delete_link_t')
  1419. def delete_link_event_tiers(request):
  1420. """ Create user if not exist, add it to current event """
  1421. if request.user is None:
  1422. # Don't answer to users that aren't logged
  1423. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1424. year = int(request.matchdict.get('year', -1))
  1425. intervention = request.matchdict.get('intervention', None)
  1426. TargetEvent = Event.by_id( request.params.get('uid') )
  1427. Exist = Tiers.by_id( request.params.get('tid') )
  1428. if not Exist:
  1429. request.session.flash(('error',u"Une erreur s'est produite lors de l'ajout de votre entité !"))
  1430. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1431. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid)))
  1432. else:
  1433. TargetTiers = Exist
  1434. Matching = DBSession.query(Role_Tiers)\
  1435. .filter(Role_Tiers.year_uid==year)\
  1436. .filter(Role_Tiers.tiers_role=="Exposant")\
  1437. .filter(Role_Tiers.tiers_uid==TargetTiers.uid)\
  1438. .filter(Role_Tiers.event_uid==TargetEvent.uid)\
  1439. .all()
  1440. if len(Matching)==0:
  1441. request.session.flash(('error',u"Une erreur s'est produite lors de la suppression de votre entité !"))
  1442. else:
  1443. for item in Matching:
  1444. DBSession.delete(item)
  1445. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1446. year=str(year), intervention=intervention, event_id=str(TargetEvent.uid), _anchor="Tiers"))
  1447. @view_config(route_name='delete_event')
  1448. def delete_event(request):
  1449. if request.user is None:
  1450. # Don't answer to users that aren't logged
  1451. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1452. year = int(request.matchdict.get('year', -1))
  1453. event_id = request.matchdict.get('event_id')
  1454. intervention = request.matchdict.get('intervention', None)
  1455. # Check intervention
  1456. if not intervention in ['Stand', 'Table_ronde', 'Atelier', 'Conference', 'Concert']:
  1457. raise HTTPNotFound(u"Ce type d'évènement n'est pas reconnu")
  1458. # We should remove all links before to remove the event
  1459. if event_id.isdigit():
  1460. TheEvent = Event.by_id(event_id)
  1461. if TheEvent is None:
  1462. raise HTTPNotFound(u"Cette réference n'existe pas")
  1463. else:
  1464. TheEvent = Event.by_slug(event_id, year)
  1465. if TheEvent is None:
  1466. raise HTTPNotFound(u"Cette réference n'existe pas")
  1467. # Remove Roles
  1468. Roles_Link = DBSession.query(Role_Tiers).filter(Role_Tiers.event_uid==TheEvent.uid).all()
  1469. for tmp in Roles_Link:
  1470. DBSession.delete(tmp)
  1471. # Remove Intervenant
  1472. User_Link = DBSession.query(User_Event).filter(User_Event.event_uid==TheEvent.uid).all()
  1473. for tmp in User_Link:
  1474. DBSession.delete(tmp)
  1475. # Remove attachment if any
  1476. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1477. shutil.rmtree(SRCPath, ignore_errors=True)
  1478. # Remove Event
  1479. DBSession.delete(TheEvent)
  1480. return HTTPFound(location=request.route_url('jm2l', _anchor="Interventions"))
  1481. @view_config(route_name='edit_event', renderer="jm2l:templates/edit_event.mako")
  1482. def edit_event(request):
  1483. if request.user is None:
  1484. # Don't answer to users that aren't logged
  1485. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1486. year = int(request.matchdict.get('year', -1))
  1487. event_id = request.matchdict.get('event_id')
  1488. intervention = request.matchdict.get('intervention', None)
  1489. IntervLabel = intervention.replace('_',' ').lower()
  1490. if intervention=='Conference':
  1491. IntervLabel = u'conférence'
  1492. elif intervention=='Table_ronde':
  1493. IntervLabel = u'Table ronde'
  1494. # Check intervention
  1495. if not intervention in ['Stand', 'Table_ronde', 'Atelier', 'Conference', 'Concert']:
  1496. raise HTTPNotFound(u"Ce type d'évènement n'est pas reconnu")
  1497. TheYear = DBSession.query(JM2L_Year)\
  1498. .filter(JM2L_Year.year_uid==year)\
  1499. .first()
  1500. # Check year avaibility
  1501. if not TheYear:
  1502. raise HTTPNotFound(u"Cette année n'est pas pris en charge")
  1503. # Generate Timeslots for current year
  1504. TimeSlots = list(enumerate( [ x.strftime('%a %d %b %H:%M') for x in
  1505. TheYear.AvailableTimeSlots ] ))
  1506. if event_id:
  1507. # We try to update an existing record
  1508. if event_id.isdigit():
  1509. TheEvent = Event.by_id(event_id)
  1510. if TheEvent is None:
  1511. raise HTTPNotFound(u"Cette réference n'existe pas")
  1512. else:
  1513. TheEvent = Event.by_slug(event_id, year)
  1514. if TheEvent is None:
  1515. raise HTTPNotFound(u"Cette réference n'existe pas")
  1516. if request.user is None or not (request.user.Staff or request.user in TheEvent.intervenants):
  1517. raise HTTPForbidden(u"Vous n'êtes pas identifié comme étant un participant à cette intervention.")
  1518. # Compute some field value from selected event
  1519. if TheEvent.start_time in TheYear.AvailableTimeSlots:
  1520. start_sel = TheYear.AvailableTimeSlots.index(TheEvent.start_time)
  1521. else:
  1522. start_sel = len(TimeSlots)
  1523. TimeSlots.append( (len(TimeSlots), TheEvent.start_time.strftime('%a %d %b %H:%M')))
  1524. duration = (TheEvent.end_time - TheEvent.start_time).total_seconds()/60
  1525. end = TheEvent.start_time + datetime.timedelta(minutes=duration)
  1526. # prepare the form with update
  1527. form = ConfUpdateForm(request.POST, TheEvent, start_sel=start_sel, duration=duration, end_time=end,
  1528. meta={'csrf_context': request.session} )
  1529. # Customize labels
  1530. form.name.label.text += IntervLabel
  1531. form.description.label.text += IntervLabel
  1532. # Each event can get severals members
  1533. formAdd = AddIntervenant(event_uid=TheEvent.uid)
  1534. # Build list of intervenant
  1535. # Get users from db
  1536. Users = DBSession.query(User)\
  1537. .filter(User.Staff==1)\
  1538. .order_by('nom').all()
  1539. # Put some users on form
  1540. formAdd.intervenant.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  1541. for u in Users]
  1542. # Each event can get severals entities
  1543. formAddT = AddTiers(event_uid=TheEvent.uid)
  1544. # Build list of entities
  1545. # Get entities from db
  1546. TmpTiers = DBSession.query(Tiers)\
  1547. .order_by('name').limit(10)
  1548. # Put some entities on form
  1549. formAddT.tiers.choices = [(u.uid, "%s %s" % (u.nom, u.prenom))
  1550. for u in Users]
  1551. else:
  1552. TheEvent = Event()
  1553. # prepare the form for creation
  1554. form = ConfCreateForm(request.POST,
  1555. event_type=intervention,
  1556. for_year=str(year), meta={'csrf_context': request.session}
  1557. )
  1558. # Customize labels
  1559. form.name.label.text += IntervLabel
  1560. form.description.label.text += IntervLabel
  1561. duration=60
  1562. # No intervenant
  1563. formAdd = None
  1564. formAddT = None
  1565. SalleDispo = DBSession.query(Salles)\
  1566. .filter(Salles.year_uid==year)\
  1567. .order_by('name')
  1568. if intervention=="Conference":
  1569. form.duration.choices =[
  1570. (15,u'Lighting talk ( 5 min)'),
  1571. (30,u'Conférence (20 min)'),
  1572. (60,u'Conférence (50 min)'),
  1573. (90,u'Conférence (75 min)'),
  1574. ]
  1575. if not duration in [15, 30, 60, 90]:
  1576. form.duration.choices.append( (duration,u'Conférence (%d min)' % duration) )
  1577. if not form._fields.has_key("uid"):
  1578. form.duration.data=60
  1579. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Conference', 'MAO', 'Atelier']))
  1580. elif intervention=="Stand":
  1581. form.duration.choices =[
  1582. (8*60, u'Toute la journée'),
  1583. (4*60, u'une demi-journée')
  1584. ]
  1585. SalleDispo = SalleDispo.filter(Salles.place_type=='Stand')
  1586. elif intervention=="Atelier":
  1587. form.duration.choices = map( lambda d:(d, u'Atelier (%dh%.2d)' % (d/60, d%60) ), \
  1588. [60, 90, 120, 150, 180, 210, 240] )
  1589. if not duration in map(lambda (d,y): d, form.duration.choices):
  1590. form.duration.choices.append( (duration,u'Atelier (%dh%.2d)' % (duration/60, duration%60) ) )
  1591. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Atelier', 'MAO']))
  1592. elif intervention=="Table_ronde":
  1593. form.duration.choices = map( lambda d:(d, u'Table ronde (%dh%.2d)' % (d/60, d%60) ), \
  1594. [60, 90, 120, 150] )
  1595. if not duration in map(lambda (d,y): d, form.duration.choices):
  1596. form.duration.choices.append( (duration,u'Table ronde (%dh%.2d)' % (duration/60, duration%60) ) )
  1597. SalleDispo = SalleDispo.filter(Salles.place_type=='Table ronde')
  1598. elif intervention=="Concert":
  1599. form.duration.choices = map( lambda d:(d, u'Concert (%dh%.2d)' % (d/60, d%60) ), \
  1600. [60, 90, 120, 150, 180, 210, 240] )
  1601. if not duration in map(lambda (d,y): d, form.duration.choices):
  1602. form.duration.choices.append( (duration,u'Concert (%dh%.2d)' % (duration/60, duration%60) ) )
  1603. SalleDispo = SalleDispo.filter(Salles.place_type.in_(['Stand', 'MAO']))
  1604. else:
  1605. raise HTTPForbidden(u"Pas encore disponible.")
  1606. form.salle_uid.choices = [(s.salle_id, s.name) for s in SalleDispo]
  1607. form.start_sel.choices = TimeSlots
  1608. if request.method == 'POST' and form.validate():
  1609. form.populate_obj(TheEvent)
  1610. TheEvent.start_time = TheYear.AvailableTimeSlots[form.start_sel.data]
  1611. TheEvent.end_time = TheEvent.start_time + datetime.timedelta(minutes=form.duration.data)
  1612. # Ok, time to put in database
  1613. if not form._fields.has_key("uid"):
  1614. TheEvent.slug = unicode(slugify(TheEvent.name))
  1615. if intervention==u"Table_ronde":
  1616. TheEvent.event_type = "Table ronde"
  1617. DBSession.add(TheEvent)
  1618. # Append creator by default
  1619. if request.user.uid!=1:
  1620. uev = User_Event(year_uid=TheYear.year_uid, role=u"Animateur")
  1621. uev.user_uid = request.user.uid
  1622. TheEvent.interventions.append( uev )
  1623. DBSession.flush()
  1624. request.session.flash(('sucess',u'Votre intervention a été créee ! Vous pouvez la compléter à tout moment.'))
  1625. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1626. year=str(year), intervention=intervention, event_id=str(TheEvent.slug)))
  1627. else:
  1628. if slugify(TheEvent.name)!=TheEvent.slug:
  1629. # We should move some file as slug have been changed
  1630. # First we ensure there is no related event that already exist with that slug
  1631. CheckEvent = Event.by_slug( unicode(slugify(TheEvent.name)), year)
  1632. if CheckEvent:
  1633. request.session.flash(('warning',u'Choisissez un autre titre pour votre évènement, il est en conflit avec un autre.'))
  1634. return {'event':TheEvent, 'form':form, 'formAdd':formAdd, 'formAddT':formAddT, 'Salles':Salles }
  1635. else:
  1636. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1637. TheEvent.slug=unicode(slugify(TheEvent.name))
  1638. DSTPath = path.join('jm2l/upload', *(IMAGEPATH + ['event'] + [ str(year) ] + [ TheEvent.slug ]) )
  1639. if not path.isdir(path.dirname(DSTPath)):
  1640. makedirs(path.dirname(DSTPath))
  1641. # Then we should move event attachments to the new slug (if any)
  1642. if path.exists(SRCPath):
  1643. shutil.move(SRCPath, DSTPath)
  1644. DBSession.merge(TheEvent)
  1645. request.session.flash(('sucess',u'Votre intervention a été mis à jour !'))
  1646. return HTTPFound(location=request.route_url('edit_event', sep='/',
  1647. year=str(year), intervention=intervention, event_id=str(TheEvent.slug)))
  1648. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1649. 'event':TheEvent, 'form':form, 'formAdd':formAdd, 'formAddT':formAddT,
  1650. 'Salles':Salles }
  1651. return MainTab
  1652. @view_config(route_name='entities', renderer="jm2l:templates/list_tiers.mako")
  1653. def list_tiers(request):
  1654. Entities = dict()
  1655. EntityType = DBSession.query(TiersOpt.entity_type)\
  1656. .group_by(TiersOpt.entity_type).all()
  1657. for EType in EntityType:
  1658. Entities[EType.entity_type] = DBSession.query(Tiers).join(TiersOpt)\
  1659. .filter(TiersOpt.entity_type==EType.entity_type)\
  1660. .order_by(TiersOpt.entity_subtype, Tiers.name)
  1661. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1662. 'entities':Entities, 'logged_in':request.authenticated_userid }
  1663. return MainTab
  1664. @view_config(route_name='show_entity', renderer="jm2l:templates/view_tiers.mako")
  1665. def show_tiers(request):
  1666. tiers_type = request.matchdict.get('tiers_type')
  1667. entity_id = request.matchdict.get('entity_id')
  1668. if entity_id.isdigit():
  1669. TheTiers = Tiers.by_id(entity_id)
  1670. if TheTiers is None:
  1671. raise HTTPNotFound()
  1672. else:
  1673. TheTiers = Tiers.by_slug(entity_id)
  1674. if TheTiers is None:
  1675. raise HTTPNotFound()
  1676. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1677. 'entity':TheTiers, 'logged_in':request.authenticated_userid }
  1678. return MainTab
  1679. @view_config(route_name='delete_entity')
  1680. def delete_tiers(request):
  1681. if request.user is None:
  1682. # Don't answer to users that aren't logged
  1683. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1684. entity_id = request.matchdict.get('entity_id', None)
  1685. if entity_id:
  1686. if entity_id.isdigit():
  1687. TheTiers = Tiers.by_id(int(entity_id))
  1688. if TheTiers is None:
  1689. raise HTTPNotFound()
  1690. else:
  1691. TheTiers = Tiers.by_slug(entity_id)
  1692. if TheTiers is None:
  1693. raise HTTPNotFound()
  1694. if len(TheTiers.membership)!=0:
  1695. request.session.flash(('error', u"Vous devez supprimer tous les membres liés avant la suppression d'une entité."))
  1696. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug, tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1697. if len(TheTiers.membership)!=0:
  1698. request.session.flash(('error', u"Vous devez supprimer tous les roles liés avant la suppression d'une entité."))
  1699. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug, tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1700. DBSession.delete(TheTiers)
  1701. request.session.flash(('info', u"L'entité a bien été supprimée"))
  1702. return HTTPFound(location=request.route_url('entities'))
  1703. else:
  1704. raise HTTPNotFound()
  1705. @view_config(route_name='add_entity', renderer="jm2l:templates/edit_tiers.mako")
  1706. @view_config(route_name='edit_entity', renderer="jm2l:templates/edit_tiers.mako")
  1707. def edit_tiers(request):
  1708. entity_id = request.matchdict.get('entity_id', None)
  1709. TargetList = list()
  1710. if request.user is None:
  1711. # Don't answer to users that aren't logged
  1712. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1713. entity_types = DBSession.query(TiersOpt.entity_type).group_by(TiersOpt.entity_type).all()
  1714. for entity_type in entity_types:
  1715. entity_subtypes = DBSession.query(TiersOpt)\
  1716. .filter(TiersOpt.entity_type==entity_type.entity_type)\
  1717. .group_by(TiersOpt.entity_subtype).all()
  1718. ListType = [(i.uid, i.entity_subtype) for i in entity_subtypes]
  1719. TargetList.append( (entity_type.entity_type, ListType) )
  1720. if entity_id:
  1721. if entity_id.isdigit():
  1722. TheTiers = Tiers.by_id(entity_id)
  1723. if TheTiers is None:
  1724. raise HTTPNotFound()
  1725. else:
  1726. TheTiers = Tiers.by_slug(entity_id)
  1727. if TheTiers is None:
  1728. raise HTTPNotFound()
  1729. form = UpdateTiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1730. UserOptions = DBSession.query(TiersOpt)\
  1731. .filter(TiersOpt.entity_type==TheTiers.tiers_type)\
  1732. .all()
  1733. form.tiers_type.choices = TargetList
  1734. else:
  1735. TheTiers = Tiers()
  1736. # prepare the form for creation
  1737. form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1738. form.tiers_type.choices = TargetList
  1739. UserOptions = list()
  1740. #test_form = TiersForm(request.POST, TheTiers, meta={'csrf_context': request.session})
  1741. if request.method == 'POST' and form.validate():
  1742. ToDelete = list()
  1743. ToDeleteR = list()
  1744. # First, we remove entries no more present
  1745. for obj in form.membership.object_data:
  1746. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  1747. form.membership.entries )
  1748. if not MatchEntry:
  1749. ToDelete.append(obj)
  1750. # For roles too
  1751. for obj in form.roles.object_data:
  1752. MatchEntry = filter( lambda x: x.object_data and x.object_data._sa_instance_state == obj._sa_instance_state,
  1753. form.roles.entries )
  1754. if not MatchEntry:
  1755. ToDeleteR.append(obj)
  1756. # We should remove it as it's not in original data
  1757. for obj in ToDelete:
  1758. TheTiers.membership.remove(obj)
  1759. DBSession.delete(obj)
  1760. # For roles too
  1761. for obj in ToDeleteR:
  1762. TheTiers.roles.remove(obj)
  1763. DBSession.delete(obj)
  1764. # Then, it's time to consider new entries
  1765. for entry in form.membership.entries:
  1766. if entry.object_data is None:
  1767. TmpUser = User_Tiers()
  1768. entry.object_data = TmpUser
  1769. TheTiers.membership.append(TmpUser)
  1770. form.membership.object_data = TheTiers.membership
  1771. # For roles too
  1772. for entry in form.roles.entries:
  1773. if entry.object_data is None:
  1774. TmpRole = Role_Tiers()
  1775. entry.object_data = TmpRole
  1776. TheTiers.roles.append(TmpRole)
  1777. form.roles.object_data = TheTiers.roles
  1778. form.populate_obj(TheTiers)
  1779. # Handle Remove of accents
  1780. OriginalSlug = TheTiers.slug
  1781. if not form._fields.has_key('uid'):
  1782. TheTiers.slug = slugify(form.name.data)
  1783. TheTiers.creator_id = request.user.uid
  1784. DBSession.add(TheTiers)
  1785. DBSession.flush()
  1786. return HTTPFound(location=request.route_url('edit_entity', sep='/',
  1787. entity_id=str(TheTiers.slug), tiers_type=TheTiers.get_entity_type.entity_type))
  1788. else:
  1789. if OriginalSlug!=slugify(form.name.data):
  1790. # We should move some file as slug have been changed
  1791. # First we ensure there is no related event that already exist with that slug
  1792. CheckTiers = Tiers.by_slug( slugify(form.name.data) )
  1793. if CheckTiers:
  1794. request.session.flash(('warning',u'Attention, Choisissez un autre titre pour votre entitée, elle est en conflit avec une autre.'))
  1795. DBSession.rollback()
  1796. return HTTPFound(location=request.route_url('edit_entity', sep='/',
  1797. entity_id=str(OriginalSlug), tiers_type=TheTiers.get_entity_type.entity_type))
  1798. else:
  1799. TheTiers.slug = slugify(form.name.data)
  1800. SRCPath = path.join('jm2l/upload', *(IMAGEPATH + ['tiers'] + [ OriginalSlug ]) )
  1801. DSTPath = path.join('jm2l/upload', *(IMAGEPATH + ['tiers'] + [ TheTiers.slug ]) )
  1802. if not path.isdir(path.dirname(DSTPath)):
  1803. makedirs(path.dirname(DSTPath))
  1804. # Then we should move event attachments to the new slug (if any)
  1805. if path.exists(SRCPath):
  1806. shutil.move(SRCPath, DSTPath)
  1807. DBSession.merge(TheTiers)
  1808. return HTTPFound(location=request.route_url('show_entity', entity_id=TheTiers.slug,
  1809. tiers_type=TheTiers.get_entity_type.slug_entity_type))
  1810. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1811. 'form':form, 'DBUser':User, 'UserOptions':UserOptions,
  1812. 'logged_in':request.authenticated_userid }
  1813. return MainTab
  1814. @view_config(route_name='edit_entity_cat', renderer="jm2l:templates/edit_tiers_categ.mako")
  1815. def edit_tiers_category(request):
  1816. if request.user is None:
  1817. # Don't answer to users that aren't logged
  1818. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1819. DicResult = dict()
  1820. ListChanges = list()
  1821. if request.method == 'POST':
  1822. # Reformat data
  1823. RegExist = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[(?P<id>\d+)\]')
  1824. RegTitle = re.compile('collection\[(?P<slug>[\w-]+)\]\[title]')
  1825. RegNew = re.compile('collection\[(?P<slug>[\w-]+)\]\[(?P<num>\d+)\]\[id\]')
  1826. for key, value in request.POST.iteritems():
  1827. regN= RegNew.match(key)
  1828. regT= RegTitle.match(key)
  1829. reg = RegExist.match(key)
  1830. if reg:
  1831. if not DicResult.has_key(reg.group('slug')):
  1832. DicResult[reg.group('slug')] = dict()
  1833. if DicResult[reg.group('slug')].has_key('items'):
  1834. DicResult[reg.group('slug')]['items'].append( ( int(reg.group('id')), value ) )
  1835. else:
  1836. DicResult[reg.group('slug')]['items'] = [ ( int(reg.group('id')), value ) ]
  1837. elif regN:
  1838. if not DicResult.has_key(regN.group('slug')):
  1839. DicResult[regN.group('slug')] = dict()
  1840. if DicResult[regN.group('slug')].has_key('items'):
  1841. DicResult[regN.group('slug')]['items'].append( ( 'id', value ) )
  1842. else:
  1843. DicResult[regN.group('slug')]['items'] = [ ( 'id', value ) ]
  1844. ListChanges.append(('add', 0, DicResult[regN.group('slug')]['title'], value))
  1845. elif regT:
  1846. if not DicResult.has_key(regT.group('slug')):
  1847. DicResult[regT.group('slug')] = dict()
  1848. DicResult[regT.group('slug')]['title'] = value
  1849. else:
  1850. raise
  1851. for opt in DBSession.query(TiersOpt).all():
  1852. if DicResult.has_key(opt.slug_entity_type):
  1853. found = filter( lambda (x,y): opt.uid==x,
  1854. DicResult[opt.slug_entity_type].get('items', []))
  1855. if not found:
  1856. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  1857. else:
  1858. for tst in found:
  1859. # Check changes on Cat Name
  1860. if DicResult[opt.slug_entity_type]['title']!=opt.entity_type or \
  1861. tst[1]!=opt.entity_subtype:
  1862. ListChanges.append(('changed', opt.uid,
  1863. DicResult[opt.slug_entity_type]['title'],
  1864. tst[1]))
  1865. else:
  1866. ListChanges.append(('remove', opt.uid, opt.entity_type, opt.entity_subtype))
  1867. # Do The change
  1868. for action, uid, entity, subentity in ListChanges:
  1869. if action=="changed":
  1870. opt = TiersOpt.by_id(uid)
  1871. opt.entity_type = entity
  1872. opt.entity_subtype = subentity
  1873. elif action=="remove":
  1874. opt = TiersOpt.by_id(uid)
  1875. DBSession.delete(opt)
  1876. elif action=="add":
  1877. opt = TiersOpt()
  1878. opt.entity_type = entity
  1879. opt.entity_subtype = subentity
  1880. DBSession.add(opt)
  1881. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1882. 'logged_in':request.authenticated_userid, 'TiersOpt':TiersOpt }
  1883. return MainTab
  1884. @view_config(route_name='show_user', renderer="jm2l:templates/view_user.mako")
  1885. def show_user(request):
  1886. user_slug = request.matchdict.get('user_slug', None)
  1887. if user_slug is None or len(user_slug)==0:
  1888. raise HTTPNotFound(u"Cet utilisateur n'a pas été reconnu")
  1889. # Query database
  1890. DispUser = User.by_slug(user_slug)
  1891. if DispUser is None:
  1892. raise HTTPNotFound()
  1893. MainTab = {'programme':'','presse':'', 'plan':'', 'participer':'',
  1894. 'DispUser':DispUser, 'logged_in':request.authenticated_userid }
  1895. return MainTab
  1896. #@view_config(route_name='link_user_entity')
  1897. def link_user_entity(request):
  1898. if request.user is None:
  1899. # Don't answer to users that aren't logged
  1900. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1901. uid = int(request.matchdict.get('uid', -1))
  1902. year = int(request.matchdict.get('year', -1))
  1903. user_id = int(request.matchdict.get('uid', -1))
  1904. TheTiers = Tiers.by_id(uid)
  1905. if TheTiers is None:
  1906. raise HTTPNotFound()
  1907. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  1908. #@view_config(route_name='link_role_entity')
  1909. def link_role_entity(request):
  1910. if request.user is None:
  1911. # Don't answer to users that aren't logged
  1912. raise HTTPForbidden(u'Vous devez vous identifier pour obtenir une réponse.')
  1913. uid = int(request.matchdict.get('uid', -1))
  1914. year = int(request.matchdict.get('year', -1))
  1915. role_id = int(request.matchdict.get('role_id', -1))
  1916. TheTiers = Tiers.by_id(uid)
  1917. if TheTiers is None:
  1918. raise HTTPNotFound()
  1919. return HTTPFound(location=request.route_url('edit_entity', uid=uid) )
  1920. @forbidden_view_config()
  1921. def forbidden(reason, request):
  1922. if 'ident' in reason.detail:
  1923. request.session.flash(('info', reason.detail))
  1924. return HTTPFound(location='/sign/login?from='+request.environ['PATH_INFO'] )
  1925. else:
  1926. request.response.status = 403
  1927. return render_to_response('jm2l:templates/Errors/403.mako', { "reason":reason },
  1928. request=request)
  1929. @notfound_view_config()
  1930. def notfound(reason, request):
  1931. request.response.status = 404
  1932. return render_to_response('jm2l:templates/Errors/404.mako', { "reason":reason },
  1933. request=request)