Repository: fossasia/open-event-server

Issue:
Wrong Ticket Type for Free Tickets
**Describe the bug**
The ticket type of free tickets is shown as TICKET_TYPE_PAID.

**To Reproduce**
Try booking a ticket using attendee app.

**Expected behavior**
The ticket type of free tickets should be TICKET_TYPE_FREE.




Discussion:
Paste the URL and response
URL: https://open-event-api-dev.herokuapp.com/v1/events/11/tickets?include=event&fields[event]=id&page[size]=0
Response:
```
{"data": {"type": "ticket", "attributes": {"min-order": 1, "min-price": 1.0, "position": 3, "name": "Ticket 4", "is-hidden": false, "is-fee-absorbed": true, "type": "paid", "quantity": 3, "max-order": 3, "sales-starts-at": "2019-11-10T14:33:08.623000+00:00", "description": null, "is-description-visible": true, "price": 0.0, "sales-ends-at": "2019-12-13T08:30:00+00:00", "is-checkin-restricted": true, "auto-checkin-enabled": false, "deleted-at": null, "max-price": 0.0}, "id": "20", "relationships": {"ticket-tags": {"links": {"self": "/v1/tickets/20/relationships/ticket-tags", "related": "/v1/tickets/20/ticket-tags"}}, "event": {"links": {"self": "/v1/tickets/20/relationships/event", "related": "/v1/tickets/20/event"}, "data": {"type": "event", "id": "11"}}, "access-codes": {"links": {"self": "/v1/tickets/20/relationships/access-codes", "related": "/v1/tickets/20/access-codes"}}, "discount-codes": {"links": {"self": "/v1/tickets/20/relationships/discount-codes", "related": "/v1/tickets/20/discount-codes"}}, "attendees": {"links": {"self": "/v1/tickets/20/relationships/attendees", "related": "/v1/attendees?ticket_id=20"}}}, "links": {"self": "/v1/tickets/20"}}], "included": [{"type": "event", "id": "11", "links": {"self": "/v1/events/11"}}], "links": {"self": "/v1/events/11/tickets?include=event&fields%5Bevent%5D=id&page%5Bsize%5D=0"}, "meta": {"count": 4}, "jsonapi": {"version": "1.0"}}
```
@rob729 Are you working on this?
No
Taking this up!
I am getting the correct type for free and paid ticket. 
I created the event with ticket on my local machine.
```
{
    "data": [
        {
            "type": "ticket",
            "attributes": {
                "is-fee-absorbed": true,
                "sales-starts-at": "2019-11-17T15:04:23.414000+00:00",
                "price": 0.0,
                "max-price": 0.0,
                "type": "free",
                "is-description-visible": true,
                "quantity": 10,
                "is-checkin-restricted": true,
                "min-price": 1.0,
                "description": null,
                "name": "Free ticket",
                "deleted-at": null,
                "position": 0,
                "auto-checkin-enabled": false,
                "max-order": 10,
                "min-order": 1,
                "is-hidden": false,
                "sales-ends-at": "2019-12-16T16:20:00+00:00"
            },
            "relationships": {
                "ticket-tags": {
                    "links": {
                        "self": "/v1/tickets/1/relationships/ticket-tags",
                        "related": "/v1/tickets/1/ticket-tags"
                    }
                },
                "attendees": {
                    "links": {
                        "self": "/v1/tickets/1/relationships/attendees",
                        "related": "/v1/attendees?ticket_id=1"
                    }
                },
                "event": {
                    "links": {
                        "self": "/v1/tickets/1/relationships/event",
                        "related": "/v1/tickets/1/event"
                    },
                    "data": {
                        "type": "event",
                        "id": "11"
                    }
                },
                "discount-codes": {
                    "links": {
                        "self": "/v1/tickets/1/relationships/discount-codes",
                        "related": "/v1/tickets/1/discount-codes"
                    }
                },
                "access-codes": {
                    "links": {
                        "self": "/v1/tickets/1/relationships/access-codes",
                        "related": "/v1/tickets/1/access-codes"
                    }
                }
            },
            "id": "1",
            "links": {
                "self": "/v1/tickets/1"
            }
        },
        {
            "type": "ticket",
            "attributes": {
                "is-fee-absorbed": true,
                "sales-starts-at": "2019-11-17T15:04:49.355000+00:00",
                "price": 100.0,
                "max-price": 0.0,
                "type": "paid",
                "is-description-visible": true,
                "quantity": 1,
                "is-checkin-restricted": true,
                "min-price": 1.0,
                "description": null,
                "name": "Paid Ticket",
                "deleted-at": null,
                "position": 1,
                "auto-checkin-enabled": false,
                "max-order": 1,
                "min-order": 1,
                "is-hidden": false,
                "sales-ends-at": "2019-12-10T16:20:00+00:00"
            },
            "relationships": {
                "ticket-tags": {
                    "links": {
                        "self": "/v1/tickets/2/relationships/ticket-tags",
                        "related": "/v1/tickets/2/ticket-tags"
                    }
                },
                "attendees": {
                    "links": {
                        "self": "/v1/tickets/2/relationships/attendees",
                        "related": "/v1/attendees?ticket_id=2"
                    }
                },
                "event": {
                    "links": {
                        "self": "/v1/tickets/2/relationships/event",
                        "related": "/v1/tickets/2/event"
                    },
                    "data": {
                        "type": "event",
                        "id": "11"
                    }
                },
                "discount-codes": {
                    "links": {
                        "self": "/v1/tickets/2/relationships/discount-codes",
                        "related": "/v1/tickets/2/discount-codes"
                    }
                },
                "access-codes": {
                    "links": {
                        "self": "/v1/tickets/2/relationships/access-codes",
                        "related": "/v1/tickets/2/access-codes"
                    }
                }
            },
            "id": "2",
            "links": {
                "self": "/v1/tickets/2"
            }
        }
    ],
    "included": [
        {
            "type": "event",
            "attributes": {
                "ticket-url": null,
                "is-tax-enabled": false,
                "has-sessions": false,
                "owner-description": null,
                "bank-details": null,
                "is-sponsors-enabled": false,
                "external-event-url": null,
                "onsite-details": "onsite",
                "tickets-available": 11.0,
                "deleted-at": null,
                "location-name": "New Delhi  Delhi Delhi 110018 India",
                "can-pay-by-alipay": false,
                "thumbnail-image-url": null,
                "pentabarf-url": null,
                "average-rating": null,
                "has-speakers": false,
                "owner-name": null,
                "is-map-shown": true,
                "has-owner-info": false,
                "searchable-location-name": "Delhi",
                "icon-image-url": null,
                "payment-currency": "INR",
                "description": "",
                "latitude": 0.0,
                "is-billing-info-mandatory": false,
                "name": "Test Event",
                "payment-country": "India",
                "tickets-sold": 1.0,
                "revenue": 0.0,
                "can-pay-by-paytm": false,
                "is-ticketing-enabled": true,
                "longitude": 0.0,
                "state": "published",
                "can-pay-by-paypal": false,
                "cheque-details": null,
                "is-sessions-speakers-enabled": false,
                "created-at": "2019-11-17T15:05:51.729386+00:00",
                "ends-at": "2019-12-17T11:30:43.181000+00:00",
                "is-ticket-form-enabled": true,
                "identifier": "f70146db",
                "paypal-email": null,
                "starts-at": "2019-11-17T16:20:00+00:00",
                "privacy": "public",
                "large-image-url": null,
                "can-pay-by-omise": false,
                "can-pay-by-stripe": false,
                "schedule-published-on": "1970-01-01T00:00:00+00:00",
                "is-event-online": false,
                "show-remaining-tickets": false,
                "can-pay-by-bank": false,
                "code-of-conduct": null,
                "timezone": "Asia/Calcutta",
                "refund-policy": "All sales are final. No refunds shall be issued in any case.",
                "original-image-url": null,
                "logo-url": null,
                "is-stripe-linked": false,
                "can-pay-onsite": true,
                "ical-url": null,
                "is-featured": false,
                "is-donation-enabled": false,
                "xcal-url": null,
                "can-pay-by-cheque": false
            },
            "id": "11",
            "relationships": {
                "owner": {
                    "links": {
                        "self": "/v1/events/11/relationships/owner",
                        "related": "/v1/events/11/owner"
                    }
                },
                "event-orga": {
                    "links": {
                        "self": "/v1/events/11/relationships/event-orga",
                        "related": "/v1/events/11/event-orga"
                    }
                },
                "coorganizers": {
                    "links": {
                        "self": "/v1/events/11/relationships/coorganizers",
                        "related": "/v1/users"
                    }
                },
                "speakers-call": {
                    "links": {
                        "self": "/v1/events/11/relationships/speakers-call",
                        "related": "/v1/events/11/speakers-call"
                    }
                },
                "sessions": {
                    "links": {
                        "self": "/v1/events/11/relationships/sessions",
                        "related": "/v1/events/11/sessions"
                    }
                },
                "event-sub-topic": {
                    "links": {
                        "self": "/v1/events/11/relationships/event-sub-topic",
                        "related": "/v1/events/11/event-sub-topic"
                    }
                },
                "event-copyright": {
                    "links": {
                        "self": "/v1/events/11/relationships/event-copyright",
                        "related": "/v1/events/11/event-copyright"
                    }
                },
                "social-links": {
                    "links": {
                        "self": "/v1/events/11/relationships/social-links",
                        "related": "/v1/events/11/social-links"
                    }
                },
                "faqs": {
                    "links": {
                        "self": "/v1/events/11/relationships/faqs",
                        "related": "/v1/events/11/faqs"
                    }
                },
                "feedbacks": {
                    "links": {
                        "self": "/v1/events/11/relationships/feedbacks",
                        "related": "/v1/events/11/feedbacks"
                    }
                },
                "tickets": {
                    "links": {
                        "self": "/v1/events/11/relationships/tickets",
                        "related": "/v1/events/11/tickets"
                    }
                },
                "microlocations": {
                    "links": {
                        "self": "/v1/events/11/relationships/microlocations",
                        "related": "/v1/events/11/microlocations"
                    }
                },
                "tax": {
                    "links": {
                        "self": "/v1/events/11/relationships/tax",
                        "related": "/v1/events/11/tax"
                    }
                },
                "tracks": {
                    "links": {
                        "self": "/v1/events/11/relationships/tracks",
                        "related": "/v1/events/11/tracks"
                    }
                },
                "event-type": {
                    "links": {
                        "self": "/v1/events/11/relationships/event-type",
                        "related": "/v1/events/11/event-type"
                    }
                },
                "speakers": {
                    "links": {
                        "self": "/v1/events/11/relationships/speakers",
                        "related": "/v1/events/11/speakers"
                    }
                },
                "stripe-authorization": {
                    "links": {
                        "self": "/v1/stripe-authorizations/11/relationships/event",
                        "related": "/v1/events/11/stripe-authorization"
                    }
                },
                "session-types": {
                    "links": {
                        "self": "/v1/events/11/relationships/session-types",
                        "related": "/v1/events/11/session-types"
                    }
                },
                "ticket-tags": {
                    "links": {
                        "self": "/v1/events/11/relationships/ticket-tags",
                        "related": "/v1/events/11/ticket-tags"
                    }
                },
                "organizers": {
                    "links": {
                        "self": "/v1/events/11/relationships/organizers",
                        "related": "/v1/users"
                    }
                },
                "event-topic": {
                    "links": {
                        "self": "/v1/events/11/relationships/event-topic",
                        "related": "/v1/events/11/event-topic"
                    }
                },
                "sponsors": {
                    "links": {
                        "self": "/v1/events/11/relationships/sponsors",
                        "related": "/v1/events/11/sponsors"
                    }
                },
                "faq-types": {
                    "links": {
                        "self": "/v1/events/11/relationships/faq-types",
                        "related": "/v1/events/11/faq-types"
                    }
                },
                "custom-forms": {
                    "links": {
                        "self": "/v1/events/11/relationships/custom-forms",
                        "related": "/v1/events/11/custom-forms"
                    }
                }
            },
            "links": {
                "self": "/v1/events/11"
            }
        }
    ],
    "links": {
        "self": "/v1/events/11/tickets?include=event&page%5Bsize%5D=0"
    },
    "meta": {
        "count": 2
    },
    "jsonapi": {
        "version": "1.0"
    }
}
```

