internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: fossasia/open-event-server

Issue:
ConflictException wrongly raised in the before_post of Attendee
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
When creating an attendee ConflictException is raised when we try to create an attendee on a ticket which already has an attendee. It is not correct. 
If we have a ticket whose quantity is 10, it will not allow creating more than one attendee on that ticket even though it should allow upto 10 attendees on it.

**To Reproduce**
Steps to reproduce the behavior:
1. Try to create an attendee on a ticket which already has an Attendee.

**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
It should check for number of TicketHolders with that ticket and compare it with the ticket quantity.

**Additional context**
<!-- Add any other context about the problem here. -->
Related code:
```Python
        if db.session.query(TicketHolder.id).filter_by(
                ticket_id=int(data['ticket']), event_id=int(data['event'])
                ).scalar() is not None:
            raise ConflictException(
                {'pointer': '/data/attributes/ticket_id'},
                "Attendee with this ticket already exists for the same event"
            )
```



Discussion:

Resolving patch:
diff --git a/app/api/attendees.py b/app/api/attendees.py
--- a/app/api/attendees.py
+++ b/app/api/attendees.py
@@ -2,7 +2,7 @@
 from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
 
 from app.api.bootstrap import api
-from app.api.helpers.db import safe_query
+from app.api.helpers.db import safe_query, get_count
 from app.api.helpers.exceptions import (
     ConflictException,
     ForbiddenException,
@@ -47,13 +47,12 @@ def before_post(self, args, kwargs, data):
                 {'pointer': '/data/relationships/ticket'},
                 "Ticket belongs to a different Event"
             )
-
-        if db.session.query(TicketHolder.id).filter_by(
-                ticket_id=int(data['ticket']), event_id=int(data['event']), deleted_at=None
-                ).scalar() is not None:
+        # Check if the ticket is already sold out or not.
+        if get_count(db.session.query(TicketHolder.id).
+                     filter_by(ticket_id=int(data['ticket']), deleted_at=None)) >= ticket.quantity:
             raise ConflictException(
                 {'pointer': '/data/attributes/ticket_id'},
-                "Attendee with this ticket already exists for the same event"
+                "Ticket already sold out"
             )
 
     decorators = (jwt_required,)


Test patch:
Repository: fossasia/open-event-server

Issue:
Send pdf tickets and notifications only after the payment is successful
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
Right now we are sending pdf tickets and notifications in the `after_create_object` of the orders endpoint regardless of the state of the order.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
Only send notifications and tickets when the payment is successful.

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
Parent #4852 


Discussion:

Resolving patch:
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -113,12 +113,15 @@ def after_create_object(self, order, data, view_kwargs):
         save_to_db(order)
         if not has_access('is_coorganizer', event_id=data['event']):
             TicketingManager.calculate_update_amount(order)
-        send_email_to_attendees(order, current_user.id)
-        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)
+        # send e-mail and notifications if the order status is completed
+        if order.status == 'completed':
+            send_email_to_attendees(order, current_user.id)
+            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)
 
         data['user_id'] = current_user.id
 
diff --git a/app/api/schema/orders.py b/app/api/schema/orders.py
--- a/app/api/schema/orders.py
+++ b/app/api/schema/orders.py
@@ -53,7 +53,7 @@ def initial_values(self, data):
     exp_month = fields.Str(dump_only=True)
     exp_year = fields.Str(dump_only=True)
     last4 = fields.Str(dump_only=True)
-    status = fields.Str(validate=validate.OneOf(choices=["pending", "cancelled", "confirmed", "deleted"]))
+    status = fields.Str(validate=validate.OneOf(choices=["pending", "cancelled", "completed", "placed", "expired"]))
     discount_code_id = fields.Str()
     payment_url = fields.Str(dump_only=True)
     cancel_note = fields.Str()


Test patch:
Repository: fossasia/open-event-server

Issue:
List most important event locations
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
 As seen with https://github.com/fossasia/open-event-frontend/pull/1304 the event locations need to be added dynamically, this has not yet been implemented on the server.

