<commit_before>from __future__ import absolute_import, unicode_literals

from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import signals, Q
from django.template.defaultfilters import slugify
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _, ugettext

from feincms import settings as feincms_settings
from feincms import translations
from feincms.management.checker import check_database_schema
from feincms.models import Base
from feincms.module.mixins import ContentModelMixin
from feincms.utils.managers import ActiveAwareContentManagerMixin
from feincms.utils.queryset_transform import TransformManager

@python_2_unicode_compatible
class Category(models.Model, translations.TranslatedObjectMixin):
    """
    Category is language-aware and connected to the Entry model via
    a many to many relationship.
    """

    ordering = models.SmallIntegerField(_('ordering'), default=0)

    objects = translations.TranslatedObjectManager()

    class Meta:
        verbose_name = _('category')
        verbose_name_plural = _('categories')
        ordering = ['ordering']

    def __str__(self):
        try:
            translation = self.translation
        except models.ObjectDoesNotExist:
            return ugettext('Unnamed category')

        if translation:
            return '%s' % translation

        return ugettext('Unnamed category')

@python_2_unicode_compatible
class CategoryTranslation(translations.Translation(Category)):
    title = models.CharField(_('category title'), max_length=100)
    slug = models.SlugField(_('slug'), unique=True)
    description = models.CharField(
        _('description'), max_length=250, blank=True)

    class Meta:
        verbose_name = _('category translation')
        verbose_name_plural = _('category translations')
        ordering = ['title']

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('elephantblog_category_detail', kwargs={
            'slug': self.slug,
        })

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)

        super(CategoryTranslation, self).save(*args, **kwargs)

class EntryManager(ActiveAwareContentManagerMixin, TransformManager):
    def featured(self):
        return self.active().filter(is_featured=True)

EntryManager.add_to_active_filters(
    Q(is_active=True),
    key='cleared')

EntryManager.add_to_active_filters(
    lambda queryset: queryset.filter(published_on__lte=timezone.now),
    key='published_on_past')

@python_2_unicode_compatible
class Entry(Base, ContentModelMixin):
    is_active = models.BooleanField(
        _('is active'), default=True, db_index=True)
    is_featured = models.BooleanField(
        _('is featured'), default=False, db_index=True)

    title = models.CharField(_('title'), max_length=100)
    slug = models.SlugField(
        _('slug'), max_length=100,
        unique_for_date='published_on')
    author = models.ForeignKey(
        getattr(settings, 'AUTH_USER_MODEL', 'auth.User'),
        related_name='blogentries',
        limit_choices_to={'is_staff': True}, verbose_name=_('author'))
    published_on = models.DateTimeField(
        _('published on'),
        blank=True, null=True, default=timezone.now, db_index=True,
        help_text=_(
            'Will be filled in automatically when entry gets published.'))
    last_changed = models.DateTimeField(
        _('last change'), auto_now=True, editable=False)

    categories = models.ManyToManyField(
        Category, verbose_name=_('categories'),
        related_name='blogentries', null=True, blank=True)

    objects = EntryManager()

    class Meta:
        get_latest_by = 'published_on'
        ordering = ['-published_on']
        verbose_name = _('entry')
        verbose_name_plural = _('entries')

    def __str__(self):
        return self.title

    def __init__(self, *args, **kwargs):
        super(Entry, self).__init__(*args, **kwargs)
        self._old_is_active = self.is_active

    def save(self, *args, **kwargs):
        if self.is_active and not self.published_on:
            self.published_on = timezone.now()

        super(Entry, self).save(*args, **kwargs)
    save.alters_data = True

    def get_absolute_url(self):
        # We use naive date using UTC for conversion for permalink
        if getattr(settings, 'USE_TZ', False):
            pub_date = timezone.make_naive(self.published_on, timezone.utc)
        else:
            pub_date = self.published_on
        return reverse('elephantblog_entry_detail', kwargs={
            'year': pub_date.strftime('%Y'),
            'month': pub_date.strftime('%m'),
            'day': pub_date.strftime('%d'),
            'slug': self.slug,
        })

    @classmethod
    def register_extension(cls, register_fn):
        from .modeladmins import EntryAdmin
        register_fn(cls, EntryAdmin)

try:
    _do_check = feincms_settings.FEINCMS_CHECK_DATABASE_SCHEMA
except:
    _do_check = True

if _do_check:
    signals.post_syncdb.connect(
        check_database_schema(Entry, __name__),
        weak=False)
<commit_msg>Passing callables to filter() will not be supported in Django 1.9 anymore<commit_after>from __future__ import absolute_import, unicode_literals

from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import signals, Q
from django.template.defaultfilters import slugify
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _, ugettext

from feincms import settings as feincms_settings
from feincms import translations
from feincms.management.checker import check_database_schema
from feincms.models import Base
from feincms.module.mixins import ContentModelMixin
from feincms.utils.managers import ActiveAwareContentManagerMixin
from feincms.utils.queryset_transform import TransformManager

@python_2_unicode_compatible
class Category(models.Model, translations.TranslatedObjectMixin):
    """
    Category is language-aware and connected to the Entry model via
    a many to many relationship.
    """

    ordering = models.SmallIntegerField(_('ordering'), default=0)

    objects = translations.TranslatedObjectManager()

    class Meta:
        verbose_name = _('category')
        verbose_name_plural = _('categories')
        ordering = ['ordering']

    def __str__(self):
        try:
            translation = self.translation
        except models.ObjectDoesNotExist:
            return ugettext('Unnamed category')

        if translation:
            return '%s' % translation

        return ugettext('Unnamed category')

@python_2_unicode_compatible
class CategoryTranslation(translations.Translation(Category)):
    title = models.CharField(_('category title'), max_length=100)
    slug = models.SlugField(_('slug'), unique=True)
    description = models.CharField(
        _('description'), max_length=250, blank=True)

    class Meta:
        verbose_name = _('category translation')
        verbose_name_plural = _('category translations')
        ordering = ['title']

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('elephantblog_category_detail', kwargs={
            'slug': self.slug,
        })

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)

        super(CategoryTranslation, self).save(*args, **kwargs)

class EntryManager(ActiveAwareContentManagerMixin, TransformManager):
    def featured(self):
        return self.active().filter(is_featured=True)

EntryManager.add_to_active_filters(
    Q(is_active=True),
    key='cleared')

EntryManager.add_to_active_filters(
    lambda queryset: queryset.filter(published_on__lte=timezone.now()),
    key='published_on_past')

@python_2_unicode_compatible
class Entry(Base, ContentModelMixin):
    is_active = models.BooleanField(
        _('is active'), default=True, db_index=True)
    is_featured = models.BooleanField(
        _('is featured'), default=False, db_index=True)

    title = models.CharField(_('title'), max_length=100)
    slug = models.SlugField(
        _('slug'), max_length=100,
        unique_for_date='published_on')
    author = models.ForeignKey(
        getattr(settings, 'AUTH_USER_MODEL', 'auth.User'),
        related_name='blogentries',
        limit_choices_to={'is_staff': True}, verbose_name=_('author'))
    published_on = models.DateTimeField(
        _('published on'),
        blank=True, null=True, default=timezone.now, db_index=True,
        help_text=_(
            'Will be filled in automatically when entry gets published.'))
    last_changed = models.DateTimeField(
        _('last change'), auto_now=True, editable=False)

    categories = models.ManyToManyField(
        Category, verbose_name=_('categories'),
        related_name='blogentries', null=True, blank=True)

    objects = EntryManager()

    class Meta:
        get_latest_by = 'published_on'
        ordering = ['-published_on']
        verbose_name = _('entry')
        verbose_name_plural = _('entries')

    def __str__(self):
        return self.title

    def __init__(self, *args, **kwargs):
        super(Entry, self).__init__(*args, **kwargs)
        self._old_is_active = self.is_active

    def save(self, *args, **kwargs):
        if self.is_active and not self.published_on:
            self.published_on = timezone.now()

        super(Entry, self).save(*args, **kwargs)
    save.alters_data = True

    def get_absolute_url(self):
        # We use naive date using UTC for conversion for permalink
        if getattr(settings, 'USE_TZ', False):
            pub_date = timezone.make_naive(self.published_on, timezone.utc)
        else:
            pub_date = self.published_on
        return reverse('elephantblog_entry_detail', kwargs={
            'year': pub_date.strftime('%Y'),
            'month': pub_date.strftime('%m'),
            'day': pub_date.strftime('%d'),
            'slug': self.slug,
        })

    @classmethod
    def register_extension(cls, register_fn):
        from .modeladmins import EntryAdmin
        register_fn(cls, EntryAdmin)

try:
    _do_check = feincms_settings.FEINCMS_CHECK_DATABASE_SCHEMA
except:
    _do_check = True

if _do_check:
    signals.post_syncdb.connect(
        check_database_schema(Entry, __name__),
        weak=False)
<|endoftext|>


<commit_before>import datetime
import calendar
import logging
from collections import OrderedDict

from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext

from cube.diary.models import Showing, Event, DiaryIdea, RotaEntry
import cube.diary.forms

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

def _return_close_window():
    # Really, really dirty way to emulate the original functionality and
    # close the popped up window
    return HttpResponse("<!DOCTYPE html><title>-</title>Ok")

