Compare commits
6 Commits
db45c2e7e3
...
cd2a5405db
Author | SHA1 | Date |
---|---|---|
drew | cd2a5405db | |
Stranck | 84bc070593 | |
Stranck | 1e6b400b2c | |
Stranck | 383b5bbede | |
Stranck | 938bc68383 | |
Stranck | 0d6789d307 |
9
admin.py
9
admin.py
|
@ -54,6 +54,15 @@ async def unconfirm_room(request, code, order:Order):
|
|||
await unconfirm_room_by_order(order=dOrder, throw=True, request=request)
|
||||
return redirect(f'/manage/nosecount')
|
||||
|
||||
@bp.get('/room/autoconfirm')
|
||||
async def autoconfirm_room(request, code, order:Order):
|
||||
orders = request.app.ctx.om.cache.values()
|
||||
for order in orders:
|
||||
if(order.code == order.room_id and not order.room_confirmed and len(order.room_members) == order.room_person_no):
|
||||
logger.info(f"Auto-Confirming room {order.room_id}")
|
||||
await confirm_room_by_order(order, request)
|
||||
return redirect(f'/manage/admin')
|
||||
|
||||
@bp.get('/room/delete/<code>')
|
||||
async def delete_room(request, code, order:Order):
|
||||
dOrder = await get_order_by_code(request, code, throwException=True)
|
||||
|
|
2
app.py
2
app.py
|
@ -55,7 +55,7 @@ async def handleException(request, exception):
|
|||
traceback.print_exc()
|
||||
|
||||
if statusCode == 403:
|
||||
clear_session(r)
|
||||
await clear_session(r)
|
||||
return r
|
||||
|
||||
|
||||
|
|
|
@ -80,16 +80,17 @@ async def send_unconfirm_message(room_order, orders):
|
|||
issues_html += "</ul>"
|
||||
|
||||
for member in orders:
|
||||
plain_body = EMAILS_TEXT["ROOM_UNCONFIRM_TEXT"]['plain'].format(member.name, room_order.room_name, issues_plain)
|
||||
html_body = render_email_template(EMAILS_TEXT["ROOM_UNCONFIRM_TITLE"], EMAILS_TEXT["ROOM_UNCONFIRM_TEXT"]['html'].format(member.name, room_order.room_name, issues_html))
|
||||
plain_text = MIMEText(plain_body, "plain")
|
||||
html_text = MIMEText(html_body, "html")
|
||||
message = MIMEMultipart("alternative")
|
||||
message.attach(plain_text)
|
||||
message.attach(html_text)
|
||||
message['Subject'] = f'[{EMAIL_SENDER_NAME}] Your room cannot be confirmed'
|
||||
message['To'] = f"{member.name} <{member.email}>"
|
||||
memberMessages.append(message)
|
||||
if(member.status != 'canceled'):
|
||||
plain_body = EMAILS_TEXT["ROOM_UNCONFIRM_TEXT"]['plain'].format(member.name, room_order.room_name, issues_plain)
|
||||
html_body = render_email_template(EMAILS_TEXT["ROOM_UNCONFIRM_TITLE"], EMAILS_TEXT["ROOM_UNCONFIRM_TEXT"]['html'].format(member.name, room_order.room_name, issues_html))
|
||||
plain_text = MIMEText(plain_body, "plain")
|
||||
html_text = MIMEText(html_body, "html")
|
||||
message = MIMEMultipart("alternative")
|
||||
message.attach(plain_text)
|
||||
message.attach(html_text)
|
||||
message['Subject'] = f'[{EMAIL_SENDER_NAME}] Your room cannot be confirmed'
|
||||
message['To'] = f"{member.name} <{member.email}>"
|
||||
memberMessages.append(message)
|
||||
|
||||
if len(memberMessages) == 0: return
|
||||
|
||||
|
|
19
ext.py
19
ext.py
|
@ -20,6 +20,10 @@ class Order:
|
|||
|
||||
self.time = time()
|
||||
self.data = data
|
||||
if(len(self.data['positions']) == 0):
|
||||
for fee in data['fees']:
|
||||
if(fee['fee_type'] == "cancellation"):
|
||||
self.data['status'] = 'c'
|
||||
self.status = {'n': 'pending', 'p': 'paid', 'e': 'expired', 'c': 'canceled'}[self.data['status']]
|
||||
self.secret = data['secret']
|
||||
|
||||
|
@ -218,13 +222,18 @@ class Order:
|
|||
#if ans['question'] == 40:
|
||||
# del self.answers[i]['options']
|
||||
# del self.answers[i]['option_identifiers']
|
||||
|
||||
res = await pretixClient.patch(f'orderpositions/{self.position_id}/', json={'answers': self.answers}, expectedStatusCodes=None)
|
||||
|
||||
ans = [] if self.status == "canceled" else self.answers
|
||||
res = await pretixClient.patch(f'orderpositions/{self.position_id}/', json={'answers': ans}, expectedStatusCodes=None)
|
||||
|
||||
if res.status_code != 200:
|
||||
for ans, err in zip(self.answers, res.json()['answers']):
|
||||
if err:
|
||||
logger.error ('[ANSWERS SENDING] ERROR ON %s %s', ans, err)
|
||||
e = res.json()
|
||||
if "answers" in e:
|
||||
for ans, err in zip(self.answers, res.json()['answers']):
|
||||
if err:
|
||||
logger.error ('[ANSWERS SENDING] ERROR ON %s %s', ans, err)
|
||||
else:
|
||||
logger.error("[ANSWERS SENDING] GENERIC ERROR. Response: '%s'", str(e))
|
||||
|
||||
raise exceptions.ServerError('There has been an error while updating this answers.')
|
||||
|
||||
|
|
|
@ -3,15 +3,16 @@ ROOM_ERROR_TYPES = {
|
|||
'unpaid': "Somebody in your room has not paid for their reservation, yet.",
|
||||
'type_mismatch': "A member in your room has a ticket for a different type of room capacity. This happens when users swap their room types with others, without abandoning the room.",
|
||||
'daily': "Some member in your room has a Daily ticket. These tickets do not include a hotel reservation.",
|
||||
'capacity_mismatch': "The number of people in your room mismatches your type of ticket."
|
||||
'capacity_mismatch': "The number of people in your room mismatches your type of ticket.",
|
||||
'canceled': "Someone in your room canceled his booking and it was removed from your room."
|
||||
}
|
||||
|
||||
EMAILS_TEXT = {
|
||||
"ROOM_UNCONFIRM_TITLE": "Your room got unconfirmed",
|
||||
"ROOM_UNCONFIRM_TEXT": {
|
||||
'html': "Hello <b>{0}</b><br>We had to <b>unconfirm</b> your room <i>'{1}'</i> due to the following issues:<br></p>{2}<br><p>Please contact your room's owner or contact our support for further informations at <a href=\"https://furizon.net/contact/\"> https://furizon.net/contact/</a>.<br>Thank you.<br><br><a class=\"link\" style=\"background-color: #1095c1; color: #fff;\" href=\"https://reg.furizon.net/manage/welcome\">Manage booking</a>",
|
||||
'html': "Hello <b>{0}</b><br>We had to <b>unconfirm or change</b> your room <i>'{1}'</i> due to the following issues:<br></p>{2}<br><p>Please contact your room's owner or contact our support for further informations at <a href=\"https://furizon.net/contact/\"> https://furizon.net/contact/</a>.<br>Thank you.<br><br><a class=\"link\" style=\"background-color: #1095c1; color: #fff;\" href=\"https://reg.furizon.net/manage/welcome\">Manage booking</a>",
|
||||
|
||||
'plain': "Hello {0}\nWe had to unconfirm your room '{1}' due to the following issues:\n{2}\nPlease contact your room's owner or contact our support for further informations at https://furizon.net/contact/.\nThank you\n\nTo manage your booking: https://reg.furizon.net/manage/welcome"
|
||||
'plain': "Hello {0}\nWe had to unconfirm or change your room '{1}' due to the following issues:\n{2}\nPlease contact your room's owner or contact our support for further informations at https://furizon.net/contact/.\nThank you\n\nTo manage your booking: https://reg.furizon.net/manage/welcome"
|
||||
},
|
||||
|
||||
|
||||
|
|
36
room.py
36
room.py
|
@ -5,6 +5,7 @@ from ext import *
|
|||
from config import headers
|
||||
import os
|
||||
from image_util import generate_room_preview, get_room
|
||||
from utils import confirm_room_by_order
|
||||
|
||||
bp = Blueprint("room", url_prefix="/manage/room")
|
||||
|
||||
|
@ -303,40 +304,7 @@ async def confirm_room(request, order: Order, quotas: Quotas):
|
|||
#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
|
||||
room_members = []
|
||||
for m in order.room_members:
|
||||
if m == order.code:
|
||||
res = order
|
||||
else:
|
||||
res = await request.app.ctx.om.get_order(code=m)
|
||||
|
||||
if res.room_id != order.code:
|
||||
raise exceptions.BadRequest("Please contact support: some of the members in your room are actually somewhere else")
|
||||
|
||||
if res.status != 'paid':
|
||||
raise exceptions.BadRequest("Somebody hasn't paid.")
|
||||
|
||||
if res.bed_in_room != bed_in_room:
|
||||
raise exceptions.BadRequest("Somebody has a ticket for a different type of room!")
|
||||
|
||||
if res.daily:
|
||||
raise exceptions.BadRequest("Somebody in your room has a daily ticket!")
|
||||
|
||||
room_members.append(res)
|
||||
|
||||
|
||||
if len(room_members) != order.room_person_no:
|
||||
raise exceptions.BadRequest("The number of people in your room mismatches your type of ticket!")
|
||||
|
||||
for rm in room_members:
|
||||
await rm.edit_answer('room_id', order.code)
|
||||
await rm.edit_answer('room_confirmed', "True")
|
||||
await rm.edit_answer('pending_roommates', None)
|
||||
await rm.edit_answer('pending_room', None)
|
||||
|
||||
for rm in room_members:
|
||||
await rm.send_answers()
|
||||
confirm_room_by_order(order, request)
|
||||
|
||||
return redirect('/manage/welcome')
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<a href="/manage/nosecount" role="button" title="Shortcut to the nosecount's admin data">Manage rooms</a>
|
||||
<a href="/manage/admin/room/verify" role="button" title="Will unconfirm rooms that fail the default check. Useful when editing answers from Pretix">Verify Rooms</a>
|
||||
<a href="#" onclick="confirmAction('propicReminder', this)" role="button" title="Will remind via mail all people who event uploaded a badge to do it" action="/manage/admin/propic/remind">Remind badge upload</a>
|
||||
<a href="/manage/admin/room/autoconfirm" role="button" title="Will confirm all the full rooms that are still unconfirmed">Auto-confirm Rooms</a>
|
||||
<hr>
|
||||
{% include 'components/confirm_action_modal.html' %}
|
||||
</main>
|
||||
|
|
|
@ -88,8 +88,10 @@
|
|||
|
||||
<details id="shuttle">
|
||||
<summary role="button"><img src="/res/icons/bus.svg" class="icon" />Shuttle</summary>
|
||||
<p>This year, a shuttle service operated by the tourism company of Val di Fiemme will be available. The shuttle service will consist of a bus serving the convention, with scheduled stops at major airports and train stations. More informations <a href="https://furizon.net/furizon-overlord/furizon-overlord-shuttle-bus/">in the dedicated page.</a></p>
|
||||
<p style="text-align:right;"><a href="{{LOCALES['shuttle_link_url'][locale]}}" target="_blank" role="button">Book now!</a></p>
|
||||
<p><b>Due to the low number of requests, the shuttle service managed by Trentino Trasporti will not be available. Those who have purchased a bus ticket will be refunded directly by the transport company</b></p>
|
||||
<p>On the Furizon Telegram group, there is an active topic dedicated to car sharing, and the staff is available to look for custom alternative solutions. We apologize for the inconvenience.</p>
|
||||
<!--p>This year, a shuttle service operated by the tourism company of Val di Fiemme will be available. The shuttle service will consist of a bus serving the convention, with scheduled stops at major airports and train stations. More informations <a href="https://furizon.net/furizon-overlord/furizon-overlord-shuttle-bus/">in the dedicated page.</a></p>
|
||||
<p style="text-align:right;"><a href="{{LOCALES['shuttle_link_url'][locale]}}" target="_blank" role="button">Book now!</a></p-->
|
||||
</details>
|
||||
|
||||
<details id="barcard">
|
||||
|
|
125
utils.py
125
utils.py
|
@ -151,6 +151,42 @@ async def get_people_in_room_by_code(request, code, om=None):
|
|||
await om.update_cache()
|
||||
return filter(lambda rm: rm.room_id == code, om.cache.values())
|
||||
|
||||
async def confirm_room_by_order(order, request):
|
||||
bed_in_room = order.bed_in_room # Variation id of the ticket for that kind of room
|
||||
room_members = []
|
||||
for m in order.room_members:
|
||||
if m == order.code:
|
||||
res = order
|
||||
else:
|
||||
res = await request.app.ctx.om.get_order(code=m)
|
||||
|
||||
if res.room_id != order.code:
|
||||
raise exceptions.BadRequest("Please contact support: some of the members in your room are actually somewhere else")
|
||||
|
||||
if res.status != 'paid':
|
||||
raise exceptions.BadRequest("Somebody hasn't paid.")
|
||||
|
||||
if res.bed_in_room != bed_in_room:
|
||||
raise exceptions.BadRequest("Somebody has a ticket for a different type of room!")
|
||||
|
||||
if res.daily:
|
||||
raise exceptions.BadRequest("Somebody in your room has a daily ticket!")
|
||||
|
||||
room_members.append(res)
|
||||
|
||||
|
||||
if len(room_members) != order.room_person_no:
|
||||
raise exceptions.BadRequest("The number of people in your room mismatches your type of ticket!")
|
||||
|
||||
for rm in room_members:
|
||||
await rm.edit_answer('room_id', order.code)
|
||||
await rm.edit_answer('room_confirmed', "True")
|
||||
await rm.edit_answer('pending_roommates', None)
|
||||
await rm.edit_answer('pending_room', None)
|
||||
|
||||
for rm in room_members:
|
||||
await rm.send_answers()
|
||||
|
||||
async def unconfirm_room_by_order(order, room_members=None, throw=True, request=None, om=None):
|
||||
if not om: om = request.app.ctx.om
|
||||
if not order.room_confirmed:
|
||||
|
@ -164,6 +200,17 @@ async def unconfirm_room_by_order(order, room_members=None, throw=True, request=
|
|||
await p.edit_answer('room_confirmed', "False")
|
||||
await p.send_answers()
|
||||
|
||||
async def remove_members_from_room(order, removeMembers):
|
||||
didSomething = False
|
||||
for member in removeMembers:
|
||||
if (member in order.room_members):
|
||||
order.room_members.remove(member)
|
||||
didSomething = True
|
||||
if(didSomething):
|
||||
await order.edit_answer("room_members", ','.join(order.room_members))
|
||||
await order.send_answers()
|
||||
return didSomething
|
||||
|
||||
async def validate_rooms(request, rooms, om):
|
||||
logger.info('Validating rooms...')
|
||||
if not om: om = request.app.ctx.om
|
||||
|
@ -171,6 +218,7 @@ async def validate_rooms(request, rooms, om):
|
|||
# rooms_to_unconfirm is the room that MUST be unconfirmed, room_with_errors is a less strict set containing all rooms with kind-ish errors
|
||||
rooms_to_unconfirm = []
|
||||
room_with_errors = []
|
||||
remove_members = []
|
||||
|
||||
# Validate rooms
|
||||
for order in rooms:
|
||||
|
@ -195,43 +243,58 @@ async def validate_rooms(request, rooms, om):
|
|||
# Get confirmed rooms that fail validation
|
||||
failed_confirmed_rooms = list(filter(lambda fr: (fr[0].room_confirmed == True), rooms_to_unconfirm))
|
||||
|
||||
didSomething = False
|
||||
|
||||
if len(failed_confirmed_rooms) == 0:
|
||||
logger.info('[ROOM VALIDATION] No rooms to unconfirm.')
|
||||
return
|
||||
else:
|
||||
didSomething = True
|
||||
logger.info(f"[ROOM VALIDATION] Trying to unconfirm {len(failed_confirmed_rooms)} rooms...")
|
||||
|
||||
logger.info(f"[ROOM VALIDATION] Trying to unconfirm {len(failed_confirmed_rooms)} rooms...")
|
||||
|
||||
# Try unconfirming them
|
||||
for rtu in failed_confirmed_rooms:
|
||||
order = rtu[0]
|
||||
member_orders = rtu[2]
|
||||
logger.warning(f"[ROOM VALIDATION] [UNCONFIRMING] Unconfirming room {order.code}...")
|
||||
|
||||
# Unconfirm and email users about the room
|
||||
if UNCONFIRM_ROOMS_ENABLE:
|
||||
await unconfirm_room_by_order(order, member_orders, False, None, om)
|
||||
|
||||
logger.info(f"[ROOM VALIDATION] Sending unconfirm notice to room members...")
|
||||
sent_count = 0
|
||||
# Send unconfirm notice via email
|
||||
for rtu in failed_confirmed_rooms:
|
||||
order = rtu[0]
|
||||
member_orders = rtu[2]
|
||||
try:
|
||||
# Try unconfirming them
|
||||
for rtu in failed_confirmed_rooms:
|
||||
order = rtu[0]
|
||||
member_orders = rtu[2]
|
||||
logger.warning(f"[ROOM VALIDATION] [UNCONFIRMING] Unconfirming room {order.code}...")
|
||||
|
||||
# Unconfirm and email users about the room
|
||||
if UNCONFIRM_ROOMS_ENABLE:
|
||||
await send_unconfirm_message(order, member_orders)
|
||||
sent_count += len(member_orders)
|
||||
except Exception as ex:
|
||||
if EXTRA_PRINTS: logger.exception(str(ex))
|
||||
logger.info(f"[ROOM VALIDATION] Sent {sent_count} emails")
|
||||
await unconfirm_room_by_order(order, member_orders, False, None, om)
|
||||
|
||||
for r in rooms_to_unconfirm:
|
||||
order = r[0]
|
||||
removeMembers = r[3]
|
||||
if len(removeMembers) > 0:
|
||||
logger.warning(f"[ROOM VALIDATION] [REMOVING] Removing members '{','.join(removeMembers)}' from room {order.code}")
|
||||
|
||||
if UNCONFIRM_ROOMS_ENABLE:
|
||||
didSomething |= await remove_members_from_room(order, removeMembers)
|
||||
if(r not in failed_confirmed_rooms): failed_confirmed_rooms.append(r)
|
||||
|
||||
|
||||
if(didSomething):
|
||||
logger.info(f"[ROOM VALIDATION] Sending unconfirm notice to room members...")
|
||||
sent_count = 0
|
||||
# Send unconfirm notice via email
|
||||
for rtu in failed_confirmed_rooms:
|
||||
order = rtu[0]
|
||||
member_orders = rtu[2]
|
||||
try:
|
||||
if UNCONFIRM_ROOMS_ENABLE:
|
||||
await send_unconfirm_message(order, member_orders)
|
||||
sent_count += len(member_orders)
|
||||
except Exception as ex:
|
||||
if EXTRA_PRINTS: logger.exception(str(ex))
|
||||
logger.info(f"[ROOM VALIDATION] Sent {sent_count} emails")
|
||||
|
||||
|
||||
async def check_room(request, order, om=None):
|
||||
room_errors = []
|
||||
room_members = []
|
||||
remove_members = []
|
||||
use_cached = request == None
|
||||
if not om: om = request.app.ctx.om
|
||||
if not order or not order.room_id or order.room_id != order.code: return (order, False, room_members)
|
||||
if not order or not order.room_id or order.room_id != order.code: return (order, False, room_members, remove_members)
|
||||
|
||||
# This is not needed anymore you buy tickets already
|
||||
#if quotas.get_left(len(order.room_members)) == 0:
|
||||
|
@ -249,8 +312,12 @@ async def check_room(request, order, om=None):
|
|||
if res.room_id != order.code:
|
||||
room_errors.append((res.code, 'room_id_mismatch'))
|
||||
allOk = False
|
||||
|
||||
if res.status != 'paid':
|
||||
|
||||
if res.status == 'canceled':
|
||||
room_errors.append((res.code, 'canceled'))
|
||||
remove_members.append(res.code)
|
||||
allOk = False
|
||||
elif res.status != 'paid':
|
||||
room_errors.append((res.code, 'unpaid'))
|
||||
|
||||
if res.bed_in_room != bed_in_room:
|
||||
|
@ -270,4 +337,4 @@ async def check_room(request, order, om=None):
|
|||
if order.room_confirmed:
|
||||
allOk = False
|
||||
order.set_room_errors(room_errors)
|
||||
return (order, allOk, room_members)
|
||||
return (order, allOk, room_members, remove_members)
|
Loading…
Reference in New Issue