We need an API route that gives us the most important event locations. This should be done dynamically, however I can imagine it would take a lot of time to implement, so we're just going to provide a mockup for now.


Discussion:

Resolving patch:
diff --git a/app/models/event_location.py b/app/models/event_location.py
new file mode 100644
--- /dev/null
+++ b/app/models/event_location.py
@@ -0,0 +1,36 @@
+import uuid
+
+from app.api.helpers.db import get_count
+from app.models import db
+
+
+def get_new_slug(name):
+    slug = name.lower().replace("& ", "").replace(",", "").replace("/", "-").replace(" ", "-")
+    count = get_count(EventLocation.query.filter_by(slug=slug))
+    if count == 0:
+        return slug
+    else:
+        return '{}-{}'.format(slug, uuid.uuid4().hex)
+
+
+class EventLocation(db.Model):
+    """Event location object table"""
+
+    __tablename__ = 'event_locations'
+
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
+    name = db.Column(db.String, nullable=False)
+    slug = db.Column(db.String, unique=True, nullable=False)
+
+    def __init__(self,
+                 name=None,
+                 slug=None):
+
+        self.name = name
+        self.slug = get_new_slug(name=self.name)
+
+    def __repr__(self):
+        return '<EventLocation %r>' % self.slug
+
+    def __str__(self):
+        return self.__repr__()
diff --git a/populate_db.py b/populate_db.py
--- a/populate_db.py
+++ b/populate_db.py
@@ -33,6 +33,9 @@
 # EventType
 from app.models.event_type import EventType
 
+# EventLocation
+from app.models.event_location import EventLocation
+
 # User Permissions
 from app.models.user_permission import UserPermission
 SALES = 'sales'
@@ -117,6 +120,12 @@ def create_event_types():
         get_or_create(EventType, name=type_)
 
 
+def create_event_locations():
+    event_location = ['India', 'Singapore', 'Berlin', 'New York', 'Hong Kong']
+    for loc_ in event_location:
+        get_or_create(EventLocation, name=loc_)
+
+
 def create_permissions():
     orgr = Role.query.get(1)
     coorgr = Role.query.get(2)
@@ -246,6 +255,8 @@ def populate():
     create_event_topics()
     print('Creating Event Types...')
     create_event_types()
+    print('Creating Event Locations...')
+    create_event_locations()
     print('Creating admin message settings...')
     create_admin_message_settings()
 
@@ -266,6 +277,7 @@ def populate_without_print():
     create_speaker_image_sizes()
     create_event_topics()
     create_event_types()
+    create_event_locations()
     create_admin_message_settings()
 
     db.session.commit()


Test patch:
Repository: fossasia/open-event-server

Issue:
Minor bug in export orders as CSV task
**Describe the bug**
Minor bug in exporting orders as CSV. Trying to decode string which throws a type error:
```python
                      if order.user and order.user.first_name else '',
                      str(order.user.last_name, 'utf-8')
```

**To Reproduce**
Steps to reproduce the behavior:
1. Start export orders as csv task 
2. Make sure user is linked for that particular order
3. See the error

**Expected behavior**
It should work properly

**Stacktrace**
```sh
  File "/home/mayank/OpenSource/open-event-server/app/api/helpers/tasks.py", line 238, in export_order_csv_task
    content = export_orders_csv(orders)
  File "/home/mayank/OpenSource/open-event-server/app/api/helpers/csv_jobs_util.py", line 13, in export_orders_csv
    if order.user and order.user.first_name else '',
TypeError: decoding str is not supported
```
**Additional details (please complete the following information):**
 - OS: Ubuntu 18.04
 - Python Version 3.6
 - `HEAD` Commit hash [e.g. `4629c62`]


Discussion:
I guess removing the `utf-8` argument should fix this error.
@schedutron yes :+1: 