def _get_date_range(year, month, day, user_days_ahead):
    """Support method to take fields read from HTTP request and return a tuple
    (datetime, number_of_days)
    If month or day are blank, they default to 1. If all three are blank it
    defaults to today"""
    if day is not None and month is None:
        raise Http404("Invalid request; cant specify day and no month")

    try:
        year = int(year) if year else None
        month = int(month) if month else None
        day = int(day) if day else None
    except ValueError:
        raise Http404("Invalid values")

    logger.debug("view_diary: day %s, month %s, year %s, span %s days", str(day), str(month), str(year), str(user_days_ahead))

    try:
        if day:
            startdate = datetime.date(year, month, day)
            days_ahead = 1
        elif month:
            startdate = datetime.date(year, month, 1)
            days_ahead = calendar.monthrange(year, month)[1]
        elif year:
            startdate = datetime.date(year, 1, 1)
            days_ahead = 365
            if calendar.isleap(year):
                days_ahead += 1
        else:
            startdate = datetime.date.today()
            days_ahead = 30 # default
    except ValueError:
        raise Http404("Invalid date")

    if user_days_ahead:
        try:
            days_ahead = int(user_days_ahead)
        except (ValueError, TypeError):
            pass

    return startdate, days_ahead

def view_diary(request, year=None, month=None, day=None):
    context = { }
    query_days_ahead = request.GET.get('daysahead', None)
    startdate, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    enddate = startdate + datetime.timedelta(days=days_ahead)

    context['today'] = datetime.date.today()
    context['start'] = startdate
    context['event_list_name'] = "Events for %s" % "/".join( [ str(s) for s in (day, month, year) if s ])
    # Do query. select_related() on the end encourages it to get the
    # associated showing/event data, to reduce the number of SQL queries
    context['showings'] = Showing.objects.filter(confirmed=True).filter(hide_in_programme=False).filter(start__range=[startdate, enddate]).filter(event__private=False).order_by('start').select_related()

    return render_to_response('indexed_showing_list.html', context)

def edit_diary_list(request, year=None, day=None, month=None):
    context = { }
    # Sort out date range to display
    query_days_ahead = request.GET.get('daysahead', None)
    startdate, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    enddate = startdate + datetime.timedelta(days=days_ahead)

    # Get all showings in the date range
    showings = Showing.objects.filter(start__range=[startdate, enddate]).order_by('start').select_related()
    # Build a dict with all the dates in the range as keys and empty lists as values
    dates = OrderedDict([ ((startdate + datetime.timedelta(days=days)), []) for days in xrange(days_ahead) ])
    # Put showings in the dict (so days without showings will have an empty dict)
    for showing in showings:
        dates[showing.start.date()].append(showing)

    # Get all 'ideas' in date range. Fiddle the date range to be from the start
    # of the month in startdate, so the idea for that month gets included:
    idea_startdate = datetime.date(day=1, month=startdate.month, year=startdate.year)
    idea_list = DiaryIdea.objects.filter(month__range=[idea_startdate, enddate]).order_by('month').select_related()
    logging.info(str(idea_list))
    ideas = {}
    # Assemble into dict, with keys that will match the keys in the showings
    # dict
    for idea in idea_list:
        ideas[idea.month] = idea.ideas
    # Fiddle so that the idea for the first month is displayed, even if
    # startdate is after the first day of the month:
    if idea_startdate not in showings and len(idea_list) > 0:
        ideas[startdate] = idea_list[0].ideas

    context['ideas'] = ideas
    context['dates'] = dates
    context['event_list_name'] = "Diary for %s to %s" % (str(startdate), str(enddate))
    context['start'] = startdate
    context['end'] = enddate

    return render_to_response('edit_list.html', context)

def add_showing(request, event_id):
    if request.method != 'POST':
        return HttpResponse('Invalid request!', 405) # 405 = Method not allowed
    copy_from = request.GET.get('copy_from', None)
    try:
        copy_from = int(copy_from, 10)
    except (TypeError, ValueError):
        copy_from = None

    # Create form using submitted data:
    form = cube.diary.forms.NewShowingForm(request.POST)
    if form.is_valid():
        # Submitted data will have basic time & canceled/private info, but need
        # to set the event id and rota information manually, so don't commit
        # the new object immediately:
        new_showing = form.save(commit=False)
        # Set event ID:
        new_showing.event_id = event_id
        # Create showing
        new_showing.save()
        # If a showing_id was supplied, clone the rota from that:
        if copy_from:
            source_showing = Showing.objects.get(pk=copy_from)
            for rota_entry in source_showing.rotaentry_set.all():
                r = RotaEntry(showing=new_showing, template=rota_entry)
                print "role_id:", r.role_id
                r.save()

        return _return_close_window()
    else:
        # If copy_from was supplied, assume being called from "edit showing"
        # form, and return that
        if copy_from:
            showing = get_object_or_404(Showing, pk=copy_from)
            showing_form = cube.diary.forms.ShowingForm(instance=showing)
            context = {
                    'showing' : showing,
                    'form' : showing_form,
                    'new_showing_form' : form,
                    }
            return render_to_response('form_showing.html', RequestContext(request, context))
        else:
            return HttpResponse("Failed adding showing", status=400)

def add_event(request):
    if request.method == 'POST':
        form = cube.diary.forms.NewEventForm(request.POST)
        if form.is_valid():
            print form.cleaned_data
            new_event = Event(name=form.cleaned_data['event_name'],
                              etype=form.cleaned_data['event_type'],
                              duration=form.cleaned_data['duration'],
                              outside_hire=form.cleaned_data['external'],
                              private=form.cleaned_data['private'])
            new_event.save()
            showings = []
            start = form.cleaned_data['start']
            for n in range(0, form.cleaned_data['number_of_days']):
                day_offset = datetime.timedelta(days=n)
                new_showing = Showing(event=new_event,
                                      start=(start + day_offset),
                                      discounted=form.cleaned_data['discounted'],
                                      confirmed=form.cleaned_data['confirmed'],
                                      booked_by=form.cleaned_data['booked_by'],
                                      )
                new_showing.save()
                new_showing.reset_rota_to_default()
                showings.append(new_showing)
            return _return_close_window()
        else:
            context = { 'form' : form }
            return render_to_response('form_new_event_and_showing.html', RequestContext(request, context))
    elif request.method == 'GET':
        # Marshal date out of the GET request:
        date = request.GET.get('date', datetime.date.today().strftime("%d-%m-%Y"))
        date = date.split("-")
        assert(len(date) == 3) # Should probably do this better
        try:
            date[0] = int(date[0], 10)
            date[1] = int(date[1], 10)
            date[2] = int(date[2], 10)
            event_start = datetime.datetime(hour=20, minute=0, day=date[0], month=date[1], year=date[2])
        except (ValueError, TypeError):
            return HttpResponse("Illegal date", status=400)
        # Creat form, render template:
        form = cube.diary.forms.NewEventForm(initial={'start' : event_start})
        context = { 'form' : form }
        return render_to_response('form_new_event_and_showing.html', RequestContext(request, context))
    else:
        return HttpResponse("Illegal method", status=405)

def edit_showing(request, showing_id=None):
    showing = get_object_or_404(Showing, pk=showing_id)

    if request.method == 'POST':
        form = cube.diary.forms.ShowingForm(request.POST, instance=showing)
        if form.is_valid():
            # Because Django can't cope with updating the rota automatically
            # do this two-step commit=False / save thing, then manually wrangle
            # the rota:
            modified_showing = form.save(commit=False)
            modified_showing.save()
            # Now get list of selected roles;
            selected_roles = dict(request.POST)['roles']
            initial_set = { r.values()[0] for r in showing.rotaentry_set.values('role_id')}
            print initial_set
            # For each id, this will get the entry or create it:
            for role_id in selected_roles:
                role_id = int(role_id)
                modified_showing.rotaentry_set.get_or_create(role_id = role_id)
                initial_set.discard(role_id)
            # Now remove any roles that we haven't seen:
            modified_showing.rotaentry_set.filter(role__in = initial_set).delete()

            return _return_close_window()
    else:
        form = cube.diary.forms.ShowingForm(instance=showing)
    # Also create a form for "cloning" the showing (ie. adding another one),
    # but initialise it with values from existing event, but a day later...
    new_showing_template = Showing.objects.get(pk=showing.pk)
    new_showing_template.pk = None
    new_showing_template.start += datetime.timedelta(days=1)
    new_showing_form = cube.diary.forms.NewShowingForm(instance=new_showing_template)

    context = {
            'showing' : showing,
            'form' : form,
            'new_showing_form' : new_showing_form,
            }

    return render_to_response('form_showing.html', RequestContext(request, context))

def edit_event(request, event_id=None):
    event = get_object_or_404(Event, pk=event_id)

    if request.method == 'POST':
        form = cube.diary.forms.EventForm(request.POST, instance=event)
        if form.is_valid():
            form.save()
            return _return_close_window()
    else:
        form = cube.diary.forms.EventForm(instance=event)

    context = {
            'event' : event,
            'form' : form,
            }

    return render_to_response('form_event.html', RequestContext(request, context))

