<commit_before>from datetime import timedelta
from decimal import Decimal
from unittest import mock
import uuid

import pytest
from pytest import mark, raises, approx

from django.urls import reverse
from django.conf import settings
from django.contrib.messages import constants as messages_constants
from django.test import override_settings
from django.utils import timezone

from assopy.models import Order, ORDER_TYPE
from conference.cart import CartActions, ORDER_CONFIRMATION_EMAIL_SUBJECT
from conference.models import Ticket, Fare, FARE_TICKET_TYPES, StripePayment
from conference.fares import (
    set_early_bird_fare_dates,
    set_regular_fare_dates,
    set_other_fares_dates,
    SOCIAL_EVENT_FARE_CODE,
    SIM_CARD_FARE_CODE,
    ALL_POSSIBLE_FARE_CODES,
)
from p3.models import TicketConference
from tests.common_tools import (
    redirects_to,
    template_used,
    get_default_conference,
    setup_conference_with_typical_fares,
    contains_message,
    email_sent_with_subject,
    create_valid_ticket_for_user_and_fare,
)
from tests.factories import CouponFactory, CountryFactory, OrderFactory, VatFactory, FareFactory


@mark.parametrize(
    "url",
    [
        reverse("cart:step1_choose_type"),
        reverse("cart:step2_pick_tickets", args=["other"]),
        reverse("cart:step3_add_billing_info", args=["ABCDEFGH"]),
        reverse("cart:step4_payment", args=["ABCDEFGH"]),
    ],
)
def test_cart_requires_full_profile_data(db, user_client, url):
    user = user_client.user
    attendee_profile = user.attendeeprofile
    attendee_profile.gender = ""
    attendee_profile.save()
    attendee_profile.refresh_from_db()

    response = user_client.get(url)
    assert response.status_code == 302
    assert response.url == reverse("user_panel:profile_settings")


def test_first_step_of_cart_is_available_without_auth(db, client):
    url = reverse("cart:step1_choose_type")
    response = client.get(url)
    assert response.status_code == 200
    assert template_used(
        response, "conference/cart/step_1_choose_type_of_order.html"
    )


def test_first_step_has_links_to_second_step(db, client):
    url = reverse("cart:step1_choose_type")
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])
    second_step_personal = reverse(
        "cart:step2_pick_tickets", args=["personal"]
    )
    # XXX Disabled for EP2020
    #second_step_student = reverse("cart:step2_pick_tickets", args=["student"])

    response = client.get(url)

    assert second_step_company in response.content.decode()
    assert second_step_personal in response.content.decode()
    #assert second_step_student in response.content.decode()


def test_other_fares_button_not_shown_when_other_fares_invalid(db, client):
    url = reverse("cart:step1_choose_type")
    second_step_other = reverse("cart:step2_pick_tickets", args=["other"])

    assert not Fare.objects.exclude(ticket_type=FARE_TICKET_TYPES.conference).exists()

    response = client.get(url)
    assert second_step_other not in response.content.decode()


def test_other_fares_button_shown_when_other_fares_valid(db, client):
    conference, _ = setup_conference_with_typical_fares()
    set_other_fares_dates(
        conference=conference,
        start_date=timezone.now().date(),
        end_date=timezone.now().date() + timedelta(days=7),
    )

    url = reverse("cart:step1_choose_type")
    second_step_other = reverse("cart:step2_pick_tickets", args=["other"])

    assert Fare.objects.exclude(ticket_type=FARE_TICKET_TYPES.conference).exists()

    response = client.get(url)
    assert second_step_other in response.content.decode()


def test_cart_second_step_requires_auth(db, client):
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = client.get(second_step_company)

    assert response.status_code == 302
    assert redirects_to(response, reverse('accounts:login'))


def test_second_step_doesnt_work_with_unkown_ticket_type(db, user_client):
    second_step_unkown = reverse("cart:step2_pick_tickets", args=["unkown"])

    with raises(AssertionError):
        user_client.get(second_step_unkown)


def test_cant_see_any_tickets_if_fares_are_not_available(db, user_client):
    setup_conference_with_typical_fares()
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = user_client.get(second_step_company)

    assert "No tickets available" in response.content.decode()


def test_cant_buy_any_tickets_if_fares_are_not_available(db, user_client):
    setup_conference_with_typical_fares()
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = user_client.post(
        second_step_company, {"TESP": 10, CartActions.buy_tickets: True},
        follow=True,
    )

    # Following the response to check if the message is correctly showed
    messages = list(response.context['messages'])
    assert len(messages) == 1
    assert messages[0].level == messages_constants.ERROR
    assert messages[0].message == "A selected fare is not available"
    assert Order.objects.all().count() == 0


@mark.parametrize(
    "ticket_category, expected_ticket_types",
    [
        ('personal', ['TRSP', 'TRLP', 'TRTP', 'TRCP', 'TRDP', 'TRPP']),
        ('company', ['TRSC', 'TRLC', 'TRTC', 'TRCC', 'TRDC', 'TRPC']),
        ('student', ['TRSS', 'TRLS', 'TRTS', 'TRCS', 'TRDS', 'TRPS']),
        ('other', ['SIM1', 'VOUPE03']),
    ],
)
def test_cart_only_shows_correct_ticket_types(db, user_client, ticket_category, expected_ticket_types):
    setup_conference_with_typical_fares()<commit_msg>hotfix for missing stream only fare code<commit_after>from datetime import timedelta
from decimal import Decimal
from unittest import mock
import uuid

import pytest
from pytest import mark, raises, approx

