Пример #1
0
def start_of_next_business_year():
    day = Config.business_year_start()["day"]
    month = Config.business_year_start()["month"]
    return calculate_next(day, month)
Пример #2
0
 class Meta:
     verbose_name = _('{0}-Typ').format(Config.vocabulary('subscription'))
     verbose_name_plural = _('{0}-Typen').format(
         Config.vocabulary('subscription'))
Пример #3
0
def get_server():
    return 'http://' + Config.adminportal_server_url()
Пример #4
0
    def handle(self, *args, **options):
        subscription = Subscription.objects.all()[0]
        if ExtraSubscription.objects.all().count() > 0:
            extrasub = ExtraSubscription.objects.all()[0]
        else:
            extrasub = None
        share = Share.objects.all()[0]
        job = RecuringJob.objects.all()[0]
        member = Member.objects.all()[0]
        depot = Depot.objects.all()[0]
        bill = Bill(ref_number='123456789', amount='1234.99')

        print('*** welcome  mit abo***')

        plaintext = get_template(Config.emails('welcome'))
        d = {
            'username': '******',
            'password': '******',
            'hash': 'hash',
            'subscription': subscription,
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** welcome  ohne abo***')

        plaintext = get_template(Config.emails('welcome'))
        d = {
            'username': '******',
            'password': '******',
            'hash': 'hash',
            'subscription': None,
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** s_created ***')

        plaintext = get_template(Config.emails('s_created'))
        d = {'share': share, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** n_sub ***')

        plaintext = get_template(Config.emails('n_sub'))
        d = {'subscription': subscription, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** co_welcome ***')

        plaintext = get_template(Config.emails('co_welcome'))
        d = {
            'username': '******',
            'name': 'Hans Muster',
            'password': '******',
            'hash': 'hash',
            'shares': '9',
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** co_added ***')

        plaintext = get_template(Config.emails('co_added'))
        d = {
            'username': '******',
            'name': 'Hans Muster',
            'password': '******',
            'hash': 'hash',
            'shares': '9',
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** password ***')

        plaintext = get_template(Config.emails('password'))
        d = {
            'email': '*****@*****.**',
            'password': '******',
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** j_reminder ***')

        plaintext = get_template(Config.emails('j_reminder'))
        coordinator = job.type.activityarea.coordinator
        contact = coordinator.first_name + ' ' + coordinator.last_name + ': ' + job.type.activityarea.contact(
        )
        d = {
            'job': job,
            'participants': [member],
            'serverurl': get_server(),
            'contact': contact
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** j_canceled ***')

        plaintext = get_template(Config.emails('j_canceled'))
        d = {'job': job, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** confirm ***')

        plaintext = get_template(Config.emails('confirm'))
        d = {'hash': 'hash', 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** j_changed ***')

        plaintext = get_template(Config.emails('j_changed'))
        d = {'job': job, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** j_signup ***')

        plaintext = get_template(Config.emails('j_signup'))
        d = {'job': job, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** d_changed ***')

        plaintext = get_template(Config.emails('d_changed'))
        d = {'depot': depot, 'serverurl': get_server()}
        content = plaintext.render(d)
        print(content)
        print()

        print('*** s_canceled ***')

        plaintext = get_template(Config.emails('s_canceled'))
        d = {
            'subscription': subscription,
            'message': 'Nachricht',
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** m_canceled ***')

        plaintext = get_template(Config.emails('m_canceled'))
        d = {
            'member': member,
            'end_date': timezone.now(),
            'message': 'Nachricht',
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** b_share ***')

        plaintext = get_template(Config.emails('b_share'))
        d = {
            'member': member,
            'bill': bill,
            'share': share,
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        print('*** b_sub ***')

        plaintext = get_template(Config.emails('b_sub'))
        d = {
            'member': member,
            'bill': bill,
            'sub': subscription,
            'start': timezone.now(),
            'end': timezone.now(),
            'serverurl': get_server()
        }
        content = plaintext.render(d)
        print(content)
        print()

        if extrasub is not None:
            print('*** b_esub ***')

            plaintext = get_template(Config.emails('b_esub'))
            d = {
                'member': member,
                'bill': bill,
                'extrasub': extrasub,
                'start': timezone.now(),
                'end': timezone.now(),
                'serverurl': get_server()
            }
            content = plaintext.render(d)
            print(content)
            print()
Пример #5
0
 def __str__(self):
     return '%s #%s' % (Config.vocabulary('assignment'), self.id)
Пример #6
0
def images(key):
    return Config.images(key)
Пример #7
0
def cookie_consent(key):
    return Config.cookie_consent(key)
Пример #8
0
 class Meta:
     verbose_name = Config.vocabulary('member')
     verbose_name_plural = Config.vocabulary('member_pl')
     permissions = (('can_filter_members', _('Benutzer kann {0} filtern').format(Config.vocabulary('member_pl'))),)
Пример #9
0
def share_created(share):
    EmailSender.get_sender(
        organisation_subject(
            _('Neue/r/s {} erstellt').format(Config.vocabulary('share'))),
        get_email_content('a_share_created', base_dict(locals())),
        bcc=get_emails_by_permission('notified_on_share_creation')).send()
Пример #10
0
def member_canceled(member, end_date, message, **kwargs):
    EmailSender.get_sender(organisation_subject(
        _('{} gekündigt').format(Config.vocabulary('member_type'))),
                           get_email_content('m_canceled',
                                             base_dict(locals())),
                           bcc=kwargs['emails']).send()
Пример #11
0
class Member(JuntagricoBaseModel):
    '''
    Additional fields for Django's default user class.
    '''

    # user class is only used for logins, permissions, and other builtin django stuff
    # all user information should be stored in the Member model
    user = models.OneToOneField(
        User, related_name='member', null=True, blank=True, on_delete=models.CASCADE)

    first_name = models.CharField(_('Vorname'), max_length=30)
    last_name = models.CharField(_('Nachname'), max_length=30)
    email = models.EmailField(unique=True)

    addr_street = models.CharField(_('Strasse'), max_length=100)
    addr_zipcode = models.CharField(_('PLZ'), max_length=10)
    addr_location = models.CharField(_('Ort'), max_length=50)
    birthday = models.DateField(_('Geburtsdatum'), null=True, blank=True)
    phone = models.CharField(_('Telefonnr'), max_length=50)
    mobile_phone = models.CharField(
        _('Mobile'), max_length=50, null=True, blank=True)

    iban = models.CharField('IBAN', max_length=100, blank=True, default='')

    future_subscription = models.ForeignKey(
        'Subscription', related_name='members_future', null=True, blank=True, on_delete=models.SET_NULL)
    subscription = models.ForeignKey(
        'Subscription', related_name='members', null=True, blank=True, on_delete=models.SET_NULL)
    old_subscriptions = models.ManyToManyField(
        'Subscription', related_name='members_old')

    confirmed = models.BooleanField(_('E-Mail-Adresse bestätigt'), default=False)
    reachable_by_email = models.BooleanField(
        _('Kontaktierbar von der Job Seite aus'), default=False)

    canceled = models.BooleanField(_('gekündigt'), default=False)
    cancelation_date = models.DateField(
        _('Kündigüngsdatum'), null=True, blank=True)
    end_date = models.DateField(
        _('Enddatum'), null=True, blank=True)
    inactive = models.BooleanField(_('inaktiv'), default=False,
                                   help_text=_('Sperrt Login und entfernt von E-Mail-Listen'))
    notes = models.TextField(
        _('Notizen'), max_length=1000, blank=True,
        help_text=_('Notizen für Administration. Nicht sichtbar für {}'.format(Config.vocabulary('member'))))

    @property
    def active_shares(self):
        """ :return: shares that have been paid by member and not cancelled AND paid back yet
        """
        return self.share_set.filter(paid_date__isnull=False).filter(payback_date__isnull=True)

    @property
    def active_shares_count(self):
        return self.active_shares.count()

    @property
    def is_cooperation_member(self):
        return self.active_shares_count > 0

    @property
    def usable_shares(self):
        """ :return: shares that have been ordered (i.e. created) and not cancelled yet
        """
        return self.share_set.filter(cancelled_date__isnull=True)

    @property
    def usable_shares_count(self):
        return self.usable_shares.count()

    @property
    def in_subscription(self):
        return (self.future_subscription is not None) | (self.subscription is not None)

    @property
    def blocked(self):
        future = self.future_subscription is not None
        current = self.subscription is None or not self.subscription.canceled
        return future or not current

    def get_name(self):
        return '%s %s' % (self.first_name, self.last_name)

    def get_phone(self):
        if self.mobile_phone != '':
            return self.mobile_phone
        return self.phone

    def get_hash(self):
        return hashlib.sha1((str(self.email) + str(self.pk)).encode('utf8')).hexdigest()

    def __str__(self):
        return self.get_name()

    def clean(self):
        check_member_consistency(self)

    @classmethod
    def create(cls, sender, instance, created, **kwds):
        '''
        Callback to create corresponding user when new member is created.
        '''
        if created and instance.user is None:
            username = make_username(
                instance.first_name, instance.last_name, instance.email)
            user = User(username=username)
            user.save()
            user = User.objects.get(username=username)
            instance.user = user
            instance.save()

    @classmethod
    def post_delete(cls, sender, instance, **kwds):
        instance.user.delete()

    @notifiable
    class Meta:
        verbose_name = Config.vocabulary('member')
        verbose_name_plural = Config.vocabulary('member_pl')
        permissions = (('can_filter_members', _('Benutzer kann {0} filtern').format(Config.vocabulary('member_pl'))),)
Пример #12
0
def member_created(member, **kwargs):
    EmailSender.get_sender(organisation_subject(
        _('Neue/r/s {}').format(Config.vocabulary('member_type'))),
                           get_email_content('a_member_created',
                                             base_dict(locals())),
                           bcc=kwargs['emails']).send()
Пример #13
0
def share_created(share, **kwargs):
    EmailSender.get_sender(organisation_subject(
        _('Neue/r/s {} erstellt').format(Config.vocabulary('share'))),
                           get_email_content('a_share_created',
                                             base_dict(locals())),
                           bcc=kwargs['emails']).send()
Пример #14
0
def subscription_canceled(subscription, message, **kwargs):
    EmailSender.get_sender(organisation_subject(
        _('{} gekündigt').format(Config.vocabulary('subscription'))),
                           get_email_content('s_canceled',
                                             base_dict(locals())),
                           bcc=kwargs['emails']).send()
Пример #15
0
class Subscription(Billable):
    '''
    One Subscription that may be shared among several people.
    '''
    depot = models.ForeignKey('Depot',
                              on_delete=models.PROTECT,
                              related_name='subscription_set')
    future_depot = models.ForeignKey(
        Depot,
        on_delete=models.PROTECT,
        related_name='future_subscription_set',
        null=True,
        blank=True,
        verbose_name=_('Zukünftiges {}').format(Config.vocabulary('depot')),
        help_text='Nur setzen, wenn {} geändert werden soll'.format(
            Config.vocabulary('depot')))
    types = models.ManyToManyField('SubscriptionType',
                                   through='TSST',
                                   related_name='subscription_set')
    future_types = models.ManyToManyField(
        'SubscriptionType',
        through='TFSST',
        related_name='future_subscription_set')
    primary_member = models.ForeignKey(
        'Member',
        related_name='subscription_primary',
        null=True,
        blank=True,
        on_delete=models.PROTECT,
        verbose_name=_('Haupt-{}-BezieherIn').format(
            Config.vocabulary('subscription')))
    active = models.BooleanField(default=False, verbose_name='Aktiv')
    canceled = models.BooleanField(_('gekündigt'), default=False)
    activation_date = models.DateField(_('Aktivierungssdatum'),
                                       null=True,
                                       blank=True)
    deactivation_date = models.DateField(_('Deaktivierungssdatum'),
                                         null=True,
                                         blank=True)
    cancelation_date = models.DateField(_('Kündigüngssdatum'),
                                        null=True,
                                        blank=True)
    creation_date = models.DateField(_('Erstellungsdatum'),
                                     null=True,
                                     blank=True,
                                     auto_now_add=True)
    start_date = models.DateField(_('Gewünschtes Startdatum'),
                                  null=False,
                                  default=start_of_next_business_year)
    end_date = models.DateField(_('Gewünschtes Enddatum'),
                                null=True,
                                blank=True)
    notes = models.TextField(
        _('Notizen'),
        max_length=1000,
        blank=True,
        help_text=_('Notizen für Administration. Nicht sichtbar für {}'.format(
            Config.vocabulary('member'))))
    _future_members = None

    def __str__(self):
        namelist = [_(' Einheiten {0}').format(self.size)]
        namelist.extend(extra.type.name
                        for extra in self.extra_subscriptions.all())
        return _('Abo ({1}) {0}').format(' + '.join(namelist), self.id)

    def __repr__(self):
        return _('Abo ({})').format(self.id)

    @property
    def overview(self):
        namelist = [_(' Einheiten {0}').format(self.size)]
        namelist.extend(extra.type.name
                        for extra in self.extra_subscriptions.all())
        return '%s' % (' + '.join(namelist))

    @property
    def size(self):
        sizes = {}
        for type in self.types.all():
            sizes[type.size.product.name] = type.size.units + sizes.get(
                type.size.product.name, 0)
        return ', '.join(
            [key + ':' + str(value) for key, value in sizes.items()])

    @property
    def types_changed(self):
        return sorted(list(self.types.all())) != sorted(
            list(self.future_types.all()))

    def recipients_names(self):
        members = self.recipients
        return ', '.join(str(member) for member in members)

    recipients_names.short_description = '{}-BezieherInnen'.format(
        Config.vocabulary('subscription'))

    def other_recipients(self):
        return self.recipients.exclude(email=self.primary_member.email)

    def other_recipients_names(self):
        members = self.other_recipients()
        return ', '.join(str(member) for member in members)

    @property
    def recipients(self):
        return self.recipients_all.filter(inactive=False)

    @property
    def recipients_all(self):
        return self.recipients_all_for_state(self.state)

    def recipients_all_for_state(self, state):
        if state == 'waiting':
            return self.members_future.all()
        elif state == 'inactive':
            return self.members_old.all()
        else:
            return self.members.all()

    def primary_member_nullsave(self):
        member = self.primary_member
        return str(member) if member is not None else ''

    primary_member_nullsave.short_description = primary_member.verbose_name

    @property
    def state(self):
        if self.active is False and self.deactivation_date is None:
            return 'waiting'
        elif self.active is True and self.canceled is False:
            return 'active'
        elif self.active is True and self.canceled is True:
            return 'canceled'
        elif self.active is False and self.deactivation_date is not None:
            return 'inactive'

    @property
    def extra_subscriptions(self):
        return self.extra_subscription_set.filter(active=True)

    @property
    def future_extra_subscriptions(self):
        return self.extra_subscription_set.filter(
            Q(active=False, deactivation_date=None)
            | Q(active=True, canceled=False))

    @property
    def all_shares(self):
        return ShareDao.all_shares_subscription(self).count()

    @property
    def paid_shares(self):
        return ShareDao.paid_shares(self).count()

    @property
    def share_overflow(self):
        return self.all_shares - self.required_shares

    @property
    def extrasubscriptions_changed(self):
        current_extrasubscriptions = self.extra_subscriptions.all()
        future_extrasubscriptions = self.future_extra_subscriptions.all()
        return set(current_extrasubscriptions) != set(
            future_extrasubscriptions)

    def subscription_amount(self, size):
        return self.calc_subscription_amount(self.types, size)

    def subscription_amount_future(self, size):
        return self.calc_subscription_amount(self.future_types, size)

    @staticmethod
    def calc_subscription_amount(types, size):
        return types.filter(size=size).count()

    def future_amount_by_type(self, type):
        return len(self.future_types.filter(id=type))

    @staticmethod
    def next_extra_change_date():
        month = int(time.strftime('%m'))
        if month >= 7:
            next_extra = datetime.date(day=1,
                                       month=1,
                                       year=timezone.now().today().year + 1)
        else:
            next_extra = datetime.date(day=1,
                                       month=7,
                                       year=timezone.now().today().year)
        return next_extra

    @staticmethod
    def next_size_change_date():
        return start_of_next_business_year()

    @staticmethod
    def get_size_name(types=[]):
        size_dict = {}
        for type in types.all():
            size_dict[type.__str__()] = 1 + size_dict.get(type.__str__(), 0)
        size_names = [
            key + ':' + str(value) for key, value in size_dict.items()
        ]
        if len(size_names) > 0:
            return '<br>'.join(size_names)
        return _('kein/e/n {0}').format(Config.vocabulary('subscription'))

    @property
    def required_shares(self):
        result = 0
        for type in self.types.all():
            result += type.shares
        return result

    @property
    def required_assignments(self):
        result = 0
        for type in self.types.all():
            result += type.required_assignments
        return result

    @property
    def required_core_assignments(self):
        result = 0
        for type in self.types.all():
            result += type.required_core_assignments
        return result

    @property
    def price(self):
        result = 0
        for type in self.types.all():
            result += type.price
        return result

    @property
    def size_name(self):
        return Subscription.get_size_name(types=self.types)

    @property
    def future_size_name(self):
        return Subscription.get_size_name(types=self.future_types)

    def extra_subscription_amount(self, extra_sub_type):
        return self.extra_subscriptions.filter(type=extra_sub_type).count()

    def clean(self):
        check_sub_consistency(self)

    @notifiable
    class Meta:
        verbose_name = Config.vocabulary('subscription')
        verbose_name_plural = Config.vocabulary('subscription_pl')
        permissions = (('can_filter_subscriptions',
                        _('Benutzer kann {0} filtern').format(
                            Config.vocabulary('subscription'))), )
Пример #16
0
def member_created(member):
    EmailSender.get_sender(
        organisation_subject(
            _('Neue/r/s {}').format(Config.vocabulary('member_type'))),
        get_email_content('a_member_created', base_dict(locals())),
        bcc=get_emails_by_permission('notified_on_member_creation')).send()
Пример #17
0
 class Meta:
     verbose_name = Config.vocabulary('subscription')
     verbose_name_plural = Config.vocabulary('subscription_pl')
     permissions = (('can_filter_subscriptions',
                     _('Benutzer kann {0} filtern').format(
                         Config.vocabulary('subscription'))), )
Пример #18
0
 def __init__(self, model, admin_site):
     super().__init__(model, admin_site)
     if not Config.enable_shares():
         self.exclude.append('shares')
Пример #19
0
def vocabulary(key):
    return Config.vocabulary(key)
Пример #20
0
 def get_submit_button():
     return Submit('submit',
                   _('{} hinzufügen').format(
                       Config.vocabulary('co_member')),
                   css_class='btn-success')
Пример #21
0
 def create(cls, sender, instance, created, **kwds):
     if created and Config.billing():
         bill_share(instance)
Пример #22
0
 def button_next_text(self):
     return _('Keine weiteren {} hinzufügen').format(
         Config.vocabulary('co_member_pl'))
Пример #23
0
class Job(PolymorphicModel):
    slots = models.PositiveIntegerField(_('Plaetze'))
    time = models.DateTimeField()
    multiplier = models.PositiveIntegerField(_('{0}) vielfaches').format(
        Config.vocabulary('assignment')),
                                             default=1)
    pinned = models.BooleanField(default=False)
    reminder_sent = models.BooleanField(_('Reminder verschickt'),
                                        default=False)
    canceled = models.BooleanField(_('abgesagt'), default=False)
    old_canceled = None
    old_time = None

    @property
    def type(self):
        raise NotImplementedError

    def __str__(self):
        return _('Job #%s') % (self.id)

    def weekday_name(self):
        day = self.time.isoweekday()
        return weekday_short(day, 2)

    def time_stamp(self):
        return int(time.mktime(self.time.timetuple()) * 1000)

    def free_slots(self):
        if not (self.slots is None):
            return self.slots - self.occupied_places()
        else:
            return 0

    def end_time(self):
        return self.time + timezone.timedelta(hours=self.type.duration)

    def start_time(self):
        return self.time

    def occupied_places(self):
        return self.assignment_set.count()

    def get_status_percentage(self):
        assignments = AssignmentDao.assignments_for_job(self.id)
        if self.slots < 1:
            return get_status_image(100)
        return get_status_image(assignments.count() * 100 / self.slots)

    def is_core(self):
        return self.type.activityarea.core

    def extras(self):
        extras_result = []
        for extra in self.type.job_extras_set.all():
            if extra.empty(self.assignment_set.all()):
                extras_result.append(extra.extra_type.display_empty)
            else:
                extras_result.append(extra.extra_type.display_full)
        return ' '.join(extras_result)

    def empty_per_job_extras(self):
        extras_result = []
        for extra in self.type.job_extras_set.filter(per_member=False):
            if extra.empty(self.assignment_set.all()):
                extras_result.append(extra)
        return extras_result

    def full_per_job_extras(self):
        extras_result = []
        for extra in self.type.job_extras_set.filter(per_member=False):
            if not extra.empty(self.assignment_set.all()):
                extras_result.append(extra)
        return extras_result

    def per_member_extras(self):
        return self.type.job_extras_set.filter(per_member=True)

    def clean(self):
        if self.old_canceled != self.canceled and self.old_canceled is True:
            raise ValidationError(
                _('Abgesagte jobs koennen nicht wieder aktiviert werden'),
                code='invalid')

    @classmethod
    def pre_save(cls, sender, instance, **kwds):
        if instance.old_canceled != instance.canceled and instance.old_canceled is False:
            assignments = AssignmentDao.assignments_for_job(instance.id)
            emails = set()
            for assignment in assignments:
                emails.add(assignment.member.email)
            instance.slots = 0
            if len(emails) > 0:
                send_job_canceled(emails, instance)
        if instance.old_time != instance.time:
            assignments = AssignmentDao.assignments_for_job(instance.id)
            emails = set()
            for assignment in assignments:
                emails.add(assignment.member.email)
            if len(emails) > 0:
                send_job_time_changed(emails, instance)

    @classmethod
    def post_init(cls, sender, instance, **kwds):
        instance.old_time = instance.time
        instance.old_canceled = instance.canceled
        if instance.canceled:
            assignments = AssignmentDao.assignments_for_job(instance.id)
            assignments.delete()

    class Meta:
        verbose_name = _('AbstractJob')
        verbose_name_plural = _('AbstractJobs')
Пример #24
0
 def get_promoted_jobs():
     return RecuringJob.objects.filter(
         type__name__in=Config.promoted_job_types(),
         time__gte=timezone.now()).order_by(
             'time')[:Config.promomted_jobs_amount()]
Пример #25
0
 class Meta:
     verbose_name = Config.vocabulary('assignment')
     verbose_name_plural = Config.vocabulary('assignment_pl')
Пример #26
0
def send_fund_confirmation_mail(fund, password=None):
    plaintext = get_template(CrowdfundingConfig.emails('fund_confirmation_mail'))
    content = plaintext.render(base_dict(locals()))
    EmailSender.get_sender(
        Config.organisation_name() + ' - Beitragsbestätigung',
        content).send_to(fund.funder.email)
from juntagrico.admins import BaseAdmin
from juntagrico.config import Config


class ExtraSubscriptionTypeAdmin(BaseAdmin):
    exclude = []


if not Config.enable_shares():
    ExtraSubscriptionTypeAdmin.exclude.append('shares')
Пример #28
0
def job(request, job_id):
    '''
    Details for a job
    '''
    member = request.user.member
    job = get_object_or_404(Job, id=int(job_id))
    slotrange = list(range(0, job.slots))
    allowed_additional_participants = list(range(1, job.free_slots + 1))
    job_fully_booked = len(allowed_additional_participants) == 0
    job_is_in_past = job.end_time() < timezone.now()
    job_is_running = job.start_time() < timezone.now()
    job_canceled = job.canceled
    can_subscribe = job.infinite_slots or not (
        job_fully_booked or job_is_in_past or job_is_running or job_canceled)
    renderdict = get_menu_dict(request)

    if request.method == 'POST' and can_subscribe and 0 < int(
            request.POST.get('jobs')) <= job.free_slots:
        num = int(request.POST.get('jobs'))
        # adding participants
        amount = 1
        if Config.assignment_unit() == 'ENTITY':
            amount = job.multiplier
        elif Config.assignment_unit() == 'HOURS':
            amount = job.multiplier * job.duration
        for i in range(num):
            assignment = Assignment.objects.create(member=member,
                                                   job=job,
                                                   amount=amount)
        for extra in job.type.job_extras_set.all():
            if request.POST.get('extra' + str(extra.extra_type.id)) == str(
                    extra.extra_type.id):
                assignment.job_extras.add(extra)
        assignment.save()
        membernotification.job_signup(member.email, job)
        # redirect to same page such that refresh in the browser or back
        # button does not trigger a resubmission of the form
        return redirect('job', job_id=job_id)
    elif request.method == 'POST':
        renderdict['messages'].extend(error_message(request))

    all_participants = MemberDao.members_by_job(job)
    number_of_participants = len(all_participants)
    unique_participants = all_participants.annotate(
        assignment_for_job=Count('id')).distinct()

    participants_summary = []
    emails = []
    for participant in unique_participants:
        name = '{} {}'.format(participant.first_name, participant.last_name)
        if participant.assignment_for_job == 2:
            name += _(' (mit einer weiteren Person)')
        elif participant.assignment_for_job > 2:
            name += _(' (mit {} weiteren Personen)').format(
                participant.assignment_for_job - 1)
        contact_url = reverse('contact-member', args=[participant.id])
        extras = []
        for assignment in AssignmentDao.assignments_for_job_and_member(
                job.id, participant):
            for extra in assignment.job_extras.all():
                extras.append(extra.extra_type.display_full)
        reachable = participant.reachable_by_email is True or request.user.is_staff or \
            job.type.activityarea.coordinator == participant
        participants_summary.append(
            (name, contact_url, reachable, ' '.join(extras)))
        emails.append(participant.email)

    renderdict['messages'].extend(job_messages(request, job))
    renderdict.update({
        'can_contact':
        request.user.has_perm('juntagrico.can_send_mails')
        or (job.type.activityarea.coordinator == member
            and request.user.has_perm('juntagrico.is_area_admin')),
        'emails':
        '\n'.join(emails),
        'number_of_participants':
        number_of_participants,
        'participants_summary':
        participants_summary,
        'job':
        job,
        'slotrange':
        slotrange,
        'allowed_additional_participants':
        allowed_additional_participants,
        'can_subscribe':
        can_subscribe,
        'edit_url':
        get_job_admin_url(request, job)
    })
    return render(request, 'job.html', renderdict)
Пример #29
0
 def contact_admin_link(text):
     return mark_safe(
         escape(text).format('<a href="mailto:{0}">{0}</a>'.format(
             Config.info_email())))
Пример #30
0
def start_of_specific_business_year(refdate):
    day = Config.business_year_start()['day']
    month = Config.business_year_start()['month']
    return calculate_last_offset(day, month, refdate)