def create_order(): data, errors = OrderAmountInputSchema().load(request.get_json()) if errors: return make_response(jsonify(errors), 422) tickets_dict = data['tickets'] order_amount = calculate_order_amount(tickets_dict, data.get('discount_code')) ticket_ids = {ticket['id'] for ticket in tickets_dict} ticket_map = {int(ticket['id']): ticket for ticket in tickets_dict} tickets = ( Ticket.query.filter_by(deleted_at=None).filter(Ticket.id.in_(ticket_ids)).all() ) if not tickets: raise UnprocessableEntityError( {'source': 'tickets'}, "Tickets missing in Order request", ) event = tickets[0].event try: attendees = [] for ticket in tickets: for _ in range(ticket_map[ticket.id]['quantity']): ticket.raise_if_unavailable() attendees.append( TicketHolder(firstname='', lastname='', ticket=ticket, event=event) ) db.session.commit() except Exception as e: db.session.rollback() raise e validate_attendees({attendee.id for attendee in attendees}) if data.get('amount') is not None and ( current_user.is_staff or has_access('is_coorganizer', event_id=event.id) ): # If organizer or admin has overrided the amount of order order_amount['total'] = data['amount'] order = Order( amount=order_amount['total'], event=event, discount_code_id=data.get('discount_code'), ticket_holders=attendees, ) db.session.commit() order.populate_and_save() order_tickets = OrderTicket.query.filter_by(order_id=order.id).all() for order_ticket in order_tickets: ticket_info = ticket_map[order_ticket.ticket.id] order_ticket.price = ticket_info.get('price') save_to_db(order_ticket) return OrderSchema().dump(order)
def create_order(): data, errors = OrderAmountInputSchema().load(request.get_json()) if errors: return make_response(jsonify(errors), 422) tickets_dict = data['tickets'] order_amount = calculate_order_amount(tickets_dict, data.get('discount_code')) ticket_ids = {ticket['id'] for ticket in tickets_dict} ticket_map = {int(ticket['id']): ticket for ticket in tickets_dict} tickets = ( Ticket.query.filter_by(deleted_at=None).filter(Ticket.id.in_(ticket_ids)).all() ) if not tickets: raise UnprocessableEntityError( {'source': 'tickets'}, "Tickets missing in Order request", ) event = tickets[0].event try: attendees = [] for ticket in tickets: for _ in range(ticket_map[ticket.id]['quantity']): ticket.raise_if_unavailable() attendees.append( TicketHolder(firstname='', lastname='', ticket=ticket, event=event) ) db.session.commit() except Exception as e: db.session.rollback() raise e validate_attendees({attendee.id for attendee in attendees}) order = Order( amount=order_amount['total'], event=event, discount_code_id=data.get('discount_code'), ticket_holders=attendees, ) db.session.commit() order.populate_and_save() return OrderSchema().dumps(order)
def add_target(self, data, obj): if obj.target is None: # handler -> if target data is deleted after generation of notification. # to be implemented in future -> delete notification if target is deleted ex. RoleInvite. return {} event = None if obj.target_type == 'Order': serialized = normalize_jsonapi_data( OrderSchema(only=('id', 'amount', 'identifier')), obj.target ) data['order'] = serialized event = obj.target.event elif obj.target_type == 'Session': serialized = normalize_jsonapi_data( SessionSchema(only=('id', 'title')), obj.target ) data['session'] = serialized event = obj.target.event elif obj.target_type == 'EventInvoice': serialized = normalize_jsonapi_data( EventInvoiceSchema( only=('id', 'identifier', 'amount', 'issued_at', 'due_at', 'status') ), obj.target, ) data['invoice'] = serialized event = obj.target.event elif obj.target_type == 'RoleInvite': serialized = normalize_jsonapi_data(RoleInviteSchema(), obj.target) data['event_invite'] = serialized data['role'] = normalize_jsonapi_data(RoleSchema(), obj.target.role) event = obj.target.event if event: data['event'] = normalize_jsonapi_data( EventSchemaPublic(only=('id', 'name', 'identifier')), obj.target.event ) return data
def create_order(): data = request.get_json() tickets, discount_code = calculate_order_amount_wrapper(data) attendee = data['attendee'] for attribute in attendee: attendee[attribute.replace('-', '_')] = attendee.pop(attribute) schema = AttendeeSchema() json_api_attendee = { "data": { "attributes": data['attendee'], "type": "attendee" } } result = schema.load(json_api_attendee) if result.errors: return make_response(jsonify(result.errors), 422) ticket_ids = {int(ticket['id']) for ticket in tickets} quantity = {int(ticket['id']): ticket['quantity'] for ticket in tickets} ticket_list = (db.session.query(Ticket).filter( Ticket.id.in_(ticket_ids)).filter_by(event_id=data['event_id'], deleted_at=None).all()) ticket_ids_found = { ticket_information.id for ticket_information in ticket_list } tickets_not_found = ticket_ids - ticket_ids_found if tickets_not_found: return make_response( jsonify( status='Order Unsuccessful', error='Tickets with id {} were not found in Event {}.'.format( tickets_not_found, data['event_id']), ), 404, ) for ticket_info in ticket_list: if (ticket_info.quantity - get_count( db.session.query(TicketHolder.id).filter_by( ticket_id=int(ticket_info.id), deleted_at=None))) < quantity[ticket_info.id]: return make_response( jsonify(status='Order Unsuccessful', error='Ticket already sold out.'), 409, ) attendee_list = [] for ticket in tickets: for ticket_amount in range(ticket['quantity']): attendee = TicketHolder(**result[0], event_id=int(data['event_id']), ticket_id=int(ticket['id'])) db.session.add(attendee) attendee_list.append(attendee) ticket_pricing = calculate_order_amount(tickets, discount_code) if not has_access('is_coorganizer', event_id=data['event_id']): data['status'] = 'initializing' # create on site attendees # check if order already exists for this attendee. # check for free tickets and verified user order = Order( amount=ticket_pricing['total_amount'], user_id=current_user.id, event_id=int(data['event_id']), status=data['status'], ) db.session.add(order) db.session.commit() db.session.refresh(order) order_tickets = {} for holder in attendee_list: holder.order_id = order.id db.session.add(holder) if not order_tickets.get(holder.ticket_id): order_tickets[holder.ticket_id] = 1 else: order_tickets[holder.ticket_id] += 1 create_pdf_tickets_for_holder(order) for ticket in order_tickets: od = OrderTicket(order_id=order.id, ticket_id=ticket, quantity=order_tickets[ticket]) db.session.add(od) order.quantity = order.tickets_count db.session.add(order) db.session.commit() db.session.refresh(order) order_schema = OrderSchema() return order_schema.dump(order)
def complete_order(order_id): data = request.get_json() for attribute in data: data[attribute.replace('-', '_')] = data.pop(attribute) order = Order.query.filter_by(id=order_id).first() order_schema = OrderSchema() if (not has_access('is_coorganizer', event_id=order.event_id)) and ( not current_user.id == order.user_id): return make_response( jsonify(status='Access Forbidden', error='You cannot update an order.'), 403) if has_access('is_coorganizer', event_id=order.event_id) and 'status' in data: if data['status'] != 'cancelled': return make_response( jsonify(status='Access Forbidden', error='You can only cancel an order.'), 403, ) elif data['status'] == 'cancelled': order.status = 'cancelled' db.session.add(order) attendees = (db.session.query(TicketHolder).filter_by( order_id=order_id, deleted_at=None).all()) for attendee in attendees: attendee.deleted_at = datetime.now(pytz.utc) db.session.add(attendee) db.session.commit() send_order_cancel_email(order) send_notif_ticket_cancel(order) return order_schema.dump(order) updated_attendees = data['attendees'] for updated_attendee in updated_attendees: for attribute in updated_attendee: updated_attendee[attribute.replace( '-', '_')] = updated_attendee.pop(attribute) if get_count(db.session.query(TicketHolder).filter_by( order_id=order_id)) != len(updated_attendees): return make_response( jsonify( status='Unprocessable Entity', error='You need to provide info of all attendees.', ), 422, ) else: attendees = (db.session.query(TicketHolder).filter_by( order_id=order_id, deleted_at=None).all()) form_fields = (db.session.query(CustomForms).filter_by( event_id=order.event_id, form='attendee', is_included=True).all()) for attendee, updated_attendee in zip(attendees, updated_attendees): for field in form_fields: if (field.is_required is True and field.field_identifier not in updated_attendee): return make_response( jsonify( status='Unprocessable Entity', error='{} is a required field.'.format( field.field_identifier), ), 422, ) if field.field_identifier in updated_attendee: setattr( attendee, field.field_identifier, updated_attendee[field.field_identifier], ) db.session.add(attendee) # modified_at not getting filled if order.amount == 0: order.status = 'completed' order.completed_at = datetime.utcnow() elif order.amount > 0: if 'payment_mode' not in data: return make_response( jsonify(status='Unprocessable Entity', error='Payment mode not specified.'), 422, ) if data['payment_mode'] in ['bank', 'cheque', 'onsite']: order.status = 'placed' order.completed_at = datetime.utcnow() else: order.status = 'pending' if 'is_billing_enabled' in data: if data['is_billing_enabled']: if (('company' not in data) or ('address' not in data) or ('city' not in data) or ('zipcode' not in data) or ('country' not in data)): return make_response( jsonify( status='Unprocessable Entity', error='Billing information incomplete.', ), 422, ) else: return make_response( jsonify( status='Unprocessable Entity', error='Billing information incomplete.', ), 422, ) else: return make_response( jsonify( status='Unprocessable Entity', error='Billing information is mandatory ' 'for this order.', ), 422, ) order.company = data['company'] order.address = data['address'] order.city = data['city'] order.zipcode = data['zipcode'] order.country = data['country'] order.payment_mode = data['payment_mode'] if 'state' in data: order.state = data['state'] if 'tax_business_info' in data: order.tax_business_info = data['tax_business_info'] db.session.add(order) db.session.commit() create_pdf_tickets_for_holder(order) if (order.status == 'completed' or order.status == 'placed') and (order.deleted_at is None): order_identifier = order.identifier key = UPLOAD_PATHS['pdf']['tickets_all'].format( identifier=order_identifier) ticket_path = ( 'generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf') key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier) invoice_path = ( 'generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf') # send email and notifications. send_email_to_attendees( order=order, purchaser_id=current_user.id, attachments=[ticket_path, invoice_path], ) send_notif_to_attendees(order, current_user.id) order_url = make_frontend_url(path='/orders/{identifier}'.format( identifier=order.identifier)) for organizer in order.event.organizers: send_notif_ticket_purchase_organizer( organizer, order.invoice_number, order_url, order.event.name, order.identifier, ) if order.event.owner: send_notif_ticket_purchase_organizer( order.event.owner, order.invoice_number, order_url, order.event.name, order.identifier, ) return order_schema.dump(order)