Resolving patch:
diff --git a/app/api/helpers/csv_jobs_util.py b/app/api/helpers/csv_jobs_util.py
--- a/app/api/helpers/csv_jobs_util.py
+++ b/app/api/helpers/csv_jobs_util.py
@@ -9,11 +9,11 @@ def export_orders_csv(orders):
                       str(order.status) if order.status else '', str(order.paid_via) if order.paid_via else '',
                       str(order.amount) if order.amount else '', str(order.get_tickets_count()),
                       str(order.discount_code.code) if order.discount_code else '',
-                      str(order.user.first_name, 'utf-8')
+                      str(order.user.first_name)
                       if order.user and order.user.first_name else '',
-                      str(order.user.last_name, 'utf-8')
+                      str(order.user.last_name)
                       if order.user and order.user.last_name else '',
-                      str(order.user._email, 'utf-8') if order.user and order.user._email else '']
+                      str(order.user.email) if order.user and order.user.email else '']
             rows.append(column)
 
     return rows


Test patch:
Repository: fossasia/open-event-server

Issue:
Only allow the event organizer/admin to delete the order
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
Right now anyone can delete an order.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
Allow Event Organizer/Admin to delete the order only **when the order is free** since we don't have refund system.

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
#4852 


Discussion:

Resolving patch:
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -260,6 +260,8 @@ def before_delete_object(self, order, view_kwargs):
         """
         if not has_access('is_coorganizer', event_id=order.event.id):
             raise ForbiddenException({'source': ''}, 'Access Forbidden')
+        elif order.amount and order.amount > 0 and (order.status == 'completed' or order.status == 'placed'):
+            raise ConflictException({'source': ''}, 'You cannot delete a placed/completed paid order.')
 
     decorators = (jwt_required,)
 


Test patch:
Repository: fossasia/open-event-server

Issue:
Set allow_none to true in fields of Order schema
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
Set allow_none to true in fields of Order schema since when the request is made from Java/JS, the empty fields can be None which raises HTTP 422

Parent: #4852 


Discussion:

Resolving patch:
diff --git a/app/api/schema/orders.py b/app/api/schema/orders.py
--- a/app/api/schema/orders.py
+++ b/app/api/schema/orders.py
@@ -39,11 +39,11 @@ def initial_values(self, data):
     id = fields.Str(dump_only=True)
     identifier = fields.Str(dump_only=True)
     amount = fields.Float(validate=lambda n: n > 0)
-    address = fields.Str()
-    city = fields.Str()
-    state = fields.Str(db.String)
-    country = fields.Str()
-    zipcode = fields.Str()
+    address = fields.Str(allow_none=True)
+    city = fields.Str(allow_none=True)
+    state = fields.Str(db.String, allow_none=True)
+    country = fields.Str(allow_none=True)
+    zipcode = fields.Str(allow_none=True)
     completed_at = fields.DateTime(dump_only=True)
     transaction_id = fields.Str(dump_only=True)
     payment_mode = fields.Str(default="free",
@@ -54,9 +54,9 @@ def initial_values(self, data):
     exp_year = fields.Str(dump_only=True)
     last4 = fields.Str(dump_only=True)
     status = fields.Str(validate=validate.OneOf(choices=["pending", "cancelled", "completed", "placed", "expired"]))
-    discount_code_id = fields.Str()
+    discount_code_id = fields.Str(allow_none=True)
     payment_url = fields.Str(dump_only=True)
-    cancel_note = fields.Str()
+    cancel_note = fields.Str(allow_none=True)
     order_notes = fields.Str(allow_none=True)
 
     attendees = Relationship(attribute='ticket_holders',


Test patch:
Repository: fossasia/open-event-server

Issue:
Database not migrated after addition of location model
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
Database not migrated after addition of location model in #4982 


Discussion:
@Kreijstal @bhaveshAn @mayank8318 @schedutron You can fix this if you want.
I would need to have a snapshot of the old database, because when I run manage.py db migrate it doesn't detect any changes. 
The migration file was generated on my machine locally. Will push it.

Resolving patch:
diff --git a/migrations/versions/000b9376b87b_.py b/migrations/versions/000b9376b87b_.py
new file mode 100644
--- /dev/null
+++ b/migrations/versions/000b9376b87b_.py
@@ -0,0 +1,34 @@
+"""empty message
+
+Revision ID: 000b9376b87b
+Revises: 6440077182f0
+Create Date: 2018-07-05 09:52:56.681093
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+import sqlalchemy_utils
+
+
+# revision identifiers, used by Alembic.
+revision = '000b9376b87b'
+down_revision = '6440077182f0'
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('event_locations',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('name', sa.String(), nullable=False),
+    sa.Column('slug', sa.String(), nullable=False),
+    sa.PrimaryKeyConstraint('id'),
+    sa.UniqueConstraint('slug')
+    )
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('event_locations')
+    # ### end Alembic commands ###