Also working fine on dev env 

Endpoint: https://open-event-api-dev.herokuapp.com/v1/events/9/tickets?include=event&fields[event]=id&page[size]=0 (1294ms)

```
{"data": [{"type": "ticket", "relationships": {"event": {"links": {"self": "/v1/tickets/8/relationships/event", "related": "/v1/tickets/8/event"}, "data": {"type": "event", "id": "9"}}, "ticket-tags": {"links": {"self": "/v1/tickets/8/relationships/ticket-tags", "related": "/v1/tickets/8/ticket-tags"}}, "discount-codes": {"links": {"self": "/v1/tickets/8/relationships/discount-codes", "related": "/v1/tickets/8/discount-codes"}}, "attendees": {"links": {"self": "/v1/tickets/8/relationships/attendees", "related": "/v1/attendees?ticket_id=8"}}, "access-codes": {"links": {"self": "/v1/tickets/8/relationships/access-codes", "related": "/v1/tickets/8/access-codes"}}}, "attributes": {"description": "This is a free ticket", "max-order": 10, "min-order": 1, "price": 0.0, "is-checkin-restricted": true, "name": "Free ticket", "is-fee-absorbed": true, "sales-starts-at": "2019-11-10T07:28:24.392000+00:00", "position": 0, "deleted-at": null, "sales-ends-at": "2019-11-18T18:30:00+00:00", "quantity": 100, "auto-checkin-enabled": false, "is-hidden": false, "is-description-visible": true, "max-price": 0.0, "min-price": 1.0, "type": "free"}, "id": "8", "links": {"self": "/v1/tickets/8"}}, {"type": "ticket", "relationships": {"event": {"links": {"self": "/v1/tickets/9/relationships/event", "related": "/v1/tickets/9/event"}, "data": {"type": "event", "id": "9"}}, "ticket-tags": {"links": {"self": "/v1/tickets/9/relationships/ticket-tags", "related": "/v1/tickets/9/ticket-tags"}}, "discount-codes": {"links": {"self": "/v1/tickets/9/relationships/discount-codes", "related": "/v1/tickets/9/discount-codes"}}, "attendees": {"links": {"self": "/v1/tickets/9/relationships/attendees", "related": "/v1/attendees?ticket_id=9"}}, "access-codes": {"links": {"self": "/v1/tickets/9/relationships/access-codes", "related": "/v1/tickets/9/access-codes"}}}, "attributes": {"description": "This is a paid ticket", "max-order": 10, "min-order": 1, "price": 100.0, "is-checkin-restricted": true, "name": "Paid Ticket", "is-fee-absorbed": true, "sales-starts-at": "2019-11-10T07:28:38.126000+00:00", "position": 1, "deleted-at": null, "sales-ends-at": "2019-11-18T18:30:00+00:00", "quantity": 100, "auto-checkin-enabled": false, "is-hidden": false, "is-description-visible": true, "max-price": 0.0, "min-price": 1.0, "type": "paid"}, "id": "9", "links": {"self": "/v1/tickets/9"}}], "included": [{"type": "event", "id": "9", "links": {"self": "/v1/events/9"}}], "links": {"self": "/v1/events/9/tickets?include=event&fields%5Bevent%5D=id&page%5Bsize%5D=0"}, "meta": {"count": 2}, "jsonapi": {"version": "1.0"}}
```

