Skip to content

Commit 3a85e5e

Browse files
Hieu Lam - TMAkhangon
andauthored
feature-8990: Allow to search attendees via email or name (#9010)
* feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name * feature-8990: Allow to search attendees via email or name --------- Co-authored-by: Khang On - TMA <[email protected]>
1 parent 52c7de9 commit 3a85e5e

File tree

4 files changed

+123
-3
lines changed

4 files changed

+123
-3
lines changed

app/api/custom/events.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from app.models.exhibitor import Exhibitor
1616
from app.models.session import Session
1717
from app.models.speaker import Speaker
18+
from app.models.ticket_holder import TicketHolder
1819

1920
events_routes = Blueprint('events_routes', __name__, url_prefix='/v1/events')
2021

@@ -193,3 +194,23 @@ def delete_unused_discount_codes(event_id):
193194
db.session.commit()
194195

195196
return jsonify({'success': True, 'deletes': result})
197+
198+
199+
@events_routes.route('/<string:event_identifier>/attendees/search', methods=['GET'])
200+
@to_event_id
201+
@jwt_required
202+
def search_attendees(event_id):
203+
"""Search attendees by name or email."""
204+
query = TicketHolder.query.filter(TicketHolder.event_id == event_id)
205+
args = request.args
206+
if args.get('name'):
207+
query = query.filter(
208+
(TicketHolder.firstname.ilike('%' + args.get('name') + '%'))
209+
| (TicketHolder.lastname.ilike('%' + args.get('name') + '%'))
210+
)
211+
if args.get('email'):
212+
query = query.filter(TicketHolder.email.ilike('%' + args.get('email') + '%'))
213+
214+
attendees = query.order_by(TicketHolder.id.desc()).all()
215+
216+
return jsonify({'attendees': attendees})

docs/api/blueprint/attendees.apib

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,60 @@ Get a list of attendees of an event.
244244
}
245245
}
246246

247+
## Search Attendees under an event [/v1/events/{event_id}/attendees/search]
248+
+ Parameters
249+
+ event_id: 1 (integer) - Identifier of the event
250+
251+
### Search All Attendees under an event [GET]
252+
Search a list of attendees of an event.
253+
254+
+ Request
255+
256+
+ Headers
257+
258+
Accept: application/vnd.api+json
259+
260+
Authorization: JWT <Auth Key>
261+
262+
+ Response 200 (application/json)
263+
{
264+
"attendees": [
265+
{
266+
"facebook": null,
267+
"address": "address",
268+
"ticket-id": "31",
269+
"is-checked-out": null,
270+
"checkout-times": null,
271+
"job-title": null,
272+
"deleted-at": null,
273+
"work-address": null,
274+
"checkin-times": null,
275+
"state": "example",
276+
"country": "IN",
277+
"lastname": "UnDoe",
278+
"city": "example",
279+
"phone": null,
280+
"company": null,
281+
"is-checked-in": false,
282+
"gender": null,
283+
"shipping-address": null,
284+
"blog": null,
285+
"firstname": "John",
286+
"website": null,
287+
"billing-address": null,
288+
"pdf-url": null,
289+
"tax-business-info": null,
290+
"home-address": null,
291+
"work-phone": null,
292+
"birth-date": null,
293+
"github": null,
294+
"twitter": null,
295+
"email": "[email protected]",
296+
"attendee-notes": null
297+
}
298+
]
299+
}
300+
247301
## List Attendees under a ticket [/v1/tickets/{ticket_id}/attendees]
248302
+ Parameters
249303
+ ticket_id: 1 (integer) - Identifier of the event
@@ -535,3 +589,4 @@ Delete a single attendee.
535589
"version": "1.0"
536590
}
537591
}
592+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from tests.factories.attendee import AttendeeFactoryBase
2+
from tests.factories.event import EventFactoryBasic
3+
from tests.factories.order import OrderFactory
4+
from tests.factories.ticket import TicketFactory
5+
6+
7+
def test_event_search_attendee(db, jwt, client):
8+
"""Method to test the count query of sold tickets"""
9+
event = EventFactoryBasic()
10+
ticket = TicketFactory()
11+
completed_order = OrderFactory(status='completed')
12+
13+
db.session.commit()
14+
15+
# will be counted as attendee have valid orders
16+
AttendeeFactoryBase.create_batch(
17+
1, order_id=completed_order.id, ticket_id=ticket.id, event_id=event.id
18+
)
19+
20+
response = client.get(
21+
f'/v1/events/{event.id}/attendees/search',
22+
content_type='application/vnd.api+json',
23+
headers=jwt,
24+
)
25+
26+
assert response.status_code == 200
27+
assert len(response.json['attendees']) == 1

tests/hook_main.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
from tests.factories.session import SessionFactory, SessionFactoryBasic
5252
from tests.factories.speaker import SpeakerFactory
5353
from tests.factories.ticket import TicketFactory
54-
from tests.factories.attendee import AttendeeFactory, AttendeeOrderSubFactory
54+
from tests.factories.attendee import (
55+
AttendeeFactory,
56+
AttendeeOrderSubFactory,
57+
)
5558
from tests.factories.session_type import SessionTypeFactory
5659
from tests.factories.track import TrackFactory
5760
from tests.factories.ticket_tag import TicketTagFactory
@@ -815,7 +818,7 @@ def group_get_list(transaction):
815818

816819

817820
@hooks.before("Group > Groups under an User > List All Groups under an User")
818-
def group_get_list(transaction):
821+
def group_get_list_from_user(transaction):
819822
"""
820823
GET /users/1/groups
821824
:param transaction:
@@ -3579,7 +3582,6 @@ def image_upload_post(transaction):
35793582
:param transaction:
35803583
:return:
35813584
"""
3582-
pass
35833585

35843586

35853587
@hooks.before("Upload > File Upload > Upload a File")
@@ -4957,3 +4959,18 @@ def exhibitor_delete(transaction):
49574959
with stash['app'].app_context():
49584960
ExhibitorFactory()
49594961
db.session.commit()
4962+
4963+
4964+
@hooks.before(
4965+
"Attendees > Search Attendees under an event > Search All Attendees under an event"
4966+
)
4967+
def search_attendees_from_event(transaction):
4968+
"""
4969+
GET /v1/events/{event_id}/attendees/search
4970+
:param transaction:
4971+
:return:
4972+
"""
4973+
with stash['app'].app_context():
4974+
event = EventFactoryBasic()
4975+
db.session.add(event)
4976+
db.session.commit()

0 commit comments

Comments
 (0)