from django.urls import reverse
from django.conf import settings
from django.contrib.messages import constants as messages_constants
from django.test import override_settings
from django.utils import timezone

from assopy.models import Order, ORDER_TYPE
from conference.cart import CartActions, ORDER_CONFIRMATION_EMAIL_SUBJECT
from conference.models import Ticket, Fare, FARE_TICKET_TYPES, StripePayment
from conference.fares import (
    set_early_bird_fare_dates,
    set_regular_fare_dates,
    set_other_fares_dates,
    SOCIAL_EVENT_FARE_CODE,
    SIM_CARD_FARE_CODE,
    ALL_POSSIBLE_FARE_CODES,
)
from p3.models import TicketConference
from tests.common_tools import (
    redirects_to,
    template_used,
    get_default_conference,
    setup_conference_with_typical_fares,
    contains_message,
    email_sent_with_subject,
    create_valid_ticket_for_user_and_fare,
)
from tests.factories import CouponFactory, CountryFactory, OrderFactory, VatFactory, FareFactory


@mark.parametrize(
    "url",
    [
        reverse("cart:step1_choose_type"),
        reverse("cart:step2_pick_tickets", args=["other"]),
        reverse("cart:step3_add_billing_info", args=["ABCDEFGH"]),
        reverse("cart:step4_payment", args=["ABCDEFGH"]),
    ],
)
def test_cart_requires_full_profile_data(db, user_client, url):
    user = user_client.user
    attendee_profile = user.attendeeprofile
    attendee_profile.gender = ""
    attendee_profile.save()
    attendee_profile.refresh_from_db()

    response = user_client.get(url)
    assert response.status_code == 302
    assert response.url == reverse("user_panel:profile_settings")


def test_first_step_of_cart_is_available_without_auth(db, client):
    url = reverse("cart:step1_choose_type")
    response = client.get(url)
    assert response.status_code == 200
    assert template_used(
        response, "conference/cart/step_1_choose_type_of_order.html"
    )


def test_first_step_has_links_to_second_step(db, client):
    url = reverse("cart:step1_choose_type")
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])
    second_step_personal = reverse(
        "cart:step2_pick_tickets", args=["personal"]
    )
    # XXX Disabled for EP2020
    #second_step_student = reverse("cart:step2_pick_tickets", args=["student"])

    response = client.get(url)

    assert second_step_company in response.content.decode()
    assert second_step_personal in response.content.decode()
    #assert second_step_student in response.content.decode()


def test_other_fares_button_not_shown_when_other_fares_invalid(db, client):
    url = reverse("cart:step1_choose_type")
    second_step_other = reverse("cart:step2_pick_tickets", args=["other"])

    assert not Fare.objects.exclude(ticket_type=FARE_TICKET_TYPES.conference).exists()

    response = client.get(url)
    assert second_step_other not in response.content.decode()


def test_other_fares_button_shown_when_other_fares_valid(db, client):
    conference, _ = setup_conference_with_typical_fares()
    set_other_fares_dates(
        conference=conference,
        start_date=timezone.now().date(),
        end_date=timezone.now().date() + timedelta(days=7),
    )

    url = reverse("cart:step1_choose_type")
    second_step_other = reverse("cart:step2_pick_tickets", args=["other"])

    assert Fare.objects.exclude(ticket_type=FARE_TICKET_TYPES.conference).exists()

    response = client.get(url)
    assert second_step_other in response.content.decode()


def test_cart_second_step_requires_auth(db, client):
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = client.get(second_step_company)

    assert response.status_code == 302
    assert redirects_to(response, reverse('accounts:login'))


def test_second_step_doesnt_work_with_unkown_ticket_type(db, user_client):
    second_step_unkown = reverse("cart:step2_pick_tickets", args=["unkown"])

    with raises(AssertionError):
        user_client.get(second_step_unkown)


def test_cant_see_any_tickets_if_fares_are_not_available(db, user_client):
    setup_conference_with_typical_fares()
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = user_client.get(second_step_company)

    assert "No tickets available" in response.content.decode()


def test_cant_buy_any_tickets_if_fares_are_not_available(db, user_client):
    setup_conference_with_typical_fares()
    second_step_company = reverse("cart:step2_pick_tickets", args=["company"])

    response = user_client.post(
        second_step_company, {"TESP": 10, CartActions.buy_tickets: True},
        follow=True,
    )

    # Following the response to check if the message is correctly showed
    messages = list(response.context['messages'])
    assert len(messages) == 1
    assert messages[0].level == messages_constants.ERROR
    assert messages[0].message == "A selected fare is not available"
    assert Order.objects.all().count() == 0


@mark.parametrize(
    "ticket_category, expected_ticket_types",
    [
        ('personal', ['TRSP', 'TRLP', 'TRTP', 'TRCP', 'TRDP', 'TRPP', 'TRVP']),
        ('company', ['TRSC', 'TRLC', 'TRTC', 'TRCC', 'TRDC', 'TRPC', 'TRVC']),
        ('student', ['TRSS', 'TRLS', 'TRTS', 'TRCS', 'TRDS', 'TRPS', 'TRVS']),
        ('other', ['SIM1', 'VOUPE03']),
    ],
)
def test_cart_only_shows_correct_ticket_types(db, user_client, ticket_category, expected_ticket_types):
    setup_conference_with_typical_fares()
{'fraction_non_alphanumeric': 0.10382610232393744, 'fraction_numerical': 0.007422461783158081, 'mean_word_length': 5.157780195865071, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4468521', 'n_tokens_mistral': 3782, 'n_tokens_neox': 3663, 'n_words': 656}