def edit_ideas(request, year=None, month=None):
    context = {}
    year = int(year)
    month = int(month)

    # Use get or create in order to silently create the ideas entry if it
    # didn't already exist:
    instance, created = DiaryIdea.objects.get_or_create(month=datetime.date(year=year, month=month, day=1))
    if request.method == 'POST':
        form = cube.diary.forms.DiaryIdeaForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return _return_close_window()
    else:
        form = cube.diary.forms.DiaryIdeaForm(instance=instance)

    context['form'] = form
    context['month'] = instance.month

    return render_to_response('form_idea.html', RequestContext(request, context))

def view_showing(request, showing_id=None):
    context = {}
    context['showing'] = get_object_or_404(Showing, id=showing_id)
    context['event'] = context['showing'].event
    return render_to_response('showing.html', context)

def view_event(request, event_id=None):
    context = {}
    context['event'] = get_object_or_404(Event, id=event_id)
    context['showings'] = context['event'].showing_set.all()
    return render_to_response('event.html', context)

def delete_showing(request, showing_id):
    if request.method == 'POST':
        showing = Showing.objects.get(pk=showing_id)
        showing.delete()

    return _return_close_window()

def view_rota(request, year, month, day):
    query_days_ahead = request.GET.get('daysahead', None)
    start_date, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    end_date = start_date + datetime.timedelta(days=days_ahead)
    showings = Showing.objects.filter(cancelled=False).filter(confirmed=True).filter(start__range=[start_date, end_date]).order_by('start').select_related()
    context = {
            'showings': showings,
            }
    return render_to_response('rota_view.html', context)

<commit_msg>Don't allow viewing of diary into the past<commit_after>import datetime
import calendar
import logging
from collections import OrderedDict

from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.core.urlresolvers import reverse

from cube.diary.models import Showing, Event, DiaryIdea, RotaEntry
import cube.diary.forms

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

def _return_close_window():
    # Really, really dirty way to emulate the original functionality and
    # close the popped up window
    return HttpResponse("<!DOCTYPE html><title>-</title>Ok")

def _get_date_range(year, month, day, user_days_ahead):
    """Support method to take fields read from HTTP request and return a tuple
    (datetime, number_of_days)
    If month or day are blank, they default to 1. If all three are blank it
    defaults to today"""
    if day is not None and month is None:
        raise Http404("Invalid request; cant specify day and no month")

    try:
        year = int(year) if year else None
        month = int(month) if month else None
        day = int(day) if day else None
    except ValueError:
        raise Http404("Invalid values")

    logger.debug("view_diary: day %s, month %s, year %s, span %s days", str(day), str(month), str(year), str(user_days_ahead))

    try:
        if day:
            startdate = datetime.date(year, month, day)
            days_ahead = 1
        elif month:
            startdate = datetime.date(year, month, 1)
            days_ahead = calendar.monthrange(year, month)[1]
        elif year:
            startdate = datetime.date(year, 1, 1)
            days_ahead = 365
            if calendar.isleap(year):
                days_ahead += 1
        else:
            startdate = datetime.date.today()
            days_ahead = 30 # default
    except ValueError:
        raise Http404("Invalid date")

    if user_days_ahead:
        try:
            days_ahead = int(user_days_ahead)
        except (ValueError, TypeError):
            pass

    return startdate, days_ahead

def view_diary(request, year=None, month=None, day=None):
    context = { }
    query_days_ahead = request.GET.get('daysahead', None)
    startdate, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    enddate = startdate + datetime.timedelta(days=days_ahead)

    context['today'] = datetime.date.today()
    context['start'] = startdate
    context['event_list_name'] = "Events for %s" % "/".join( [ str(s) for s in (day, month, year) if s ])
    # Do query. select_related() on the end encourages it to get the
    # associated showing/event data, to reduce the number of SQL queries
    context['showings'] = Showing.objects.filter(confirmed=True).filter(hide_in_programme=False).filter(start__range=[startdate, enddate]).filter(event__private=False).order_by('start').select_related()

    return render_to_response('indexed_showing_list.html', context)

def edit_diary_list(request, year=None, day=None, month=None):
    context = { }
    # Sort out date range to display
    query_days_ahead = request.GET.get('daysahead', None)
    startdate, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    # Don't allow viewing of dates before today, to avoid editing of the past:
    if startdate < datetime.date.today():
        # Change startdate to today:
        startdate = datetime.date.today()
        # Redirect to the correct page:
        new_url = ("%s?daysahead=%d" %
                    (reverse('day-edit', kwargs={
                               'year' : startdate.year,
                               'month' : startdate.month,
                               'day' : startdate.day}),
                     days_ahead))
        return HttpResponseRedirect(new_url)
    enddate = startdate + datetime.timedelta(days=days_ahead)

    # Get all showings in the date range
    showings = Showing.objects.filter(start__range=[startdate, enddate]).order_by('start').select_related()
    # Build a dict with all the dates in the range as keys and empty lists as values
    dates = OrderedDict([ ((startdate + datetime.timedelta(days=days)), []) for days in xrange(days_ahead) ])
    # Put showings in the dict (so days without showings will have an empty dict)
    for showing in showings:
        dates[showing.start.date()].append(showing)

    # Get all 'ideas' in date range. Fiddle the date range to be from the start
    # of the month in startdate, so the idea for that month gets included:
    idea_startdate = datetime.date(day=1, month=startdate.month, year=startdate.year)
    idea_list = DiaryIdea.objects.filter(month__range=[idea_startdate, enddate]).order_by('month').select_related()
    logging.info(str(idea_list))
    ideas = {}
    # Assemble into dict, with keys that will match the keys in the showings
    # dict
    for idea in idea_list:
        ideas[idea.month] = idea.ideas
    # Fiddle so that the idea for the first month is displayed, even if
    # startdate is after the first day of the month:
    if idea_startdate not in showings and len(idea_list) > 0:
        ideas[startdate] = idea_list[0].ideas

    context['ideas'] = ideas
    context['dates'] = dates
    context['event_list_name'] = "Diary for %s to %s" % (str(startdate), str(enddate))
    context['start'] = startdate
    context['end'] = enddate

    return render_to_response('edit_list.html', context)

def add_showing(request, event_id):
    if request.method != 'POST':
        return HttpResponse('Invalid request!', 405) # 405 = Method not allowed
    copy_from = request.GET.get('copy_from', None)
    try:
        copy_from = int(copy_from, 10)
    except (TypeError, ValueError):
        copy_from = None

    # Create form using submitted data:
    form = cube.diary.forms.NewShowingForm(request.POST)
    if form.is_valid():
        # Submitted data will have basic time & canceled/private info, but need
        # to set the event id and rota information manually, so don't commit
        # the new object immediately:
        new_showing = form.save(commit=False)
        # Set event ID:
        new_showing.event_id = event_id
        # Create showing
        new_showing.save()
        # If a showing_id was supplied, clone the rota from that:
        if copy_from:
            source_showing = Showing.objects.get(pk=copy_from)
            for rota_entry in source_showing.rotaentry_set.all():
                r = RotaEntry(showing=new_showing, template=rota_entry)
                print "role_id:", r.role_id
                r.save()

        return _return_close_window()
    else:
        # If copy_from was supplied, assume being called from "edit showing"
        # form, and return that
        if copy_from:
            showing = get_object_or_404(Showing, pk=copy_from)
            showing_form = cube.diary.forms.ShowingForm(instance=showing)
            context = {
                    'showing' : showing,
                    'form' : showing_form,
                    'new_showing_form' : form,
                    }
            return render_to_response('form_showing.html', RequestContext(request, context))
        else:
            return HttpResponse("Failed adding showing", status=400)

def add_event(request):
    if request.method == 'POST':
        form = cube.diary.forms.NewEventForm(request.POST)
        if form.is_valid():
            print form.cleaned_data
            new_event = Event(name=form.cleaned_data['event_name'],
                              etype=form.cleaned_data['event_type'],
                              duration=form.cleaned_data['duration'],
                              outside_hire=form.cleaned_data['external'],
                              private=form.cleaned_data['private'])
            new_event.save()
            showings = []
            start = form.cleaned_data['start']
            for n in range(0, form.cleaned_data['number_of_days']):
                day_offset = datetime.timedelta(days=n)
                new_showing = Showing(event=new_event,
                                      start=(start + day_offset),
                                      discounted=form.cleaned_data['discounted'],
                                      confirmed=form.cleaned_data['confirmed'],
                                      booked_by=form.cleaned_data['booked_by'],
                                      )
                new_showing.save()
                new_showing.reset_rota_to_default()
                showings.append(new_showing)
            return _return_close_window()
        else:
            context = { 'form' : form }
            return render_to_response('form_new_event_and_showing.html', RequestContext(request, context))
    elif request.method == 'GET':
        # Marshal date out of the GET request:
        date = request.GET.get('date', datetime.date.today().strftime("%d-%m-%Y"))
        date = date.split("-")
        assert(len(date) == 3) # Should probably do this better
        try:
            date[0] = int(date[0], 10)
            date[1] = int(date[1], 10)
            date[2] = int(date[2], 10)
            event_start = datetime.datetime(hour=20, minute=0, day=date[0], month=date[1], year=date[2])
        except (ValueError, TypeError):
            return HttpResponse("Illegal date", status=400)
        # Creat form, render template:
        form = cube.diary.forms.NewEventForm(initial={'start' : event_start})
        context = { 'form' : form }
        return render_to_response('form_new_event_and_showing.html', RequestContext(request, context))
    else:
        return HttpResponse("Illegal method", status=405)

