<commit_before># -*- coding: UTF-8 -*-
import datetime
import os
import os.path
from collections import defaultdict

from django.conf import settings as dsettings
from django.db import models
from django.db.models import Q
from django.db.models.query import QuerySet

from conference.models import Ticket, ConferenceTaggedItem, AttendeeProfile
from taggit.managers import TaggableManager

class SpeakerConference(models.Model):
    speaker = models.OneToOneField('conference.Speaker', related_name='p3_speaker')
    first_time = models.BooleanField(default=False)

TICKET_CONFERENCE_SHIRT_SIZES = (
    ('fs', 'S (female)'),
    ('fm', 'M (female)'),
    ('fl', 'L (female)'),
    ('fxl', 'XL (female)'),
    ('fxxl', 'XXL (female)'),
    ('s', 'S (male)'),
    ('m', 'M (male)'),
    ('l', 'L (male)'),
    ('xl', 'XL (male)'),
    ('xxl', 'XXL (male)'),
)
TICKET_CONFERENCE_DIETS = (
    ('omnivorous', 'Omnivorous'),
    ('vegetarian', 'Vegetarian'),
    #('vegan', 'Vegan'),
    #('kosher', 'Kosher'),
)
TICKET_CONFERENCE_EXPERIENCES = (
    (0, '0'),
    (1, '1'),
    (2, '2'),
    (3, '3'),
    (4, '4'),
    (5, '5'),
)
class TicketConferenceManager(models.Manager):
    def get_query_set(self):
        return self._QuerySet(self.model)

    def __getattr__(self, name):
        return getattr(self.all(), name)

    class _QuerySet(QuerySet):
        def available(self, user, conference=None):
            """
            restituisce il qs con i biglietti disponibili per l'utente;
            disponibili significa comprati dall'utente o assegnati a lui.
            """
            # TODO: drop in favore di dataaccess.user_tickets
            q1 = user.ticket_set.all()
            if conference:
                q1 = q1.conference(conference)

            q2 = Ticket.objects.filter(p3_conference__assigned_to=user.email)
            if conference:
                q2 = q2.filter(fare__conference=conference)

            return q1 | q2

class TicketConference(models.Model):
    ticket = models.OneToOneField(Ticket, related_name='p3_conference')
    shirt_size = models.CharField(max_length=4, choices=TICKET_CONFERENCE_SHIRT_SIZES, default='l')
    python_experience = models.PositiveIntegerField(choices=TICKET_CONFERENCE_EXPERIENCES, default=0)
    diet = models.CharField(max_length=10, choices=TICKET_CONFERENCE_DIETS, default='omnivorous')
    tagline = models.CharField(max_length=60, blank=True, help_text='a (funny?) tagline that will be displayed on the badge<br />Eg. CEO of FooBar Inc.; Student at MIT; Super Python fanboy')
    days = models.TextField(verbose_name='Days of attendance', blank=True)
    assigned_to = models.EmailField(blank=True)

    objects = TicketConferenceManager()

    def profile(self):
        if self.assigned_to:
            return AttendeeProfile.objects.get(user__email=self.assigned_to)
        else:
            return AttendeeProfile.objects.get(user=self.ticket.user)

def _ticket_sim_upload_to(instance, filename):
    subdir = 'p3/personal_documents'
    # inserisco anche l'id del biglietto nel nome del file perché un utente può
    # acquistare più sim e probabilmente non sono tutte per lui.
    fname = '%s-%s' % (instance.ticket.user.username, instance.ticket.id)
    fdir = os.path.join(dsettings.SECURE_MEDIA_ROOT, subdir)
    for f in os.listdir(fdir):
        if os.path.splitext(f)[0] == fname:
            os.unlink(os.path.join(fdir, f))
            break
    return os.path.join(subdir, fname + os.path.splitext(filename)[1].lower())