Test patch:
Repository: fossasia/open-event-server

Issue:
Unskip dredd test for PATCH Sponsors and POST attendee
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
Currently, we are skipping the dredd test for PATCH Sponsors and POST attendee
**To Reproduce**
Steps to reproduce the behavior:
1. Go to  A travis build logs and can find easily
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
Modify the dredd tests to pass.
**Stacktrace**
<!-- If applicable, add stacktrace to help explain your problem. -->

**Additional details (please complete the following information):**
 - OS: [e.g. MacOS, Ubuntu, CentOS]
 - Python Version [e.g. `3.5`, `3.6`]
 - `HEAD` Commit hash [e.g. `4629c62`]

**Additional context**
<!-- Add any other context about the problem here. -->

**Wanna work on this issue**


Discussion:

Resolving patch:
diff --git a/app/factories/attendee.py b/app/factories/attendee.py
--- a/app/factories/attendee.py
+++ b/app/factories/attendee.py
@@ -21,3 +21,4 @@ class Meta:
     is_checked_in = True
     pdf_url = common.url_
     event_id = 1
+    ticket_id = None


Test patch:
diff --git a/tests/hook_main.py b/tests/hook_main.py
--- a/tests/hook_main.py
+++ b/tests/hook_main.py
@@ -1473,8 +1473,6 @@ def sponsor_patch(transaction):
     :param transaction:
     :return:
     """
-    # Skip until docs for direct endpoints added
-    transaction['skip'] = True
 
     with stash['app'].app_context():
         sponsor = SponsorFactory()
@@ -1804,7 +1802,13 @@ def attendee_post(transaction):
     :return:
     """
     # Skip until docs for direct endpoints added
-    transaction['skip'] = True
+    with stash['app'].app_context():
+        ticket = TicketFactory()
+        db.session.add(ticket)
+
+        attendee = AttendeeFactory(ticket_id=1)
+        db.session.add(attendee)
+        db.session.commit()
 
 
 @hooks.before("Attendees > Attendee Details > Attendee Details")
Repository: fossasia/open-event-server

Issue:
Disallow updating the status of a cancelled order
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
Disallow updating the status of a cancelled order since once the order is cancelled the tickets are unlocked. If in the future we try to uncancel it then we may not be sure that the tickets will be available or not, hence once the order is cancelled, then it shouldn't be allowed to invert it.

**Additional context**
<!-- Add any other context about the problem here. -->
Parent #4852 


Discussion:

Resolving patch:
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -225,6 +225,10 @@ def before_update_object(self, order, data, view_kwargs):
                             # Since we don't have a refund system.
                             raise ForbiddenException({'pointer': 'data/status'},
                                                      "You cannot update the status of a completed paid order")
+                        elif element == 'status' and order.status == 'cancelled':
+                            # Since the tickets have been unlocked and we can't revert it.
+                            raise ForbiddenException({'pointer': 'data/status'},
+                                                     "You cannot update the status of a cancelled order")
 
         elif current_user.id == order.user_id:
             if order.status != 'pending':