def edit_showing(request, showing_id=None):
    showing = get_object_or_404(Showing, pk=showing_id)

    if request.method == 'POST':
        form = cube.diary.forms.ShowingForm(request.POST, instance=showing)
        if form.is_valid():
            # Because Django can't cope with updating the rota automatically
            # do this two-step commit=False / save thing, then manually wrangle
            # the rota:
            modified_showing = form.save(commit=False)
            modified_showing.save()
            # Now get list of selected roles;
            selected_roles = dict(request.POST)['roles']
            initial_set = { r.values()[0] for r in showing.rotaentry_set.values('role_id')}
            print initial_set
            # For each id, this will get the entry or create it:
            for role_id in selected_roles:
                role_id = int(role_id)
                modified_showing.rotaentry_set.get_or_create(role_id = role_id)
                initial_set.discard(role_id)
            # Now remove any roles that we haven't seen:
            modified_showing.rotaentry_set.filter(role__in = initial_set).delete()

            return _return_close_window()
    else:
        form = cube.diary.forms.ShowingForm(instance=showing)
    # Also create a form for "cloning" the showing (ie. adding another one),
    # but initialise it with values from existing event, but a day later...
    new_showing_template = Showing.objects.get(pk=showing.pk)
    new_showing_template.pk = None
    new_showing_template.start += datetime.timedelta(days=1)
    new_showing_form = cube.diary.forms.NewShowingForm(instance=new_showing_template)

    context = {
            'showing' : showing,
            'form' : form,
            'new_showing_form' : new_showing_form,
            }

    return render_to_response('form_showing.html', RequestContext(request, context))

def edit_event(request, event_id=None):
    event = get_object_or_404(Event, pk=event_id)

    if request.method == 'POST':
        form = cube.diary.forms.EventForm(request.POST, instance=event)
        if form.is_valid():
            form.save()
            return _return_close_window()
    else:
        form = cube.diary.forms.EventForm(instance=event)

    context = {
            'event' : event,
            'form' : form,
            }

    return render_to_response('form_event.html', RequestContext(request, context))

def edit_ideas(request, year=None, month=None):
    context = {}
    year = int(year)
    month = int(month)

    # Use get or create in order to silently create the ideas entry if it
    # didn't already exist:
    instance, created = DiaryIdea.objects.get_or_create(month=datetime.date(year=year, month=month, day=1))
    if request.method == 'POST':
        form = cube.diary.forms.DiaryIdeaForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return _return_close_window()
    else:
        form = cube.diary.forms.DiaryIdeaForm(instance=instance)

    context['form'] = form
    context['month'] = instance.month

    return render_to_response('form_idea.html', RequestContext(request, context))

def view_showing(request, showing_id=None):
    context = {}
    context['showing'] = get_object_or_404(Showing, id=showing_id)
    context['event'] = context['showing'].event
    return render_to_response('showing.html', context)

def view_event(request, event_id=None):
    context = {}
    context['event'] = get_object_or_404(Event, id=event_id)
    context['showings'] = context['event'].showing_set.all()
    return render_to_response('event.html', context)

def delete_showing(request, showing_id):
    if request.method == 'POST':
        showing = Showing.objects.get(pk=showing_id)
        showing.delete()

    return _return_close_window()

def view_rota(request, year, month, day):
    query_days_ahead = request.GET.get('daysahead', None)
    start_date, days_ahead = _get_date_range(year, month, day, query_days_ahead)
    end_date = start_date + datetime.timedelta(days=days_ahead)
    showings = Showing.objects.filter(cancelled=False).filter(confirmed=True).filter(start__range=[start_date, end_date]).order_by('start').select_related()
    context = {
            'showings': showings,
            }
    return render_to_response('rota_view.html', context)

<|endoftext|>


<commit_before>__author__ = 'bkeroack'

import shutil
import os
import os.path
import sys
from sh import service
import logging
from clint.textui import progress, puts, indent, colored

def get_root_dir():
    return os.path.abspath(os.path.dirname(__file__))

def cp_file_checkperms(src, dest):
    logging.debug("copying {} to {}".format(src, dest))
    try:
        shutil.copyfile(src, dest)
    except IOError:
        puts(colored.red("IO error (Insufficient permissions?)"))
        sys.exit(1)

def mk_etc_dir_posix():
    if not os.path.isdir('/etc/elita'):
        try:
            os.mkdir('/etc/elita')
        except IOError:
            puts(colored.red("IO error (Insufficient permissions?)"))
            sys.exit(1)

def cp_prod_ini_posix():
    ini_location = os.path.join(get_root_dir(), "util/elita.ini")
    cp_file_checkperms(ini_location, '/etc/elita/elita.ini')

def do_step(msg, func, params=[]):
    puts(msg + " ... ", newline=False)
    func(*params)
    puts(colored.green("DONE"))

def InstallUbuntu():

    puts("OS Flavor: Ubuntu")

    do_step("Making /etc/elita", mk_etc_dir_posix)

    do_step("Copying ini", cp_prod_ini_posix)

    upstart_location = os.path.join(get_root_dir(), "util", "upstart-elita.conf")

    do_step("Creating service (upstart)", cp_file_checkperms, [upstart_location, '/etc/init/elita.conf'])

    puts("Starting service...")
    service("start", "elita")

    puts(colored.green("Done!"))

def InstallLinux():
    return InstallUbuntu()<commit_msg>fix service start<commit_after>__author__ = 'bkeroack'

import shutil
import os
import os.path
import sys
from sh import service
import logging
from clint.textui import progress, puts, indent, colored

def get_root_dir():
    return os.path.abspath(os.path.dirname(__file__))

def cp_file_checkperms(src, dest):
    logging.debug("copying {} to {}".format(src, dest))
    try:
        shutil.copyfile(src, dest)
    except IOError:
        puts(colored.red("IO error (Insufficient permissions?)"))
        sys.exit(1)

def mk_etc_dir_posix():
    if not os.path.isdir('/etc/elita'):
        try:
            os.mkdir('/etc/elita')
        except IOError:
            puts(colored.red("IO error (Insufficient permissions?)"))
            sys.exit(1)

def cp_prod_ini_posix():
    ini_location = os.path.join(get_root_dir(), "util/elita.ini")
    cp_file_checkperms(ini_location, '/etc/elita/elita.ini')

def do_step(msg, func, params=[]):
    puts(msg + " ... ", newline=False)
    func(*params)
    puts(colored.green("DONE"))

def InstallUbuntu():

    puts("OS Flavor: Ubuntu")

    do_step("Making /etc/elita", mk_etc_dir_posix)

    do_step("Copying ini", cp_prod_ini_posix)

    upstart_location = os.path.join(get_root_dir(), "util", "upstart-elita.conf")

    do_step("Creating service (upstart)", cp_file_checkperms, [upstart_location, '/etc/init/elita.conf'])

    puts("Starting service...")
    service("elita", "start")

    puts(colored.green("Done!"))

def InstallLinux():
    return InstallUbuntu()<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
#   dp for Tornado
#      YoungYong Park (youngyongpark@gmail.com)
#      2014.11.04
#

from __future__ import absolute_import
from engine.helper import Helper as dpHelper

import re

class NumericHelper(dpHelper):
    def extract_numbers(self, string):
        if self.helper.system.py_version <= 2:
            types = basestring,
        else:
            types = str,

        if not isinstance(string, types):
            return None

        return re.sub(r'\D+', '', string)

    def number_format(self, value, tsep=',', dsep='.'):
        value = self.extract_numbers(value)

        if not value:
            return '0'

        s = str(value)
        cnt = 0
        numchars = dsep + '0123456789'
        ls = len(s)
        while cnt < ls and s[cnt] not in numchars:
            cnt += 1

        lhs = s[:cnt]
        s = s[cnt:]
        if not dsep:
            cnt = -1
        else:
            cnt = s.rfind(dsep)
        if cnt > 0:
            rhs = dsep + s[cnt+1:]
            s = s[:cnt]
        else:
            rhs = ''

        splt = ''
        while s != '':
            splt = s[-3:] + tsep + splt
            s = s[:-3]

        return lhs + splt[:-1] + rhs

    def int(self, a):
        if self.helper.system.py_version <= 2:
            return int(a)
        else:
            return int(a)

    def long(self, a):
        if self.helper.system.py_version <= 2:
            return long(a)
        else:
            return int(a)<commit_msg>Add convert method, decimal numeric to alphabetical numeric.<commit_after># -*- coding: utf-8 -*-
#
#   dp for Tornado
#      YoungYong Park (youngyongpark@gmail.com)
#      2014.11.04
#

from __future__ import absolute_import
from engine.helper import Helper as dpHelper

import re

class NumericHelper(dpHelper):
    def extract_numbers(self, string):
        if self.helper.system.py_version <= 2:
            types = basestring,
        else:
            types = str,

        if not isinstance(string, types):
            return None

        return re.sub(r'\D+', '', string)

    def number_format(self, value, tsep=',', dsep='.'):
        value = self.extract_numbers(value)

        if not value:
            return '0'

        s = str(value)
        cnt = 0
        numchars = dsep + '0123456789'
        ls = len(s)
        while cnt < ls and s[cnt] not in numchars:
            cnt += 1

        lhs = s[:cnt]
        s = s[cnt:]
        if not dsep:
            cnt = -1
        else:
            cnt = s.rfind(dsep)
        if cnt > 0:
            rhs = dsep + s[cnt+1:]
            s = s[:cnt]
        else:
            rhs = ''

        splt = ''
        while s != '':
            splt = s[-3:] + tsep + splt
            s = s[:-3]

        return lhs + splt[:-1] + rhs

    def int(self, a):
        if self.helper.system.py_version <= 2:
            return int(a)
        else:
            return int(a)

    def long(self, a):
        if self.helper.system.py_version <= 2:
            return long(a)
        else:
            return int(a)

    @property
    def xxx(self):
        return 'ABtQR5JxfghijN_qrb4KSy9-Uuvw6ZVcLnpMFGkeTPd3WXYEHCDma78sz12'

    def to_xxx(self, x):
        __ = self.xxx
        _ = ''

        while (True):
            if x <= 0:
                break

            k = x % len(__)
            _ = '%s%s' % (__[k:k+1], _)
            x = self.long(x / len(__))

        return _

    def from_xxx(self, x):
        __ = self.xxx
        _ = 0
        c = 0

        for i in reversed(str(x)):
            i = __.find(i)
            _ += i * (len(__) ** c)
            c += 1

        return _<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json
import logging

import requests
from lxml import html

from db.player import Player

logger = logging.getLogger(__name__)

JSON_SUMMARY_URL_TEMPLATE = (
    "http://statsapi.web.nhl.com/api/v1/game/%s/feed/live")

def add_nhl_ids_to_content(url, content):
    """
    Adds player ids used by nhl.com to each roster player on event summary
    to allow for a unique identification later on.
    """

    season = int(os.path.dirname(url).split("/")[-1][:4])
    game_id = os.path.basename(url).split(".")[0][2:]

    # setting up fully qualified game id to be used in boxscore url
    full_game_id = "%d%s" % (season, game_id)
    # retrieving json summary from  NHL stats API
    summary = retrieve_summary(full_game_id)

    # if json boxscore is valid, use it to retrieve nhl player ids from it
    if summary and 'liveData' in summary.keys():
        road_players, home_players = retrieve_player_ids_from_summary(summary)
    # sometimes json summaries are missing
    # alternative is to retrieve nhl player ids from the database itself
    # prerequisite: players have to be in database already and must be
    # uniquely identifiable by name, prename and position
    else:
        logger.warn(
            "Trying to retrieve nhl ids from database for " +
            "game %s" % full_game_id)
        road_players, home_players = retrieve_player_ids_from_database(content)

    # finally adding retrieved player ids to recently downloaded game rosters
    doc = html.document_fromstring(content)
    # retrieving all table cells that contain a player's number
    rtds = get_table_cells(doc, 25, 'preceding')
    htds = get_table_cells(doc, 25, 'following')
    # rtds = doc.xpath(
    #     "//tr/td[@colspan='25']/parent::*/preceding-sibling::*/td" +
    #     "[@align='center' and @class='lborder + bborder + rborder']")
    # htds = doc.xpath(
    #     "//tr/td[@colspan='25']/parent::*/following-sibling::*/td" +
    #     "[@align='center' and @class='lborder + bborder + rborder']")

    logger.debug(
        "Number of road/home players found: %d/%d" % (len(rtds), len(htds)))

    if not rtds or not htds:
        logger.debug(
            "Couldn't retrieve team rosters by standard" +
            "method, trying alternative method")
        rtds = get_table_cells(doc, 22, 'preceding')
        htds = get_table_cells(doc, 22, 'following')

        # rtds = doc.xpath("//tr/td[@colspan='22']/parent::*/preceding-sibl
        # ing::*/td[@align='center' and @class='lborder + bborder + rborder']")
        # htds = doc.xpath("//tr/td[@colspan='22']/parent::*/following-sibl
        # ing::*/td[@align='center' and @class='lborder + bborder + rborder']")
        logger.debug(
            "Number of road/home players found via" +
            "alternative: %d/%d" % (len(rtds), len(htds)))

    # TODO: re-analyze what is done here
    for a in [rtds, htds]:
        if len(a) > 20:
            seen_numbers = list()
            tds_to_remove = list()
            for td in reversed(a):
                no = int(td.xpath("text()").pop())
                if no in seen_numbers:
                    logger.debug(
                        "Will remove table cell element from retrieved" +
                        "player numbers (game id: %s, raw_data: %s)" % (
                            full_game_id,
                            ", ".join(
                                td.xpath("following-sibling::td/text()"))))
                    tds_to_remove.append(td)
                    continue
                seen_numbers.append(no)
            else:
                [a.remove(tdr) for tdr in tds_to_remove]

def get_table_cells(doc, colspan, sibling_type):
    """
    Get table cells from specified parsed html document using the given colspan
    value and sibling type.
    """
    return doc.xpath(
        "//tr/td[@colspan='%d']/parent::*/%s-sib" % (colspan, sibling_type) +
        "ling::*/td[@align='center' and @class='lborder + bborder + rborder']")

def retrieve_player_ids_from_database(content):
    """
    Retrieves NHL player ids for all players listed in event summary from
    database.
    """
    # parsing raw HTML data into structured format
    game_report = html.document_fromstring(content)

    # retrieving player numbers and names from the game report raw data
    away_nos = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/preceding-sibling::*/td" +
        "[@align='center' and @class='lborder + bborder + rborder']")
    home_nos = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/following-sibling::*/td" +
        "[@align='center' and @class='lborder + bborder + rborder']")
    away_names = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/preceding-sibling::*/td" +
        "[@class='bborder + rborder']")
    home_names = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/following-sibling::*/td" +
        "[@class='bborder + rborder']")

    road_players = convert_names_numbers_to_players(away_names, away_nos)
    home_players = convert_names_numbers_to_players(home_names, home_nos)

    return road_players, home_players

def retrieve_player_ids_from_summary(summary):
    """
    Retrieves NHL player ids for all dressed players from JSON summary data
    provided by NHL stats API.
    """
    # setting up dictionary object to contain separate dictionaries with
    # jersey numbers as keys and player ids as values from
    player_nos_by_team = dict()

    for home_away_type in ['home', 'away']:
        players_for_team = summary[
            'liveData']['boxscore']['teams'][home_away_type]
        # retrieving all player ids (skaters and goalies) first
        all_player_ids = set(
            players_for_team['skaters'] + players_for_team['goalies'])
        # retrieving ids of scratched players
        scratches_ids = set(players_for_team['scratches'])
        # deriving ids of all players dressed for current game
        dressed_ids = list(all_player_ids.difference(scratches_ids))

        team_player_no_dict = dict()

        # iterating over all collected player ids
        for nhl_id in dressed_ids:
            try:
                # retrieving jersey number of current player in current game
                no = int(
                    summary[
                        'liveData']['boxscore']['teams'][home_away_type][
                            'players']["ID%d" % nhl_id]["jerseyNumber"])
                # checking whether jersey number has already been used
                # (this shouldn't happen)
                if no in team_player_no_dict:
                    plr_already_inserted = Player.find_by_id(
                        team_player_no_dict[no])
                    plr_to_be_inserted = Player.find_by_id(nhl_id)
                    logger.warn(
                        "Jersey number %d used multiple times? " +
                        "(%s vs. %s)" % (
                            no, plr_already_inserted, plr_to_be_inserted))
                team_player_no_dict[no] = nhl_id
            except KeyError:
                logger.warn(
                    "JSON key 'jerseyNumber' not found for player with " +
                    "nhl_id %d." % nhl_id)
        else:
            player_nos_by_team[home_away_type] = team_player_no_dict

    return player_nos_by_team['away'], player_nos_by_team['home']

def retrieve_summary(full_game_id):
    """
    Retrieves JSON summary from NHL stats API using the specified game id.
    """
    try:
        url = JSON_SUMMARY_URL_TEMPLATE % full_game_id
        req = requests.get(url, params={'site': 'en_nhl'})
        logger.info(
            "Retrieving player nhl ids for game %s from %s" % (
                full_game_id, req.url))
        summary = json.loads(req.text)
    except:
        logger.warn(
            "Couldn't retrieve player nhl ids for game %s" % full_game_id)
        summary = None

    return summary

def convert_names_numbers_to_players(names, numbers):
    """
    Converting names and numbers retrieved from event summary to NHL player
    ids by searching database.
    """
    # extracting number, position, name and prename from event summary
    players = dict()
    for i in range(0, len(names), 2):
        # retrieving position
        position = names[i].xpath("text()")[0]

        # team penalties are listed in event summary
        # but only in the last line, i.e. it's safe to break from the
        # process here
        if position.upper() == 'TEAM PENALTY':
            break

        # retrieving name and prename (split by ',')
        last_name, first_name = names[i + 1].xpath("text()")[0].split(", ")
        # retrieving corresponding number from other list
        number = int(numbers.pop(0).xpath("text()")[0])

        # retrieving nhl id from database
        nhl_id = retrieve_nhl_id(last_name, first_name, position)

        players[number] = nhl_id

    return players

def retrieve_nhl_id(last_name, first_name, position):

    plr = Player.find_by_name(first_name, last_name)

    if plr is None:
        plr = Player.find_by_name_position(first_name, last_name, position)

    if plr is None:
        plr = Player.find_by_name_extended(first_name, last_name)

    if plr is None:
        logger.error(
            "Player not found in database: " +
            "%s %s (%s)" % (first_name, last_name, position))
        return 0
    else:
        return plr.nhl_id