TICKET_SIM_TYPE = (
    ('std', 'Standard SIM (USIM)'),
    ('micro', 'Micro SIM'),
)
TICKET_SIM_PLAN_TYPE = (
    ('std', 'Standard Plan'),
    ('bb', 'BlackBerry Plan'),
)
class TicketSIM(models.Model):
    ticket = models.OneToOneField(Ticket, related_name='p3_conference_sim')
    document = models.FileField(
        verbose_name='ID Document',
        upload_to=_ticket_sim_upload_to,
        storage=dsettings.SECURE_STORAGE,
        blank=True,
        help_text='Italian regulations require a document ID to activate a phone SIM. You can use the same ID for up to three SIMs. Any document is fine (EU driving license, personal ID card, etc).',
    )
    sim_type = models.CharField(
        max_length=5,
        choices=TICKET_SIM_TYPE,
        default='std',
        help_text='Select the SIM physical format. USIM is the sandard for most mobile phones; Micro SIM is notably used on iPad and iPhone 4.',
    )
    plan_type = models.CharField(
        max_length=3,
        choices=TICKET_SIM_PLAN_TYPE,
        default='std',
        help_text='Standard plan is fine for all mobiles except BlackBerry that require a special plan (even though rates and features are exactly the same).',
    )

HOTELROOM_ROOM_TYPE = (
    ('t1', 'Single room'),
    ('t2', 'Double room'),
    ('t3', 'Triple room'),
    ('t4', 'Quadruple room'),
)
class HotelRoom(models.Model):
    conference = models.ForeignKey('conference.Conference')
    room_type = models.CharField(max_length=2, choices=HOTELROOM_ROOM_TYPE)
    quantity = models.PositiveIntegerField()
    amount = models.CharField(max_length=50, help_text='''
        Costo della camera per notte.
        <ul>
            <li>10x1,8x2,7x3 significa: 10 € per una notte, 8 a notte per due notti, 7 a notte per 3 notti.</li>
            <li>10 significa: 10 € a notte</li>
            <li>7,12x1,8x2 significa: 12 € per una notte, 8 a notte per due notti, 7 a notte per tutti gli altri periodi</li>
        </ul>
    ''')

    class Meta:
        unique_together = (('conference', 'room_type'),)

    def clean(self):
        try:
            self._calc_rules()
        except (TypeError, ValueError):
            from django.core.exceptions import ValidationError
            raise ValidationError('Invalid "amount" value')

    def _calc_rules(self):
        rules = {}
        if self.amount:
            for rule in self.amount.split(','):
                if 'x' in rule:
                    amount, days = rule.split('x')
                    amount = float(amount)
                    days = int(days)
                else:
                    amount = float(rule)
                    days = None
                rules[days] = amount
        return rules

    def price(self, days):
        """
        costo del singolo posto letto per `days` giorni
        """
        if days <= 0 or not self.amount:
            return 0
        rules = self._calc_rules()
        try:
            price = rules[days]
        except KeyError:
            price = rules.get(None, 0)
        return days * price

    def beds(self):
        """
        numero di posti letto in camera
        """
        return int(self.room_type[1])

class TicketRoomManager(models.Manager):
    def valid_tickets(self):
        # prima di tutto individuo i biglietti validi; sono quelli il cui
        # ordine è confermato o, nel caso di ordini con bonifico bancario, sono
        # avvenuti di "recente"...
        incomplete_limit = datetime.date.today() - datetime.timedelta(days=5)
        return TicketRoom.objects\
            .filter(ticket__fare__conference=dsettings.CONFERENCE_CONFERENCE)\
            .filter(
                Q(ticket__orderitem__order___complete=True)
                | Q(ticket__orderitem__order__method='bank', ticket__orderitem__order__created__gte=incomplete_limit)
            )
<commit_msg>aumentato l'hard limit per considerare i bonifici ancora validi a 15g<commit_after># -*- coding: UTF-8 -*-
import datetime
import os
import os.path
from collections import defaultdict

from django.conf import settings as dsettings
from django.db import models
from django.db.models import Q
from django.db.models.query import QuerySet

from conference.models import Ticket, ConferenceTaggedItem, AttendeeProfile
from taggit.managers import TaggableManager

class SpeakerConference(models.Model):
    speaker = models.OneToOneField('conference.Speaker', related_name='p3_speaker')
    first_time = models.BooleanField(default=False)

TICKET_CONFERENCE_SHIRT_SIZES = (
    ('fs', 'S (female)'),
    ('fm', 'M (female)'),
    ('fl', 'L (female)'),
    ('fxl', 'XL (female)'),
    ('fxxl', 'XXL (female)'),
    ('s', 'S (male)'),
    ('m', 'M (male)'),
    ('l', 'L (male)'),
    ('xl', 'XL (male)'),
    ('xxl', 'XXL (male)'),
)
TICKET_CONFERENCE_DIETS = (
    ('omnivorous', 'Omnivorous'),
    ('vegetarian', 'Vegetarian'),
    #('vegan', 'Vegan'),
    #('kosher', 'Kosher'),
)
TICKET_CONFERENCE_EXPERIENCES = (
    (0, '0'),
    (1, '1'),
    (2, '2'),
    (3, '3'),
    (4, '4'),
    (5, '5'),
)
class TicketConferenceManager(models.Manager):
    def get_query_set(self):
        return self._QuerySet(self.model)

    def __getattr__(self, name):
        return getattr(self.all(), name)

    class _QuerySet(QuerySet):
        def available(self, user, conference=None):
            """
            restituisce il qs con i biglietti disponibili per l'utente;
            disponibili significa comprati dall'utente o assegnati a lui.
            """
            # TODO: drop in favore di dataaccess.user_tickets
            q1 = user.ticket_set.all()
            if conference:
                q1 = q1.conference(conference)

            q2 = Ticket.objects.filter(p3_conference__assigned_to=user.email)
            if conference:
                q2 = q2.filter(fare__conference=conference)

            return q1 | q2

class TicketConference(models.Model):
    ticket = models.OneToOneField(Ticket, related_name='p3_conference')
    shirt_size = models.CharField(max_length=4, choices=TICKET_CONFERENCE_SHIRT_SIZES, default='l')
    python_experience = models.PositiveIntegerField(choices=TICKET_CONFERENCE_EXPERIENCES, default=0)
    diet = models.CharField(max_length=10, choices=TICKET_CONFERENCE_DIETS, default='omnivorous')
    tagline = models.CharField(max_length=60, blank=True, help_text='a (funny?) tagline that will be displayed on the badge<br />Eg. CEO of FooBar Inc.; Student at MIT; Super Python fanboy')
    days = models.TextField(verbose_name='Days of attendance', blank=True)
    assigned_to = models.EmailField(blank=True)

    objects = TicketConferenceManager()

    def profile(self):
        if self.assigned_to:
            return AttendeeProfile.objects.get(user__email=self.assigned_to)
        else:
            return AttendeeProfile.objects.get(user=self.ticket.user)

def _ticket_sim_upload_to(instance, filename):
    subdir = 'p3/personal_documents'
    # inserisco anche l'id del biglietto nel nome del file perché un utente può
    # acquistare più sim e probabilmente non sono tutte per lui.
    fname = '%s-%s' % (instance.ticket.user.username, instance.ticket.id)
    fdir = os.path.join(dsettings.SECURE_MEDIA_ROOT, subdir)
    for f in os.listdir(fdir):
        if os.path.splitext(f)[0] == fname:
            os.unlink(os.path.join(fdir, f))
            break
    return os.path.join(subdir, fname + os.path.splitext(filename)[1].lower())