Test patch:
Repository: fossasia/open-event-server

Issue:
Delete the associated attendees after deleting an order so that tickets are unlocked
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
After deleting an order, the server should also delete the associated attendees with the order so that the tickets are unlocked.

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
Parent #4852 


Discussion:

Resolving patch:
diff --git a/app/api/helpers/order.py b/app/api/helpers/order.py
new file mode 100644
--- /dev/null
+++ b/app/api/helpers/order.py
@@ -0,0 +1,17 @@
+import logging
+
+
+def delete_related_attendees_for_order(self, order):
+    """
+    Delete the associated attendees of an order when it is cancelled/deleted/expired
+    :param self:
+    :param order: Order whose attendees have to be deleted.
+    :return:
+    """
+    for ticket_holder in order.ticket_holders:
+        self.session.delete(ticket_holder)
+        try:
+            self.session.commit()
+        except Exception as e:
+            logging.error('DB Exception! %s' % e)
+            self.session.rollback()
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -20,6 +20,7 @@
 from app.api.helpers.permission_manager import has_access
 from app.api.helpers.permissions import jwt_required
 from app.api.helpers.query import event_query
+from app.api.helpers.order import delete_related_attendees_for_order
 from app.api.helpers.ticketing import TicketingManager
 from app.api.helpers.utilities import dasherize, require_relationship
 from app.api.schema.orders import OrderSchema
@@ -262,6 +263,9 @@ def after_update_object(self, order, data, view_kwargs):
             send_order_cancel_email(order)
             send_notif_ticket_cancel(order)
 
+            # delete the attendees so that the tickets are unlocked.
+            delete_related_attendees_for_order(self, order)
+
     def before_delete_object(self, order, view_kwargs):
         """
         method to check for proper permissions for deleting


Test patch:
Repository: fossasia/open-event-server

Issue:
Allow amount to be null in a free order
**Describe the bug**
Currently, the amount in the body of order has to be > 0 even for free tickets, which should not be the case

**To Reproduce**
Steps to reproduce the behavior:
1. Try creating an order for any free ticket
2. Keep amount in order body as 0 
4. See error

**Expected behavior**
The amount should be allowed to be 0 for free tickets



Discussion:
If it is a free order, simply send amount as null.
Create a helper function `Utils.zeroToNull` in the android project which takes the number and returns null if the number is zero. Similar to `TextUtils.emptyToNull` which returns null for an empty string. 
@srv-twry please look at it
![image](https://user-images.githubusercontent.com/16715499/42360967-82c4beb2-8109-11e8-9fa0-93b658fa34d8.png)

Alright, I'll fix this null issue. Thanks for reporting!

Resolving patch:
diff --git a/app/api/orders.py b/app/api/orders.py
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -69,6 +69,10 @@ def before_create_object(self, data, view_kwargs):
         if data.get('cancel_note'):
             del data['cancel_note']
 
+        if data.get('payment_mode') != 'free' and not data.get('amount'):
+            raise ConflictException({'pointer': '/data/attributes/amount'},
+                                    "Amount cannot be null for a paid order")
+
         # Apply discount only if the user is not event admin
         if data.get('discount') and not has_access('is_coorganizer', event_id=data['event']):
             discount_code = safe_query_without_soft_deleted_entries(self, DiscountCode, 'id', data['discount'],
diff --git a/app/api/schema/orders.py b/app/api/schema/orders.py
--- a/app/api/schema/orders.py
+++ b/app/api/schema/orders.py
@@ -38,7 +38,7 @@ def initial_values(self, data):
 
     id = fields.Str(dump_only=True)
     identifier = fields.Str(dump_only=True)
-    amount = fields.Float(validate=lambda n: n > 0)
+    amount = fields.Float(validate=lambda n: n > 0, allow_none=True)
     address = fields.Str(allow_none=True)
     city = fields.Str(allow_none=True)
     state = fields.Str(db.String, allow_none=True)


Test patch: