Skip to content

Commit 4d0895a

Browse files
nnhathungHieu Lam - TMAlthanhhieu
authored
feature-5865 Able to book more discounted or access restricted tickets than allowed (#9041)
* fix issue user request check in not admin * feature-5865: Able to book more discounted or access restricted tickets than allowed * feature-5865: Able to book more discounted or access restricted tickets than allowed * fix ut * fix ut * fix ut * fix ut * fix ut * feature-5865: Able to book more discounted or access restricted tickets than allowed * feature-5865: Able to book more discounted or access restricted tickets than allowed * feature-5865: Able to book more discounted or access restricted tickets than allowed * fix complex function * fix complex function * fix complex function * fix complex function * add foreign key name * fix complex code * fix complex code * fix complex code * fix complex code * fix complex code * feature-5865: Merge code development * feature-5865: Able to book more discounted or access restricted tickets than allowed * fea-5865: update migration --------- Co-authored-by: Hieu Lam - TMA <[email protected]> Co-authored-by: lthanhhieu <[email protected]>
1 parent 6a2eceb commit 4d0895a

File tree

15 files changed

+379
-102
lines changed

15 files changed

+379
-102
lines changed

app/api/custom/orders.py

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from sqlalchemy.orm.exc import NoResultFound
88

99
from app.api.custom.schema.order_amount import OrderAmountInputSchema
10-
from app.api.helpers.db import safe_query, save_to_db
10+
from app.api.helpers.db import safe_query, safe_query_by_id, save_to_db
1111
from app.api.helpers.errors import ForbiddenError, NotFoundError, UnprocessableEntityError
1212
from app.api.helpers.mail import send_email_to_attendees
1313
from app.api.helpers.order import (
@@ -21,6 +21,8 @@
2121
from app.api.schema.orders import OrderSchema
2222
from app.extensions.limiter import limiter
2323
from app.models import db
24+
from app.models.access_code import AccessCode
25+
from app.models.discount_code import DiscountCode
2426
from app.models.order import Order, OrderTicket
2527
from app.models.ticket import Ticket
2628
from app.models.ticket_holder import TicketHolder
@@ -91,7 +93,11 @@ def calculate_amount():
9193
data, errors = OrderAmountInputSchema().load(request.get_json())
9294
if errors:
9395
return make_response(jsonify(errors), 422)
94-
return jsonify(calculate_order_amount(data['tickets'], data.get('discount_code')))
96+
return jsonify(
97+
calculate_order_amount(
98+
data['tickets'], data.get('discount_verify'), data.get('discount_code')
99+
)
100+
)
95101

96102

97103
@order_blueprint.route('/create-order', methods=['POST'])
@@ -102,7 +108,9 @@ def create_order():
102108
return make_response(jsonify(errors), 422)
103109

104110
tickets_dict = data['tickets']
105-
order_amount = calculate_order_amount(tickets_dict, data.get('discount_code'))
111+
order_amount = calculate_order_amount(
112+
tickets_dict, data.get('discount_verify'), data.get('discount_code')
113+
)
106114
ticket_ids = {ticket['id'] for ticket in tickets_dict}
107115
ticket_map = {int(ticket['id']): ticket for ticket in tickets_dict}
108116
tickets = (
@@ -116,14 +124,75 @@ def create_order():
116124
)
117125

118126
event = tickets[0].event
119-
127+
discount_code = None
128+
access_code = None
129+
discount_threshold = 0
130+
access_threshold = 0
131+
current_access_usage_count = 0
132+
if data.get('discount_code') and (
133+
isinstance(data.get('discount_code'), int)
134+
or (
135+
isinstance(data.get('discount_code'), str)
136+
and data.get('discount_code').isdigit()
137+
)
138+
):
139+
# Discount Code ID is passed
140+
discount_code = safe_query_by_id(DiscountCode, data.get('discount_code'))
141+
if discount_code is not None:
142+
current_discount_usage_count = discount_code.confirmed_attendees_count
143+
discount_threshold = (
144+
discount_code.tickets_number - current_discount_usage_count
145+
)
146+
if data.get('access_code') and (
147+
isinstance(data.get('access_code'), int)
148+
or (
149+
isinstance(data.get('access_code'), str) and data.get('access_code').isdigit()
150+
)
151+
):
152+
# Access Code check
153+
access_code = safe_query_by_id(AccessCode, data.get('access_code'))
154+
if access_code is not None:
155+
current_access_usage_count = access_code.confirmed_attendees_count
156+
access_threshold = access_code.tickets_number - current_access_usage_count
120157
try:
121158
attendees = []
122159
for ticket in tickets:
123160
for _ in range(ticket_map[ticket.id]['quantity']):
124161
ticket.raise_if_unavailable()
162+
is_discount_applied = False
163+
is_access_code_applied = False
164+
if (
165+
discount_code
166+
and (ticket in discount_code.tickets)
167+
and (discount_threshold > 0)
168+
):
169+
is_discount_applied = True
170+
discount_threshold -= 1
171+
172+
if (
173+
access_code
174+
and (ticket in access_code.tickets)
175+
and access_threshold >= 0
176+
):
177+
if access_threshold == 0:
178+
raise UnprocessableEntityError(
179+
{'source': 'access_code'},
180+
f"Access code for ticket {ticket.name} is exhausted, "
181+
f"only {access_code.tickets_number - current_access_usage_count} "
182+
"quantity is available",
183+
)
184+
is_access_code_applied = True
185+
access_threshold -= 1
186+
125187
attendees.append(
126-
TicketHolder(firstname='', lastname='', ticket=ticket, event=event)
188+
TicketHolder(
189+
firstname='',
190+
lastname='',
191+
ticket=ticket,
192+
event=event,
193+
is_discount_applied=is_discount_applied,
194+
is_access_code_applied=is_access_code_applied,
195+
)
127196
)
128197
db.session.commit()
129198
except Exception as e:
@@ -142,6 +211,7 @@ def create_order():
142211
amount=order_amount['total'],
143212
event=event,
144213
discount_code_id=data.get('discount_code'),
214+
access_code_id=data.get('access_code'),
145215
ticket_holders=attendees,
146216
)
147217
db.session.commit()
@@ -184,7 +254,6 @@ def ticket_attendee_pdf(attendee_id):
184254

185255
@order_blueprint.route('/<string:order_identifier>/verify', methods=['POST'])
186256
def verify_order_payment(order_identifier):
187-
188257
order = Order.query.filter_by(identifier=order_identifier).first()
189258

190259
if order.payment_mode == 'stripe':

app/api/custom/schema/order_amount.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
class TicketSchema(Schema):
55
id = fields.Integer(required=True)
66
quantity = fields.Integer(default=1)
7+
quantity_discount = fields.Integer(allow_none=True)
78
price = fields.Float(allow_none=True)
89

910

1011
class OrderAmountInputSchema(Schema):
1112
tickets = fields.Nested(TicketSchema, many=True)
1213
discount_code = fields.Integer(load_from='discount-code')
14+
access_code = fields.Integer(load_from='access-code')
1315
amount = fields.Float(allow_none=True)
16+
discount_verify = fields.Boolean(
17+
required=False, default=True, load_from='discount-verify'
18+
)

0 commit comments

Comments
 (0)