TICKET_SIM_TYPE = (
    ('std', 'Standard SIM (USIM)'),
    ('micro', 'Micro SIM'),
)
TICKET_SIM_PLAN_TYPE = (
    ('std', 'Standard Plan'),
    ('bb', 'BlackBerry Plan'),
)
class TicketSIM(models.Model):
    ticket = models.OneToOneField(Ticket, related_name='p3_conference_sim')
    document = models.FileField(
        verbose_name='ID Document',
        upload_to=_ticket_sim_upload_to,
        storage=dsettings.SECURE_STORAGE,
        blank=True,
        help_text='Italian regulations require a document ID to activate a phone SIM. You can use the same ID for up to three SIMs. Any document is fine (EU driving license, personal ID card, etc).',
    )
    sim_type = models.CharField(
        max_length=5,
        choices=TICKET_SIM_TYPE,
        default='std',
        help_text='Select the SIM physical format. USIM is the sandard for most mobile phones; Micro SIM is notably used on iPad and iPhone 4.',
    )
    plan_type = models.CharField(
        max_length=3,
        choices=TICKET_SIM_PLAN_TYPE,
        default='std',
        help_text='Standard plan is fine for all mobiles except BlackBerry that require a special plan (even though rates and features are exactly the same).',
    )

HOTELROOM_ROOM_TYPE = (
    ('t1', 'Single room'),
    ('t2', 'Double room'),
    ('t3', 'Triple room'),
    ('t4', 'Quadruple room'),
)
class HotelRoom(models.Model):
    conference = models.ForeignKey('conference.Conference')
    room_type = models.CharField(max_length=2, choices=HOTELROOM_ROOM_TYPE)
    quantity = models.PositiveIntegerField()
    amount = models.CharField(max_length=50, help_text='''
        Costo della camera per notte.
        <ul>
            <li>10x1,8x2,7x3 significa: 10 € per una notte, 8 a notte per due notti, 7 a notte per 3 notti.</li>
            <li>10 significa: 10 € a notte</li>
            <li>7,12x1,8x2 significa: 12 € per una notte, 8 a notte per due notti, 7 a notte per tutti gli altri periodi</li>
        </ul>
    ''')

    class Meta:
        unique_together = (('conference', 'room_type'),)

    def clean(self):
        try:
            self._calc_rules()
        except (TypeError, ValueError):
            from django.core.exceptions import ValidationError
            raise ValidationError('Invalid "amount" value')

    def _calc_rules(self):
        rules = {}
        if self.amount:
            for rule in self.amount.split(','):
                if 'x' in rule:
                    amount, days = rule.split('x')
                    amount = float(amount)
                    days = int(days)
                else:
                    amount = float(rule)
                    days = None
                rules[days] = amount
        return rules

    def price(self, days):
        """
        costo del singolo posto letto per `days` giorni
        """
        if days <= 0 or not self.amount:
            return 0
        rules = self._calc_rules()
        try:
            price = rules[days]
        except KeyError:
            price = rules.get(None, 0)
        return days * price

    def beds(self):
        """
        numero di posti letto in camera
        """
        return int(self.room_type[1])

class TicketRoomManager(models.Manager):
    def valid_tickets(self):
        # prima di tutto individuo i biglietti validi; sono quelli il cui
        # ordine è confermato o, nel caso di ordini con bonifico bancario, sono
        # avvenuti di "recente"...
        incomplete_limit = datetime.date.today() - datetime.timedelta(days=15)
        return TicketRoom.objects\
            .filter(ticket__fare__conference=dsettings.CONFERENCE_CONFERENCE)\
            .filter(
                Q(ticket__orderitem__order___complete=True)
                | Q(ticket__orderitem__order__method='bank', ticket__orderitem__order__created__gte=incomplete_limit)
            )

{'fraction_non_alphanumeric': 0.11443055086177763, 'fraction_numerical': 0.010341331530922608, 'mean_word_length': 2.729770607511974, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, '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': '2092939', 'n_tokens_mistral': 4845, 'n_tokens_neox': 4661, 'n_words': 1188}