<commit_msg>Finalize player id injection in downloaded team roster summaries<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json
import logging

import requests
from lxml import html, etree

from db.player import Player

logger = logging.getLogger(__name__)

JSON_SUMMARY_URL_TEMPLATE = (
    "http://statsapi.web.nhl.com/api/v1/game/%s/feed/live")

def add_nhl_ids_to_content(url, content):
    """
    Adds player ids used by nhl.com to each roster player on event summary
    to allow for a unique identification later on.
    """

    season = int(os.path.dirname(url).split("/")[-1][:4])
    game_id = os.path.basename(url).split(".")[0][2:]

    # setting up fully qualified game id to be used in boxscore url
    full_game_id = "%d%s" % (season, game_id)
    # retrieving json summary from  NHL stats API
    summary = retrieve_summary(full_game_id)

    # if json boxscore is valid, use it to retrieve nhl player ids from it
    if summary and 'liveData' in summary.keys():
        road_players, home_players = retrieve_player_ids_from_summary(summary)
    # sometimes json summaries are missing
    # alternative is to retrieve nhl player ids from the database itself
    # prerequisite: players have to be in database already and must be
    # uniquely identifiable by name, prename and position
    else:
        logger.warn(
            "Trying to retrieve nhl ids from database for " +
            "game %s" % full_game_id)
        road_players, home_players = retrieve_player_ids_from_database(content)

    # finally adding retrieved player ids to recently downloaded game rosters
    doc = html.document_fromstring(content)

    # retrieving all table cells that contain a player's number
    rtds = get_table_cells(doc, 'preceding')
    htds = get_table_cells(doc, 'following')
    # inserting player id in span element behind player's numbers
    insert_nhl_ids(rtds, road_players)
    insert_nhl_ids(htds, home_players)

    return etree.tostring(
        doc, method='html', pretty_print=True, encoding='unicode')

def insert_nhl_ids(tds, players):
    """
    Insert nhl ids for each player into the according team's html roster
    representation.
    """
    # season = self.season
    # using each table cell
    for td in tds:
        # retrieving jersey number from table cell
        no = int(td.text_content())
        # retrieving nhl player id from player dictionary
        try:
            nhl_id = players[no]
        except KeyError:
            pos, name = td.xpath("following-sibling::*//text()")[:2]
            last_name, first_name = [x.strip() for x in name.split(",")]
            plr = Player.find_by_name_position(first_name, last_name, pos)
            nhl_id = plr.player_id
            # TODO: find and create player if not found in database
        # creating a span element with the attribute 'nhl_id'
        span = etree.Element("span", nhl_id=str(nhl_id))
        # inserting newly created span element into the document tree
        td.insert(0, span)

def get_table_cells(doc, sibling_type):
    """
    Get table cells from specified parsed html document using the given colspan
    value and sibling type.
    """
    tds = doc.xpath(
        "//tr/td[@colspan='22' or @colspan='25']/parent::*/" +
        "%s-sibling::*/td[@align='center' and @class='lborder" % sibling_type +
        " + bborder + rborder']")

    distinct_table_cells = {int(td.xpath("text()").pop()): td for td in tds}

    return list(distinct_table_cells.values())

def retrieve_player_ids_from_database(content):
    """
    Retrieves NHL player ids for all players listed in event summary from
    database.
    """
    # parsing raw HTML data into structured format
    game_report = html.document_fromstring(content)

    # retrieving player numbers and names from the game report raw data
    # TODO: check xpath expressions for general validity
    away_nos = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/preceding-sibling::*/td" +
        "[@align='center' and @class='lborder + bborder + rborder']")
    home_nos = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/following-sibling::*/td" +
        "[@align='center' and @class='lborder + bborder + rborder']")
    away_names = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/preceding-sibling::*/td" +
        "[@class='bborder + rborder']")
    home_names = game_report.xpath(
        "//tr/td[@colspan='25']/parent::*/following-sibling::*/td" +
        "[@class='bborder + rborder']")

    road_players = convert_names_numbers_to_players(away_names, away_nos)
    home_players = convert_names_numbers_to_players(home_names, home_nos)

    return road_players, home_players

def retrieve_player_ids_from_summary(summary):
    """
    Retrieves NHL player ids for all dressed players from JSON summary data
    provided by NHL stats API.
    """
    # setting up dictionary object to contain separate dictionaries with
    # jersey numbers as keys and player ids as values from
    player_nos_by_team = dict()

    for home_away_type in ['home', 'away']:
        players_for_team = summary[
            'liveData']['boxscore']['teams'][home_away_type]
        # retrieving all player ids (skaters and goalies) first
        all_player_ids = set(
            players_for_team['skaters'] + players_for_team['goalies'])
        # retrieving ids of scratched players
        scratches_ids = set(players_for_team['scratches'])
        # deriving ids of all players dressed for current game
        dressed_ids = list(all_player_ids.difference(scratches_ids))

        team_player_no_dict = dict()

        # iterating over all collected player ids
        for nhl_id in dressed_ids:
            try:
                # retrieving jersey number of current player in current game
                no = int(
                    summary[
                        'liveData']['boxscore']['teams'][home_away_type][
                            'players']["ID%d" % nhl_id]["jerseyNumber"])
                # checking whether jersey number has already been used
                # (this shouldn't happen)
                if no in team_player_no_dict:
                    plr_already_inserted = Player.find_by_id(
                        team_player_no_dict[no])
                    plr_to_be_inserted = Player.find_by_id(nhl_id)
                    logger.warn(
                        "Jersey number %d used multiple times? " +
                        "(%s vs. %s)" % (
                            no, plr_already_inserted, plr_to_be_inserted))
                team_player_no_dict[no] = nhl_id
            except KeyError:
                logger.warn(
                    "JSON key 'jerseyNumber' not found for player with " +
                    "nhl_id %d." % nhl_id)
        else:
            player_nos_by_team[home_away_type] = team_player_no_dict

    return player_nos_by_team['away'], player_nos_by_team['home']

def retrieve_summary(full_game_id):
    """
    Retrieves JSON summary from NHL stats API using the specified game id.
    """
    try:
        url = JSON_SUMMARY_URL_TEMPLATE % full_game_id
        req = requests.get(url, params={'site': 'en_nhl'})
        logger.info(
            "Retrieving player nhl ids for game %s from %s" % (
                full_game_id, req.url))
        summary = json.loads(req.text)
    except:
        logger.warn(
            "Couldn't retrieve player nhl ids for game %s" % full_game_id)
        summary = None

    return summary

def convert_names_numbers_to_players(names, numbers):
    """
    Converting names and numbers retrieved from event summary to NHL player
    ids by searching database.
    """
    # extracting number, position, name and prename from event summary
    players = dict()
    for i in range(0, len(names), 2):
        # retrieving position
        position = names[i].xpath("text()")[0]

        # team penalties are listed in event summary
        # but only in the last line, i.e. it's safe to break from the
        # process here
        if position.upper() == 'TEAM PENALTY':
            break

        # retrieving name and prename (split by ',')
        last_name, first_name = names[i + 1].xpath("text()")[0].split(", ")
        # retrieving corresponding number from other list
        number = int(numbers.pop(0).xpath("text()")[0])

        # retrieving nhl id from database
        nhl_id = retrieve_nhl_id(last_name, first_name, position)

        players[number] = nhl_id

    return players

def retrieve_nhl_id(last_name, first_name, position):

    plr = Player.find_by_name(first_name, last_name)

    if plr is None:
        plr = Player.find_by_name_position(first_name, last_name, position)

    if plr is None:
        plr = Player.find_by_name_extended(first_name, last_name)

    if plr is None:
        logger.error(
            "Player not found in database: " +
            "%s %s (%s)" % (first_name, last_name, position))
        return 0
    else:
        return plr.nhl_id
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright 2017 KMEE
#   Luis Felipe Mileo <mileo@kmee.com.br>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields
from odoo.exceptions import ValidationError
from odoo.exceptions import Warning as UserError
from odoo.addons.financial.tests.financial_test_classes import \
    FinancialTestCase

class ManualFinancialProcess(FinancialTestCase):
    """ Story: Manual Financial Process

        As a Financial User
        I want to registry a manual payable
        So that I can get our cash flow"""

    def setUp(self):
        super(ManualFinancialProcess, self).setUp()

        self.resource_calendar = self.env['resource.calendar']
        self.resource_leaves = self.env['resource.calendar.leaves']

        self.nacional_calendar_id = self.resource_calendar.create({
            'name': 'National Calendar',
        })
        self.new_year_01 = self.resource_leaves.create({
            'name': 'New Year',
            'date_from': fields.Datetime.from_string('2017-01-01 00:00:00'),
            'date_to': fields.Datetime.from_string('2017-01-01 23:59:59'),
            'calendar_id': self.nacional_calendar_id.id,
        })

        self.financial_model = self.env['financial.move']

        self.partner_agrolait = self.env.ref("base.res_partner_2")
        self.partner_axelor = self.env.ref("base.res_partner_2")
        self.currency_chf_id = self.env.ref("base.CHF").id
        self.currency_usd_id = self.env.ref("base.USD").id
        self.currency_eur_id = self.env.ref("base.EUR").id
        self.main_company = self.env.ref('base.main_company').id
        self.env.ref('base.main_company').write(
            {'currency_id': self.currency_eur_id}
        )
        self.env.ref('base.main_company').cron_update_reference_date_today()
        self.bank_112358 = self.env.ref('financial.bank_112358_13')

        self.DOCUMENTO_FINANCEIRO_TED = self.env.ref(
            "financial.DOCUMENTO_FINANCEIRO_TED").id
        self.DOCUMENTO_FINANCEIRO_BOLETO = self.env.ref(
            "financial.DOCUMENTO_FINANCEIRO_BOLETO").id
        self.account_payable = self.env.ref(
            "financial.financial_account_201008")

    def test_financial_payable_create(self):
        """Scenario 1: Financial payable of 100.00

        Given a financial payable
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne maturity date is 2017-01-01
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the User confirm the financial

        Then the financial should have the state open
        And the amount residual should be 100
        And the financial should not be reconciled
        And the business maturity date should be 2017-01-02"""

        financial_move = self.create_financial(
            type='2pay',
            amount_document=100,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref("financial.financial_account_201008").id,
            document_number='100/1',
        )

        financial_move.action_confirm()

        self.assertEqual(financial_move.state, 'open')
        self.assertAlmostEquals(
            financial_move.amount_residual, 100.00)
        self.assertFalse(financial_move.reconciled)
        # FIXME: The resource.leaves don't have a pratical method to call know
        # The next business date!
        # self.assertEqual(financial_move.date_business_maturity,
        #  '2017-01-02')

    def test_financial_payable_full_pay_one(self):
        """Scenario 2: Financial payable of 100.00

        Given a financial payable already confirmed of 100.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create one receipt item related to this payable
        and the receipt item amount is 100.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 100.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=100,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='100/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [100]
        final_state = 'paid'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 0.00)
        self.assertTrue(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_full_pay_multi(self):
        """Scenario 3: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create five receipt item related to this payable
        and each receipt item amount is 1000.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 5000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [1000, 1000, 1000, 1000, 1000]
        final_state = 'paid'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 0.00)
        self.assertTrue(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_partial_pay_one(self):
        """Scenario 4: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 5000.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create one receipt item related to this payable
        and receipt item amount is 4000.00

        Then the financial payable should be paid
        And the amount residual should be 1000
        And the financial should be not reconciled
        And the final balance of the bank account should be increase 4000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [4000]
        final_state = 'open'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 1000.00)
        self.assertFalse(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_partial_pay_multi(self):
        """Scenario 5: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create five receipt item related to this payable
        and each receipt item amount is 1000.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 5000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [1000, 1000, 1000, 1000]
        final_state = 'open'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 1000.00)
        self.assertFalse(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_cancel(self):
        """Scenario 6: Cancel a Financial Move

        Given a financial payable already confirmed of 5000.00
        And the amount document of 5000.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        Then the financial payable should be cancel
        And the user must provide a reason why this financial will be cancel
        And after that verify if the state of the financial changed to 'cancel'
        And the Amount Residual change to 0.00 by
        Amount Document - Amount Cancel = 0.00 in this scenario
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()
        cancel_reason_01 = \
            self.env['financial.move.motivo.cancelamento'].create(
                {'motivo_cancelamento': 'Motivo 01 para o cancelamento'}
            )
        wizard_cancel = self.env['financial.cancel'].with_context(
            active_id=financial_move.id,
            active_model=financial_move._model._name
        ).create(
            {
                'motivo_cancelamento_id': cancel_reason_01.id,
                'obs': 'Observações para o cancelamento',
            }
        )
        wizard_cancel.doit()
        self.assertEqual(financial_move.state, 'cancelled')
        self.assertEqual(financial_move.amount_residual, 0)

    def test_invalid_financial_payable(self):
        """Scenario 7: Invalid financial payable with document_amount = 0"""
        with self.assertRaises(ValidationError):
            self.create_financial(
                type='2pay',
                amount_document=0.0,
                currency_id=self.currency_eur_id,
                date_document='2017-01-01',
                date_maturity='2017-01-01',
                account_id=self.env.ref(
                    "financial.financial_account_101001").id,
                document_number='200/1',
            )

    def test_do_before_unlink(self):
        """Scenario 8: do not possible unlink payable state not draft or
        cancelled  """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        with self.assertRaises(UserError):
            financial_move.unlink()
<commit_msg>[MIG] Acesso a atributo do modelo<commit_after># -*- coding: utf-8 -*-
# Copyright 2017 KMEE
#   Luis Felipe Mileo <mileo@kmee.com.br>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields
from odoo.exceptions import ValidationError
from odoo.exceptions import Warning as UserError
from odoo.addons.financial.tests.financial_test_classes import \
    FinancialTestCase

class ManualFinancialProcess(FinancialTestCase):
    """ Story: Manual Financial Process

        As a Financial User
        I want to registry a manual payable
        So that I can get our cash flow"""

    def setUp(self):
        super(ManualFinancialProcess, self).setUp()

        self.resource_calendar = self.env['resource.calendar']
        self.resource_leaves = self.env['resource.calendar.leaves']

        self.nacional_calendar_id = self.resource_calendar.create({
            'name': 'National Calendar',
        })
        self.new_year_01 = self.resource_leaves.create({
            'name': 'New Year',
            'date_from': fields.Datetime.from_string('2017-01-01 00:00:00'),
            'date_to': fields.Datetime.from_string('2017-01-01 23:59:59'),
            'calendar_id': self.nacional_calendar_id.id,
        })

        self.financial_model = self.env['financial.move']

        self.partner_agrolait = self.env.ref("base.res_partner_2")
        self.partner_axelor = self.env.ref("base.res_partner_2")
        self.currency_chf_id = self.env.ref("base.CHF").id
        self.currency_usd_id = self.env.ref("base.USD").id
        self.currency_eur_id = self.env.ref("base.EUR").id
        self.main_company = self.env.ref('base.main_company').id
        self.env.ref('base.main_company').write(
            {'currency_id': self.currency_eur_id}
        )
        self.env.ref('base.main_company').cron_update_reference_date_today()
        self.bank_112358 = self.env.ref('financial.bank_112358_13')

        self.DOCUMENTO_FINANCEIRO_TED = self.env.ref(
            "financial.DOCUMENTO_FINANCEIRO_TED").id
        self.DOCUMENTO_FINANCEIRO_BOLETO = self.env.ref(
            "financial.DOCUMENTO_FINANCEIRO_BOLETO").id
        self.account_payable = self.env.ref(
            "financial.financial_account_201008")

    def test_financial_payable_create(self):
        """Scenario 1: Financial payable of 100.00

        Given a financial payable
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne maturity date is 2017-01-01
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the User confirm the financial

        Then the financial should have the state open
        And the amount residual should be 100
        And the financial should not be reconciled
        And the business maturity date should be 2017-01-02"""

        financial_move = self.create_financial(
            type='2pay',
            amount_document=100,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref("financial.financial_account_201008").id,
            document_number='100/1',
        )

        financial_move.action_confirm()

        self.assertEqual(financial_move.state, 'open')
        self.assertAlmostEquals(
            financial_move.amount_residual, 100.00)
        self.assertFalse(financial_move.reconciled)
        # FIXME: The resource.leaves don't have a pratical method to call know
        # The next business date!
        # self.assertEqual(financial_move.date_business_maturity,
        #  '2017-01-02')

    def test_financial_payable_full_pay_one(self):
        """Scenario 2: Financial payable of 100.00

        Given a financial payable already confirmed of 100.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create one receipt item related to this payable
        and the receipt item amount is 100.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 100.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=100,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='100/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [100]
        final_state = 'paid'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 0.00)
        self.assertTrue(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_full_pay_multi(self):
        """Scenario 3: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create five receipt item related to this payable
        and each receipt item amount is 1000.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 5000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [1000, 1000, 1000, 1000, 1000]
        final_state = 'paid'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 0.00)
        self.assertTrue(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_partial_pay_one(self):
        """Scenario 4: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 5000.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create one receipt item related to this payable
        and receipt item amount is 4000.00

        Then the financial payable should be paid
        And the amount residual should be 1000
        And the financial should be not reconciled
        And the final balance of the bank account should be increase 4000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [4000]
        final_state = 'open'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 1000.00)
        self.assertFalse(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_partial_pay_multi(self):
        """Scenario 5: Financial payable of 5000.00

        Given a financial payable already confirmed of 5000.00
        And the amount document of 100.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        When the user create five receipt item related to this payable
        and each receipt item amount is 1000.00

        Then the financial payable should be paid
        And the amount residual should be 0
        And the financial should be reconciled
        And the final balance of the bank account should be increase 5000.00
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        amount_credit_debit = [1000, 1000, 1000, 1000]
        final_state = 'open'
        # TODO: Verificar se o saldo da conta bancária foi modificado

        bank_account_id = self.bank_112358.id
        bank_initial_balance = 0.00

        for debt in amount_credit_debit:
            self.create_manual_debt(
                financial_move,
                bank_account_id,
                debt
            )

        self.assertEqual(financial_move.state, final_state)
        self.assertAlmostEquals(
            financial_move.amount_residual, 1000.00)
        self.assertFalse(financial_move.reconciled)

        self.check_bank_account_balance(
            bank_account_id, bank_initial_balance,
            sum(amount_credit_debit))

    def test_financial_payable_cancel(self):
        """Scenario 6: Cancel a Financial Move

        Given a financial payable already confirmed of 5000.00
        And the amount document of 5000.00
        And the date of the document is 2017-01-01
        And tne business maturity date is 2017-01-02
        And the financial account is 'Receitas com Vendas'
        And the Document number is 1000/1

        Then the financial payable should be cancel
        And the user must provide a reason why this financial will be cancel
        And after that verify if the state of the financial changed to 'cancel'
        And the Amount Residual change to 0.00 by
        Amount Document - Amount Cancel = 0.00 in this scenario
        """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()
        cancel_reason_01 = \
            self.env['financial.move.motivo.cancelamento'].create(
                {'motivo_cancelamento': 'Motivo 01 para o cancelamento'}
            )
        wizard_cancel = self.env['financial.cancel'].with_context(
            active_id=financial_move.id,
            active_model=financial_move._name
        ).create(
            {
                'motivo_cancelamento_id': cancel_reason_01.id,
                'obs': 'Observações para o cancelamento',
            }
        )
        wizard_cancel.doit()
        self.assertEqual(financial_move.state, 'cancelled')
        self.assertEqual(financial_move.amount_residual, 0)

    def test_invalid_financial_payable(self):
        """Scenario 7: Invalid financial payable with document_amount = 0"""
        with self.assertRaises(ValidationError):
            self.create_financial(
                type='2pay',
                amount_document=0.0,
                currency_id=self.currency_eur_id,
                date_document='2017-01-01',
                date_maturity='2017-01-01',
                account_id=self.env.ref(
                    "financial.financial_account_101001").id,
                document_number='200/1',
            )

    def test_do_before_unlink(self):
        """Scenario 8: do not possible unlink payable state not draft or
        cancelled  """
        financial_move = self.create_financial(
            type='2pay',
            amount_document=5000,
            currency_id=self.currency_eur_id,
            date_document='2017-01-01',
            date_maturity='2017-01-01',
            account_id=self.env.ref(
                "financial.financial_account_101001").id,
            document_number='200/1',
        )
        financial_move.action_confirm()

        with self.assertRaises(UserError):
            financial_move.unlink()
<|endoftext|>


<commit_before>def avg(a,b,c,d,e):
    return (a+b+c+d+e)/2

def range0(a):
    if a <0.0 or a>10.0:
        print a, "is out of range"

def output(avg1,avg12):
    out="""
The average is {}.
The interger part of the average is {}.
The interger part is {}.
""".format(avg1,avgfirst)
    return out

def main():
    print "This  program will ask you for 5 integer or float values."
    print "It will calculate the average of all valus from 0 inclusive to 10 exclusive."
    print "It will print out whether the resulting average is even or odd."

    n0= float(raw_input("n0:"))
    range00= range0(n0)
    n1= float(raw_input("n1:"))
    range00= range0(n1)
    n2= float(raw_input("n2:"))
    range00= range0(n2)
    n3= float(raw_input("n3:"))
    range00= range0(n3)
    n4= float(raw_input("n4:"))
    range00= range0(n4)

    avg1= avg(n0,n1,n2,n3,n4)
    avg12= int(avg1)

    out= output(avg1,avg12)
    print out

main()

<commit_msg>NOT DONE<commit_after>def avg(a,b,c,d,e):
    return ((a+b+c+d+e)/5)

def range0(a):
    if a <0.0 or a>10.0:
        print a, "is out of range"
        return a==0

def oddeven(b):
    if b ==1 or b ==3 or b ==5 or b==7 or b==9:
        return "odd"
    else:
        return "even"
    print oddeven

def output(avg1,intpart,oddeven1):
    out="""
The average is {}.
The interger part of the average is {}.
The interger part is {}.
""".format(avg1,intpart,oddeven1)
    return out

def main():
    print "This  program will ask you for 5 integer or float values."
    print "It will calculate the average of all valus from 0 inclusive to 10 exclusive."
    print "It will print out whether the resulting average is even or odd."

    n0= float(raw_input("n0:"))
    range00= range0(n0)
    n1= float(raw_input("n1:"))
    range00= range0(n1)
    n2= float(raw_input("n2:"))
    range00= range0(n2)
    n3= float(raw_input("n3:"))
    range00= range0(n3)
    n4= float(raw_input("n4:"))
    range00= range0(n4)

    avg1= avg(n0,n1,n2,n3,n4)
    intpart= int(avg1)
    oddeven2= oddeven(int(avg1))
    out= output(avg1,intpart,oddeven2)
    print out

main()

<|endoftext|>


<commit_before>#!/usr/bin/env python

import pika
import uuid

from pika.connection import Parameters
from pika.connection import ConnectionParameters

class RPCServer:
    def __init__(self, config):
        self.config = config
        self.queue = config.get('queue')
        self.connection = pika.BlockingConnection(connection_parameters(config))

        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=self.queue)
        self.channel.basic_qos(prefetch_count=1)

    def consume(self, response):
        self.response = response
        self.channel.basic_consume(self.on_request, self.queue)
        self.channel.start_consuming()

    def on_request(self, ch, method, props, body):
        reply = self.response(body)

        ch.basic_publish(
            exchange='',
            routing_key=props.reply_to,
            properties=pika.BasicProperties(
                correlation_id = props.correlation_id,
            ),
            body=str(reply),
        )
        ch.basic_ack(delivery_tag = method.delivery_tag)

class RPCClient:
    def __init__(self, config):
        self.config = config
        self.queue = config.get('queue')
        self.connection = pika.BlockingConnection(connection_parameters(config))

        self.channel = self.connection.channel()

        result = self.channel.queue_declare(exclusive=True)
        self.reply_queue = result.method.queue

        self.channel.basic_consume(
            self.on_response,
            no_ack=True,
            queue=self.reply_queue
        )

    def on_response(self, ch, method, props, body):
        if self.corr_id == props.correlation_id:
            self.reply = body

    def request(self, query):
        self.reply = None
        self.corr_id = str(uuid.uuid4())
        self.channel.basic_publish(exchange='',
            routing_key=self.queue,
            properties=pika.BasicProperties(
                reply_to = self.reply_queue,
                correlation_id = self.corr_id,
            ),
            body=str(query)
        )
        while self.reply is None:
            self.connection.process_data_events()
        return self.reply

def connection_parameters(config):
    args = {
        'host': config.get('host', ConnectionParameters._DEFAULT),
        'port': config.get('port', ConnectionParameters._DEFAULT),
        'virtual_host': config.get('virtual_host', ConnectionParameters._DEFAULT),
    }
    if 'username' in config:
        args['credentials'] = pika.PlainCredentials(
            config.get('username', Parameters.DEFAULT_USERNAME),
            config.get('password', Parameters.DEFAULT_PASSWORD)
        )
    return ConnectionParameters(**args)
<commit_msg>Fixed for pika 1.0.1<commit_after>#!/usr/bin/env python

import pika
import uuid

from pika.connection import Parameters
from pika.connection import ConnectionParameters

class RPCServer:
    def __init__(self, config):
        self.config = config
        self.queue = config.get('queue')
        self.connection = pika.BlockingConnection(connection_parameters(config))

        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=self.queue)
        self.channel.basic_qos(prefetch_count=1)

    def consume(self, response):
        self.response = response
        self.channel.basic_consume(self.on_request, self.queue)
        self.channel.start_consuming()

    def on_request(self, ch, method, props, body):
        reply = self.response(body)

        ch.basic_publish(
            exchange='',
            routing_key=props.reply_to,
            properties=pika.BasicProperties(
                correlation_id = props.correlation_id,
            ),
            body=str(reply),
        )
        ch.basic_ack(delivery_tag = method.delivery_tag)

class RPCClient:
    def __init__(self, config):
        self.config = config
        self.queue = config.get('queue')
        self.connection = pika.BlockingConnection(connection_parameters(config))

        self.channel = self.connection.channel()

        result = self.channel.queue_declare('', exclusive=True)
        self.reply_queue = result.method.queue

        self.channel.basic_consume(
            queue=self.reply_queue,
            on_message_callback=self.on_response,
            auto_ack=True,
        )

    def on_response(self, ch, method, props, body):
        if self.corr_id == props.correlation_id:
            self.reply = body

    def request(self, query):
        self.reply = None
        self.corr_id = str(uuid.uuid4())
        self.channel.basic_publish(exchange='',
            routing_key=self.queue,
            properties=pika.BasicProperties(
                reply_to = self.reply_queue,
                correlation_id = self.corr_id,
            ),
            body=str(query)
        )
        while self.reply is None:
            self.connection.process_data_events()
        return self.reply

def connection_parameters(config):
    args = {
        'host': config.get('host', ConnectionParameters._DEFAULT),
        'port': config.get('port', ConnectionParameters._DEFAULT),
        'virtual_host': config.get('virtual_host', ConnectionParameters._DEFAULT),
    }
    if 'username' in config:
        args['credentials'] = pika.PlainCredentials(
            config.get('username', Parameters.DEFAULT_USERNAME),
            config.get('password', Parameters.DEFAULT_PASSWORD)
        )
    return ConnectionParameters(**args)
<|endoftext|>