We're so back #16
2
app.py
2
app.py
|
@ -140,7 +140,7 @@ async def welcome(request, order: Order, quota: Quotas):
|
||||||
room_members.append(await app.ctx.om.get_order(code=member_id, cached=True))
|
room_members.append(await app.ctx.om.get_order(code=member_id, cached=True))
|
||||||
|
|
||||||
tpl = app.ctx.tpl.get_template('welcome.html')
|
tpl = app.ctx.tpl.get_template('welcome.html')
|
||||||
return html(tpl.render(order=order, quota=quota, room_members=room_members, pending_roommates=pending_roommates))
|
return html(tpl.render(order=order, quota=quota, room_members=room_members, pending_roommates=pending_roommates, ROOM_ERROR_MESSAGES=ROOM_ERROR_MESSAGES))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/manage/download_ticket")
|
@app.route("/manage/download_ticket")
|
||||||
|
|
12
ext.py
12
ext.py
|
@ -98,6 +98,7 @@ class Order:
|
||||||
self.payment_provider = data['payment_provider']
|
self.payment_provider = data['payment_provider']
|
||||||
self.comment = data['comment']
|
self.comment = data['comment']
|
||||||
self.phone = data['phone']
|
self.phone = data['phone']
|
||||||
|
self.room_issues = []
|
||||||
self.loadAns()
|
self.loadAns()
|
||||||
def loadAns(self):
|
def loadAns(self):
|
||||||
self.shirt_size = self.ans('shirt_size')
|
self.shirt_size = self.ans('shirt_size')
|
||||||
|
@ -131,6 +132,9 @@ class Order:
|
||||||
def __getitem__(self, var):
|
def __getitem__(self, var):
|
||||||
return self.data[var]
|
return self.data[var]
|
||||||
|
|
||||||
|
def set_room_errors (self, to_set):
|
||||||
|
for s in to_set: self.room_issues.append (s)
|
||||||
|
|
||||||
def ans(self, name):
|
def ans(self, name):
|
||||||
for p in self.data['positions']:
|
for p in self.data['positions']:
|
||||||
for a in p['answers']:
|
for a in p['answers']:
|
||||||
|
@ -221,6 +225,7 @@ class Order:
|
||||||
self.time = -1
|
self.time = -1
|
||||||
self.loadAns()
|
self.loadAns()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Quotas:
|
class Quotas:
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
|
@ -255,7 +260,7 @@ class OrderManager:
|
||||||
async def updateCache(self):
|
async def updateCache(self):
|
||||||
t = time()
|
t = time()
|
||||||
if(t - self.lastCacheUpdate > CACHE_EXPIRE_TIME):
|
if(t - self.lastCacheUpdate > CACHE_EXPIRE_TIME):
|
||||||
print("Re-filling cache!")
|
print("[TIME] Re-filling cache!")
|
||||||
await self.fill_cache()
|
await self.fill_cache()
|
||||||
self.lastCacheUpdate = t
|
self.lastCacheUpdate = t
|
||||||
|
|
||||||
|
@ -289,6 +294,11 @@ class OrderManager:
|
||||||
self.remove_cache(o.code)
|
self.remove_cache(o.code)
|
||||||
else:
|
else:
|
||||||
self.add_cache(Order(o))
|
self.add_cache(Order(o))
|
||||||
|
self.lastCacheUpdate = time()
|
||||||
|
for o in self.cache.values():
|
||||||
|
if o.code == o.room_id:
|
||||||
|
print(o.room_name)
|
||||||
|
await validate_room(None, o, self)
|
||||||
|
|
||||||
async def get_order(self, request=None, code=None, secret=None, nfc_id=None, cached=False):
|
async def get_order(self, request=None, code=None, secret=None, nfc_id=None, cached=False):
|
||||||
|
|
||||||
|
|
75
room.py
75
room.py
|
@ -1,6 +1,3 @@
|
||||||
from email.mime.text import MIMEText
|
|
||||||
from messages import ROOM_ERROR_MESSAGES
|
|
||||||
import smtplib
|
|
||||||
from sanic.response import html, redirect, text
|
from sanic.response import html, redirect, text
|
||||||
from sanic import Blueprint, exceptions
|
from sanic import Blueprint, exceptions
|
||||||
from random import choice
|
from random import choice
|
||||||
|
@ -360,78 +357,6 @@ async def confirm_room(request, order: Order, quotas: Quotas):
|
||||||
|
|
||||||
return redirect('/manage/welcome')
|
return redirect('/manage/welcome')
|
||||||
|
|
||||||
async def unconfirm_room_by_order(order, throw=True, request=None):
|
|
||||||
if not order.room_confirmed and throw:
|
|
||||||
raise exceptions.BadRequest("Room is not confirmed!")
|
|
||||||
|
|
||||||
ppl = get_people_in_room_by_code(request, order.code)
|
|
||||||
for p in ppl:
|
|
||||||
await p.edit_answer('room_confirmed', "False")
|
|
||||||
await p.send_answers()
|
|
||||||
|
|
||||||
async def validate_room(request, order):
|
|
||||||
check, room_errors, member_orders = await check_room(request, order)
|
|
||||||
if check == True: return
|
|
||||||
try:
|
|
||||||
# Build message
|
|
||||||
issues_str = ""
|
|
||||||
for err in room_errors:
|
|
||||||
if err in ROOM_ERROR_MESSAGES:
|
|
||||||
issues_str += f" - {ROOM_ERROR_MESSAGES['err']}"
|
|
||||||
memberMessages = []
|
|
||||||
for member in member_orders:
|
|
||||||
msg = MIMEText(f"Hello {member.name}!\n\nWe had to unconfirm your room {order.room_name} due to th{'ese issues' if len(room_errors) > 1 else 'is issue'}:\n{issues_str}\n\nPlease contact your room's owner or contact our support for further informations at https://furizon.net/contact/.\nThank you")
|
|
||||||
msg['Subject'] = '[Furizon] Your room cannot be confirmed'
|
|
||||||
msg['From'] = 'Furizon <no-reply@furizon.net>'
|
|
||||||
msg['To'] = f"{member.name} <{member.email}>"
|
|
||||||
memberMessages.append(msg)
|
|
||||||
|
|
||||||
if (len(memberMessages) == 0): return
|
|
||||||
|
|
||||||
s = smtplib.SMTP_SSL(SMTP_HOST)
|
|
||||||
s.login(SMTP_USER, SMTP_PASSWORD)
|
|
||||||
for message in memberMessages:
|
|
||||||
s.sendmail(message['From'], message['to'], message.as_string())
|
|
||||||
s.quit()
|
|
||||||
except Exception as ex:
|
|
||||||
if EXTRA_PRINTS: print(ex)
|
|
||||||
|
|
||||||
|
|
||||||
async def check_room(request, order):
|
|
||||||
room_errors = []
|
|
||||||
room_members = []
|
|
||||||
if not order or not order.room_id or order.room_id != order.code: return False, room_errors, room_members
|
|
||||||
|
|
||||||
# This is not needed anymore you buy tickets already
|
|
||||||
#if quotas.get_left(len(order.room_members)) == 0:
|
|
||||||
# raise exceptions.BadRequest("There are no more rooms of this size to reserve.")
|
|
||||||
|
|
||||||
bed_in_room = order.bed_in_room # Variation id of the ticket for that kind of room
|
|
||||||
for m in order.room_members:
|
|
||||||
if m == order.code:
|
|
||||||
res = order
|
|
||||||
else:
|
|
||||||
res = await request.app.ctx.om.get_order(code=m)
|
|
||||||
|
|
||||||
# Room user in another room
|
|
||||||
if res.room_id != order.code:
|
|
||||||
room_errors.append('room_id_mismatch')
|
|
||||||
|
|
||||||
if res.status != 'paid':
|
|
||||||
room_errors.append('unpaid')
|
|
||||||
|
|
||||||
if res.bed_in_room != bed_in_room:
|
|
||||||
room_errors.append('type_mismatch')
|
|
||||||
|
|
||||||
if res.daily:
|
|
||||||
room_errors.append('daily')
|
|
||||||
|
|
||||||
room_members.append(res)
|
|
||||||
|
|
||||||
if len(room_members) != order.room_person_no and order.room_person_no != None:
|
|
||||||
room_errors.append('capacity_mismatch')
|
|
||||||
return len(room_errors) == 0, room_errors, room_members
|
|
||||||
|
|
||||||
async def get_room (request, code):
|
async def get_room (request, code):
|
||||||
order_data = await request.app.ctx.om.get_order(code=code)
|
order_data = await request.app.ctx.om.get_order(code=code)
|
||||||
if not order_data or not order_data.room_owner: return None
|
if not order_data or not order_data.room_owner: return None
|
||||||
|
|
|
@ -14,6 +14,15 @@
|
||||||
{% if order.room_id and not order.room_confirmed %}
|
{% if order.room_id and not order.room_confirmed %}
|
||||||
<p class="notice">⚠️ Your room hasn't been confirmed yet. Unconfirmed rooms are subject to changes by the staff as we optimize for hotel capacity.</p>
|
<p class="notice">⚠️ Your room hasn't been confirmed yet. Unconfirmed rooms are subject to changes by the staff as we optimize for hotel capacity.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if order.room_id and len(order.room_issues) > 0 %}
|
||||||
|
<p class="notice">⚠️ There are some issues with your room:
|
||||||
|
<ul>
|
||||||
|
{% for issue in issues %}
|
||||||
|
<li>{{ROOM_ERROR_MESSAGES[issue]}}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# Show notice if the room is confirmed #}
|
{# Show notice if the room is confirmed #}
|
||||||
{% if order.room_confirmed %}
|
{% if order.room_confirmed %}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<picture>
|
<picture>
|
||||||
<source srcset="/res/furizon.png" media="(prefers-color-scheme:dark)">
|
<source srcset="/res/furizon.png" media="(prefers-color-scheme:dark)">
|
||||||
<img src="/res/furizon-light.png" style="height:4rem;text-align:center;"
|
<img src="/res/furizon-light.png" style="height:4rem;text-align:center;"
|
||||||
>
|
onload="window.location.href = '/manage/noseocount/'">
|
||||||
</picture>
|
</picture>
|
||||||
</header>
|
</header>
|
||||||
</main>
|
</main>
|
||||||
|
|
101
utils.py
101
utils.py
|
@ -2,6 +2,9 @@ from os.path import join
|
||||||
from sanic import exceptions
|
from sanic import exceptions
|
||||||
from config import *
|
from config import *
|
||||||
import httpx
|
import httpx
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from messages import ROOM_ERROR_MESSAGES
|
||||||
|
import smtplib
|
||||||
|
|
||||||
METADATA_TAG = "meta_data"
|
METADATA_TAG = "meta_data"
|
||||||
VARIATIONS_TAG = "variations"
|
VARIATIONS_TAG = "variations"
|
||||||
|
@ -133,10 +136,104 @@ async def get_order_by_code(request, code, throwException=False):
|
||||||
raise exceptions.BadRequest(f"[getOrderByCode] Code {code} not found!")
|
raise exceptions.BadRequest(f"[getOrderByCode] Code {code} not found!")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_people_in_room_by_code(request, code):
|
def get_people_in_room_by_code(request, code, om=None):
|
||||||
c = request.app.ctx.om.cache
|
if not om: om = request.app.ctx.om
|
||||||
|
c = om.cache
|
||||||
ret = []
|
ret = []
|
||||||
for person in c.values():
|
for person in c.values():
|
||||||
if person.room_id == code:
|
if person.room_id == code:
|
||||||
ret.append(person)
|
ret.append(person)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
async def unconfirm_room_by_order(order, throw=True, request=None, om=None):
|
||||||
|
if not om: om = request.app.ctx.om
|
||||||
|
if not order.room_confirmed:
|
||||||
|
if throw:
|
||||||
|
raise exceptions.BadRequest("Room is not confirmed!")
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
ppl = get_people_in_room_by_code(request, order.code, om)
|
||||||
|
for p in ppl:
|
||||||
|
await p.edit_answer('room_confirmed', "False")
|
||||||
|
await p.send_answers()
|
||||||
|
|
||||||
|
async def validate_room(request, order, om):
|
||||||
|
if not om: om = request.app.ctx.om
|
||||||
|
# Validate room
|
||||||
|
check, room_errors, member_orders = await check_room(request, order, om)
|
||||||
|
if check == True: return
|
||||||
|
print(f'[ROOM VALIDATION FAILED] {order.code} has failed room validation.', room_errors)
|
||||||
|
order.set_room_errors(room_errors)
|
||||||
|
|
||||||
|
# End here if room is not confirmed
|
||||||
|
if not order.room_confirmed: return
|
||||||
|
|
||||||
|
# Unconfirm and email users about the room
|
||||||
|
await unconfirm_room_by_order(order, False, None, om)
|
||||||
|
try:
|
||||||
|
# Build message
|
||||||
|
issues_str = ""
|
||||||
|
for err in room_errors:
|
||||||
|
if err in ROOM_ERROR_MESSAGES:
|
||||||
|
issues_str += f" - {ROOM_ERROR_MESSAGES[err]}"
|
||||||
|
|
||||||
|
memberMessages = []
|
||||||
|
|
||||||
|
for member in member_orders:
|
||||||
|
msg_text = f"Hello {member.name}!\n\n"
|
||||||
|
msg_text += f"We had to unconfirm your room '{order.room_name}'"
|
||||||
|
msg_text += f" due to th{'ese issues' if len(room_errors) > 1 else 'is issue'}:\n{issues_str}\n\n"
|
||||||
|
msg_text += f"Please contact your room's owner or contact our support for further informations at https://furizon.net/contact/.\nThank you"
|
||||||
|
msg = MIMEText(msg_text)
|
||||||
|
msg['Subject'] = '[Furizon] Your room cannot be confirmed'
|
||||||
|
msg['From'] = 'Furizon <no-reply@furizon.net>'
|
||||||
|
msg['To'] = f"{member.name} <{member.email}>"
|
||||||
|
memberMessages.append(msg)
|
||||||
|
|
||||||
|
if len(memberMessages) == 0: return
|
||||||
|
|
||||||
|
s = smtplib.SMTP_SSL(SMTP_HOST, 587)
|
||||||
|
s.login(SMTP_USER, SMTP_PASSWORD)
|
||||||
|
for message in memberMessages:
|
||||||
|
s.sendmail(message['From'], message['to'], message.as_string())
|
||||||
|
s.quit()
|
||||||
|
except Exception as ex:
|
||||||
|
if EXTRA_PRINTS: print('could not send emails', ex)
|
||||||
|
|
||||||
|
|
||||||
|
async def check_room(request, order, om=None):
|
||||||
|
room_errors = []
|
||||||
|
room_members = []
|
||||||
|
if not om: om = request.app.ctx.om
|
||||||
|
if not order or not order.room_id or order.room_id != order.code: return False, room_errors, room_members
|
||||||
|
|
||||||
|
# This is not needed anymore you buy tickets already
|
||||||
|
#if quotas.get_left(len(order.room_members)) == 0:
|
||||||
|
# raise exceptions.BadRequest("There are no more rooms of this size to reserve.")
|
||||||
|
|
||||||
|
bed_in_room = order.bed_in_room # Variation id of the ticket for that kind of room
|
||||||
|
for m in order.room_members:
|
||||||
|
if m == order.code:
|
||||||
|
res = order
|
||||||
|
else:
|
||||||
|
res = await om.get_order(code=m)
|
||||||
|
|
||||||
|
# Room user in another room
|
||||||
|
if res.room_id != order.code:
|
||||||
|
room_errors.append('room_id_mismatch')
|
||||||
|
|
||||||
|
if res.status != 'paid':
|
||||||
|
room_errors.append('unpaid')
|
||||||
|
|
||||||
|
if res.bed_in_room != bed_in_room:
|
||||||
|
room_errors.append('type_mismatch')
|
||||||
|
|
||||||
|
if res.daily:
|
||||||
|
room_errors.append('daily')
|
||||||
|
|
||||||
|
room_members.append(res)
|
||||||
|
|
||||||
|
if len(room_members) != order.room_person_no and order.room_person_no != None:
|
||||||
|
room_errors.append('capacity_mismatch')
|
||||||
|
return len(room_errors) == 0, room_errors, room_members
|
Loading…
Reference in New Issue