@iamareebjamal Inputs please, what shall be done as the response is correct
https://github.com/fossasia/open-event-server/issues/6597#issuecomment-554674573
@iamareebjamal This is an issue in frontend -
What I did is for my event on dev named Eventyay Testing, I created another ticket named as Paid Ticket testing.

1. I choose Paid ticket in ticketing options
2. In price value I write `free` instead of price integer value
3. Publish the changes.

Frontend should not allow the price non-integer value

Results : This create a Paid  type ticket in backend

![desktip](https://user-images.githubusercontent.com/20026440/69012839-2a75c500-09a0-11ea-8272-b575825d09c8.png)

The frontend has 0 responsibility to allow or disallow anything. Everything is server's responsibility

It's a good thing frontend didn't prevent this, or this bug in server could never have been discovered
Okay, got this will send a PR. 

Resolving patch:
diff --git a/app/api/schema/tickets.py b/app/api/schema/tickets.py
--- a/app/api/schema/tickets.py
+++ b/app/api/schema/tickets.py
@@ -67,6 +67,12 @@ def validate_quantity(self, data):
                 raise UnprocessableEntity({'pointer': '/data/attributes/quantity'},
                                           "quantity should be greater than or equal to max-order")
 
+    @validates_schema
+    def validate_price(self, data):
+        if data['type'] == 'paid' and ('price' not in data or data['price'] <= 0):
+            raise UnprocessableEntity({'pointer': 'data/attributes/price'},
+                                      "paid ticket price should be greater than 0")
+
     @validates_schema(pass_original=True)
     def validate_discount_code(self, data, original_data):
         if 'relationships' in original_data and 'discount-codes' in original_data['data']['relationships']:


Test patch: