예제 #1
0
파일: order.py 프로젝트: bsod85/pretix
    def create(self, request, *args, **kwargs):
        serializer = OrderCreateSerializer(
            data=request.data, context=self.get_serializer_context())
        serializer.is_valid(raise_exception=True)
        with transaction.atomic():
            self.perform_create(serializer)
            order = serializer.instance
            serializer = OrderSerializer(order, context=serializer.context)

            order.log_action(
                'pretix.event.order.placed',
                user=request.user if request.user.is_authenticated else None,
                auth=request.auth,
            )
        order_placed.send(self.request.event, order=order)

        gen_invoice = invoice_qualified(order) and (
            (order.event.settings.get('invoice_generate') == 'True') or
            (order.event.settings.get('invoice_generate') == 'paid' and
             order.status == Order.STATUS_PAID)) and not order.invoices.last()
        if gen_invoice:
            generate_invoice(order, trigger_pdf=True)

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)
예제 #2
0
def _create_order(event: Event,
                  email: str,
                  positions: list,
                  dt: datetime,
                  payment_provider: BasePaymentProvider,
                  locale: str = None):
    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee
    expires = [
        dt +
        timedelta(days=event.settings.get('payment_term_days', as_type=int))
    ]
    if event.settings.get('payment_term_last'):
        expires.append(
            event.settings.get('payment_term_last', as_type=datetime))
    order = Order.objects.create(status=Order.STATUS_PENDING,
                                 event=event,
                                 email=email,
                                 datetime=dt,
                                 expires=min(expires),
                                 locale=locale,
                                 total=total,
                                 payment_fee=payment_fee,
                                 payment_provider=payment_provider.identifier)
    OrderPosition.transform_cart_positions(positions, order)
    order_placed.send(event, order=order)
    return order
예제 #3
0
파일: orders.py 프로젝트: rahmonov/pretix
def _create_order(event: Event, email: str, positions: List[CartPosition], now_dt: datetime,
                  payment_provider: BasePaymentProvider, locale: str=None, address: int=None,
                  meta_info: dict=None):
    from datetime import date, time

    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee

    tz = pytz.timezone(event.settings.timezone)
    exp_by_date = now_dt.astimezone(tz) + timedelta(days=event.settings.get('payment_term_days', as_type=int))
    exp_by_date = exp_by_date.astimezone(tz).replace(hour=23, minute=59, second=59, microsecond=0)
    if event.settings.get('payment_term_weekdays'):
        if exp_by_date.weekday() == 5:
            exp_by_date += timedelta(days=2)
        elif exp_by_date.weekday() == 6:
            exp_by_date += timedelta(days=1)

    expires = exp_by_date

    if event.settings.get('payment_term_last'):
        last_date = make_aware(datetime.combine(
            event.settings.get('payment_term_last', as_type=date),
            time(hour=23, minute=59, second=59)
        ), tz)
        if last_date < expires:
            expires = last_date

    with transaction.atomic():
        order = Order.objects.create(
            status=Order.STATUS_PENDING,
            event=event,
            email=email,
            datetime=now_dt,
            expires=expires,
            locale=locale,
            total=total,
            payment_fee=payment_fee,
            payment_provider=payment_provider.identifier,
            meta_info=json.dumps(meta_info or {}),
        )
        OrderPosition.transform_cart_positions(positions, order)

        if address is not None:
            try:
                addr = InvoiceAddress.objects.get(
                    pk=address
                )
                if addr.order is not None:
                    addr.pk = None
                addr.order = order
                addr.save()
            except InvoiceAddress.DoesNotExist:
                pass

        order.log_action('pretix.event.order.placed')

    order_placed.send(event, order=order)
    return order
예제 #4
0
파일: orders.py 프로젝트: rixx/pretix
def _create_order(event: Event, email: str, positions: List[CartPosition], now_dt: datetime,
                  payment_provider: BasePaymentProvider, locale: str=None, address: int=None,
                  meta_info: dict=None):
    from datetime import date, time

    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee

    tz = pytz.timezone(event.settings.timezone)
    exp_by_date = now_dt.astimezone(tz) + timedelta(days=event.settings.get('payment_term_days', as_type=int))
    exp_by_date = exp_by_date.replace(hour=23, minute=59, second=59, microsecond=0)
    if event.settings.get('payment_term_weekdays'):
        if exp_by_date.weekday() == 5:
            exp_by_date += timedelta(days=2)
        elif exp_by_date.weekday() == 6:
            exp_by_date += timedelta(days=1)

    expires = exp_by_date

    if event.settings.get('payment_term_last'):
        last_date = make_aware(datetime.combine(
            event.settings.get('payment_term_last', as_type=date),
            time(hour=23, minute=59, second=59)
        ), tz)
        if last_date < expires:
            expires = last_date

    order = Order.objects.create(
        status=Order.STATUS_PENDING,
        event=event,
        email=email,
        datetime=now_dt,
        expires=expires,
        locale=locale,
        total=total,
        payment_fee=payment_fee,
        payment_provider=payment_provider.identifier,
        meta_info=json.dumps(meta_info or {}),
    )
    OrderPosition.transform_cart_positions(positions, order)

    if address is not None:
        try:
            addr = InvoiceAddress.objects.get(
                pk=address
            )
            if addr.order is not None:
                addr.pk = None
            addr.order = order
            addr.save()
        except InvoiceAddress.DoesNotExist:
            pass

    order.log_action('pretix.event.order.placed')
    order_placed.send(event, order=order)
    return order
예제 #5
0
def _create_order(event: Event,
                  email: str,
                  positions: List[CartPosition],
                  now_dt: datetime,
                  payment_provider: BasePaymentProvider,
                  locale: str = None,
                  address: int = None):
    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee

    exp_by_date = now_dt + timedelta(
        days=event.settings.get('payment_term_days', as_type=int))
    if event.settings.get('payment_term_weekdays'):
        if exp_by_date.weekday() == 5:
            exp_by_date += timedelta(days=2)
        elif exp_by_date.weekday() == 6:
            exp_by_date += timedelta(days=1)

    expires = [exp_by_date]
    if event.settings.get('payment_term_last'):
        expires.append(
            event.settings.get('payment_term_last', as_type=datetime))
    order = Order.objects.create(status=Order.STATUS_PENDING,
                                 event=event,
                                 email=email,
                                 datetime=now_dt,
                                 expires=min(expires),
                                 locale=locale,
                                 total=total,
                                 payment_fee=payment_fee,
                                 payment_provider=payment_provider.identifier)
    OrderPosition.transform_cart_positions(positions, order)

    if address is not None:
        try:
            addr = InvoiceAddress.objects.get(pk=address)
            if addr.order is not None:
                addr.pk = None
            addr.order = order
            addr.save()
        except InvoiceAddress.DoesNotExist:
            pass

    order.log_action('pretix.event.order.placed')
    order_placed.send(event, order=order)
    return order
예제 #6
0
파일: orders.py 프로젝트: cherti/pretix
def _create_order(event: Event, email: str, positions: List[CartPosition], now_dt: datetime,
                  payment_provider: BasePaymentProvider, locale: str=None, address: int=None):
    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee

    exp_by_date = now_dt + timedelta(days=event.settings.get('payment_term_days', as_type=int))
    if event.settings.get('payment_term_weekdays'):
        if exp_by_date.weekday() == 5:
            exp_by_date += timedelta(days=2)
        elif exp_by_date.weekday() == 6:
            exp_by_date += timedelta(days=1)

    expires = [exp_by_date]
    if event.settings.get('payment_term_last'):
        expires.append(event.settings.get('payment_term_last', as_type=datetime))
    order = Order.objects.create(
        status=Order.STATUS_PENDING,
        event=event,
        email=email,
        datetime=now_dt,
        expires=min(expires),
        locale=locale,
        total=total,
        payment_fee=payment_fee,
        payment_provider=payment_provider.identifier
    )
    OrderPosition.transform_cart_positions(positions, order)

    if address is not None:
        try:
            addr = InvoiceAddress.objects.get(
                pk=address
            )
            if addr.order is not None:
                addr.pk = None
            addr.order = order
            addr.save()
        except InvoiceAddress.DoesNotExist:
            pass

    order.log_action('pretix.event.order.placed')
    order_placed.send(event, order=order)
    return order
예제 #7
0
파일: orders.py 프로젝트: awg24/pretix
def place_order(event, user, positions, dt, payment_provider):
    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee
    expires = [dt + timedelta(days=event.settings.get('payment_term_days', as_type=int))]
    if event.settings.get('payment_term_last'):
        expires.append(event.settings.get('payment_term_last', as_type=datetime))
    order = Order.objects.create(
        status=Order.STATUS_PENDING,
        event=event,
        user=user,
        datetime=dt,
        expires=min(expires),
        total=total,
        payment_fee=payment_fee,
        payment_provider=payment_provider.identifier,
    )
    OrderPosition.transform_cart_positions(positions, order)
    order_placed.send(event, order=order)
    return order
예제 #8
0
파일: orders.py 프로젝트: cygery/pretix
def _create_order(event: Event, email: str, positions: list, dt: datetime,
                  payment_provider: BasePaymentProvider, locale: str=None):
    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee
    expires = [dt + timedelta(days=event.settings.get('payment_term_days', as_type=int))]
    if event.settings.get('payment_term_last'):
        expires.append(event.settings.get('payment_term_last', as_type=datetime))
    order = Order.objects.create(
        status=Order.STATUS_PENDING,
        event=event,
        email=email,
        datetime=dt,
        expires=min(expires),
        locale=locale,
        total=total,
        payment_fee=payment_fee,
        payment_provider=payment_provider.identifier
    )
    OrderPosition.transform_cart_positions(positions, order)
    order_placed.send(event, order=order)
    return order
예제 #9
0
    def create(self, request, *args, **kwargs):
        serializer = OrderCreateSerializer(data=request.data, context=self.get_serializer_context())
        serializer.is_valid(raise_exception=True)
        with transaction.atomic():
            self.perform_create(serializer)
            order = serializer.instance
            serializer = OrderSerializer(order, context=serializer.context)

            order.log_action(
                'pretix.event.order.placed',
                user=request.user if request.user.is_authenticated else None,
                auth=request.auth,
            )
        order_placed.send(self.request.event, order=order)

        gen_invoice = invoice_qualified(order) and (
            (order.event.settings.get('invoice_generate') == 'True') or
            (order.event.settings.get('invoice_generate') == 'paid' and order.status == Order.STATUS_PAID)
        ) and not order.invoices.last()
        if gen_invoice:
            generate_invoice(order, trigger_pdf=True)

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
예제 #10
0
def _create_order(event: Event, email: str, positions: List[CartPosition], now_dt: datetime,
                  payment_provider: BasePaymentProvider, locale: str=None, address: int=None,
                  meta_info: dict=None):
    from datetime import time

    total = sum([c.price for c in positions])
    payment_fee = payment_provider.calculate_fee(total)
    total += payment_fee

    tz = pytz.timezone(event.settings.timezone)
    exp_by_date = now_dt.astimezone(tz) + timedelta(days=event.settings.get('payment_term_days', as_type=int))
    exp_by_date = exp_by_date.astimezone(tz).replace(hour=23, minute=59, second=59, microsecond=0)
    if event.settings.get('payment_term_weekdays'):
        if exp_by_date.weekday() == 5:
            exp_by_date += timedelta(days=2)
        elif exp_by_date.weekday() == 6:
            exp_by_date += timedelta(days=1)

    expires = exp_by_date

    term_last = event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
    if term_last:
        if event.has_subevents:
            term_last = min([
                term_last.datetime(se).date()
                for se in event.subevents.filter(id__in=[p.subevent_id for p in positions])
            ])
        else:
            term_last = term_last.datetime(event).date()
        term_last = make_aware(datetime.combine(
            term_last,
            time(hour=23, minute=59, second=59)
        ), tz)
        if term_last < expires:
            expires = term_last

    with transaction.atomic():
        order = Order.objects.create(
            status=Order.STATUS_PENDING,
            event=event,
            email=email,
            datetime=now_dt,
            expires=expires,
            locale=locale,
            total=total,
            payment_fee=payment_fee,
            payment_provider=payment_provider.identifier,
            meta_info=json.dumps(meta_info or {}),
        )

        if address:
            if address.order is not None:
                address.pk = None
            address.order = order
            address.save()

            order._calculate_tax()  # Might have changed due to new invoice address
            order.save()

        OrderPosition.transform_cart_positions(positions, order)
        order.log_action('pretix.event.order.placed')

    order_placed.send(event, order=order)
    return order
예제 #11
0
    def create(self, request, *args, **kwargs):
        serializer = OrderCreateSerializer(
            data=request.data, context=self.get_serializer_context())
        serializer.is_valid(raise_exception=True)
        with transaction.atomic():
            self.perform_create(serializer)
            send_mail = serializer._send_mail
            order = serializer.instance
            serializer = OrderSerializer(order, context=serializer.context)

            order.log_action(
                'pretix.event.order.placed',
                user=request.user if request.user.is_authenticated else None,
                auth=request.auth,
            )
        order_placed.send(self.request.event, order=order)

        gen_invoice = invoice_qualified(order) and (
            (order.event.settings.get('invoice_generate') == 'True') or
            (order.event.settings.get('invoice_generate') == 'paid' and
             order.status == Order.STATUS_PAID)) and not order.invoices.last()
        invoice = None
        if gen_invoice:
            invoice = generate_invoice(order, trigger_pdf=True)

        if send_mail:
            payment = order.payments.last()
            free_flow = (payment and order.total == Decimal('0.00')
                         and order.status == Order.STATUS_PAID
                         and not order.require_approval
                         and payment.provider == "free")
            if free_flow:
                email_template = request.event.settings.mail_text_order_free
                log_entry = 'pretix.event.order.email.order_free'
                email_attendees = request.event.settings.mail_send_order_free_attendee
                email_attendees_template = request.event.settings.mail_text_order_free_attendee
            else:
                email_template = request.event.settings.mail_text_order_placed
                log_entry = 'pretix.event.order.email.order_placed'
                email_attendees = request.event.settings.mail_send_order_placed_attendee
                email_attendees_template = request.event.settings.mail_text_order_placed_attendee

            _order_placed_email(request.event, order,
                                payment.payment_provider if payment else None,
                                email_template, log_entry, invoice, payment)
            if email_attendees:
                for p in order.positions.all():
                    if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
                        _order_placed_email_attendee(request.event, order, p,
                                                     email_attendees_template,
                                                     log_entry)

            if not free_flow and order.status == Order.STATUS_PAID and payment:
                payment._send_paid_mail(invoice, None, '')
                if self.request.event.settings.mail_send_order_paid_attendee:
                    for p in order.positions.all():
                        if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
                            payment._send_paid_mail_attendee(p, None)

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=headers)
예제 #12
0
def import_orders(event: Event, fileid: str, settings: dict, locale: str,
                  user) -> None:
    # TODO: quotacheck?
    cf = CachedFile.objects.get(id=fileid)
    user = User.objects.get(pk=user)
    with language(locale, event.settings.region):
        cols = get_all_columns(event)
        parsed = parse_csv(cf.file)
        orders = []
        order = None
        data = []

        # Run validation
        for i, record in enumerate(parsed):
            if not any(record.values()):
                continue
            values = {}
            for c in cols:
                val = c.resolve(settings, record)
                if isinstance(val, str):
                    val = val.strip()
                try:
                    values[c.identifier] = c.clean(val, values)
                except ValidationError as e:
                    raise DataImportError(
                        _('Error while importing value "{value}" for column "{column}" in line "{line}": {message}'
                          ).format(value=val if val is not None else '',
                                   column=c.verbose_name,
                                   line=i + 1,
                                   message=e.message))
            data.append(values)

        # Prepare model objects. Yes, this might consume lots of RAM, but allows us to make the actual SQL transaction
        # shorter. We'll see what works better in reality…
        for i, record in enumerate(data):
            try:
                if order is None or settings['orders'] == 'many':
                    order = Order(
                        event=event,
                        testmode=settings['testmode'],
                    )
                    order.meta_info = {}
                    order._positions = []
                    order._address = InvoiceAddress()
                    order._address.name_parts = {
                        '_scheme': event.settings.name_scheme
                    }
                    orders.append(order)

                position = OrderPosition(positionid=len(order._positions) + 1)
                position.attendee_name_parts = {
                    '_scheme': event.settings.name_scheme
                }
                position.meta_info = {}
                order._positions.append(position)
                position.assign_pseudonymization_id()

                for c in cols:
                    c.assign(record.get(c.identifier), order, position,
                             order._address)

            except ImportError as e:
                raise ImportError(
                    _('Invalid data in row {row}: {message}').format(
                        row=i, message=str(e)))

        # quota check?
        with event.lock():
            with transaction.atomic():
                save_transactions = []
                for o in orders:
                    o.total = sum([c.price for c in o._positions
                                   ])  # currently no support for fees
                    if o.total == Decimal('0.00'):
                        o.status = Order.STATUS_PAID
                        o.save()
                        OrderPayment.objects.create(
                            local_id=1,
                            order=o,
                            amount=Decimal('0.00'),
                            provider='free',
                            info='{}',
                            payment_date=now(),
                            state=OrderPayment.PAYMENT_STATE_CONFIRMED)
                    elif settings['status'] == 'paid':
                        o.status = Order.STATUS_PAID
                        o.save()
                        OrderPayment.objects.create(
                            local_id=1,
                            order=o,
                            amount=o.total,
                            provider='manual',
                            info='{}',
                            payment_date=now(),
                            state=OrderPayment.PAYMENT_STATE_CONFIRMED)
                    else:
                        o.status = Order.STATUS_PENDING
                        o.save()
                    for p in o._positions:
                        p.order = o
                        p.save()
                    o._address.order = o
                    o._address.save()
                    for c in cols:
                        c.save(o)
                    o.log_action('pretix.event.order.placed',
                                 user=user,
                                 data={'source': 'import'})
                    save_transactions += o.create_transactions(
                        is_new=True,
                        fees=[],
                        positions=o._positions,
                        save=False)
                Transaction.objects.bulk_create(save_transactions)

            for o in orders:
                with language(o.locale, event.settings.region):
                    order_placed.send(event, order=o)
                    if o.status == Order.STATUS_PAID:
                        order_paid.send(event, order=o)

                    gen_invoice = invoice_qualified(o) and (
                        (event.settings.get('invoice_generate') == 'True') or
                        (event.settings.get('invoice_generate') == 'paid'
                         and o.status
                         == Order.STATUS_PAID)) and not o.invoices.last()
                    if gen_invoice:
                        generate_invoice(o, trigger_pdf=True)
    cf.delete()
예제 #13
0
def schedule_second_dose(self, event, op):
    op = OrderPosition.objects.select_related("item", "variation", "subevent",
                                              "order").get(pk=op)

    if LinkedOrderPosition.objects.filter(base_position=op).exists():
        return

    itemconf = op.item.vacc_autosched_config
    earliest_date = make_aware(
        datetime.combine(
            op.subevent.date_from.astimezone(event.timezone).date() +
            timedelta(days=itemconf.days),
            op.subevent.date_from.astimezone(event.timezone).time(),
        ),
        event.timezone,
    )

    target_event = itemconf.event or event
    possible_items = [
        n for n in target_event.items.all()
        if (n.internal_name or str(n.name)) == (
            op.item.internal_name or str(op.item.name))
    ]
    if len(possible_items) != 1:
        op.order.log_action(
            "pretix_vacc_autosched.failed",
            data={
                "reason": _("No product found"),
                "position": op.pk,
            },
        )
        return
    target_item = possible_items[0]

    if op.variation or target_item.variations.exists():
        possible_variations = [
            n for n in target_item.variations.all() if str(n.value) == (
                str(op.variation.value) if op.variation else None)
        ]
        if len(possible_variations) != 1:
            op.order.log_action(
                "pretix_vacc_autosched.failed",
                data={
                    "reason": _("No product variation found"),
                    "position": op.pk,
                },
            )
            return
        target_var = possible_variations[0]
    else:
        target_var = None

    for i in range(100):  # max number of subevents to check
        subevent = (target_event.subevents.filter(
            date_from__gte=earliest_date, ).order_by("date_from").first())
        if not subevent:
            op.order.log_action(
                "pretix_vacc_autosched.failed",
                data={
                    "reason": _("No available time slot found"),
                    "position": op.pk,
                },
            )
            return

        try:
            with target_event.lock(), transaction.atomic():
                avcode, avnr = target_item.check_quotas(subevent=subevent,
                                                        fail_on_no_quotas=True)
                if avcode != Quota.AVAILABILITY_OK:
                    # sold out, look for next one
                    earliest_date += timedelta(minutes=1)
                    continue

                childorder = Order.objects.create(
                    event=target_event,
                    status=Order.STATUS_PAID,
                    require_approval=False,
                    testmode=op.order.testmode,
                    email=op.order.email,
                    locale=op.order.locale,
                    expires=now() + timedelta(days=30),
                    total=Decimal("0.00"),
                    expiry_reminder_sent=True,
                    sales_channel=op.order.sales_channel,
                    comment="Auto-generated through scheduling from order {}".
                    format(op.order.code),
                    meta_info=op.order.meta_info,
                )
                op.order.log_action(
                    "pretix_vacc_autosched.scheduled",
                    data={
                        "position": op.pk,
                        "event": target_event.pk,
                        "event_slug": target_event.slug,
                        "order": childorder.code,
                    },
                )
                childorder.log_action(
                    "pretix_vacc_autosched.created",
                    data={
                        "event": event.pk,
                        "event_slug": event.slug,
                        "order": op.order.code,
                    },
                )
                childorder.log_action("pretix.event.order.placed",
                                      data={"source": "vacc_autosched"})
                childpos = childorder.positions.create(
                    positionid=1,
                    tax_rate=Decimal("0.00"),
                    tax_rule=None,
                    tax_value=Decimal("0.00"),
                    subevent=subevent,
                    item=target_item,
                    variation=target_var,
                    price=Decimal("0.00"),
                    attendee_name_cached=op.attendee_name_cached,
                    attendee_name_parts=op.attendee_name_parts,
                    attendee_email=op.attendee_email,
                    company=op.company,
                    street=op.street,
                    zipcode=op.zipcode,
                    city=op.city,
                    country=op.country,
                    state=op.state,
                    addon_to=None,
                    voucher=None,
                    meta_info=op.meta_info,
                )
                for answ in op.answers.all():
                    q = childorder.event.questions.filter(
                        identifier=answ.question.identifier).first()
                    if not q:
                        continue
                    childansw = childpos.answers.create(question=q,
                                                        answer=answ.answer,
                                                        file=answ.file)
                    if answ.options.all():
                        childopts = list(
                            q.options.filter(identifier__in=[
                                o.identifier for o in answ.options.all()
                            ]))
                        if childopts:
                            childansw.options.add(*childopts)

                LinkedOrderPosition.objects.create(base_position=op,
                                                   child_position=childpos)
            order_placed.send(event, order=childorder)
            order_paid.send(event, order=childorder)

            if event.settings.vacc_autosched_mail:
                with language(childorder.locale, target_event.settings.region):
                    email_template = event.settings.vacc_autosched_body
                    email_subject = str(event.settings.vacc_autosched_subject)

                    email_context = get_email_context(event=childorder.event,
                                                      order=childorder)
                    email_context["scheduled_datetime"] = date_format(
                        subevent.date_from.astimezone(event.timezone),
                        "SHORT_DATETIME_FORMAT",
                    )
                    try:
                        childorder.send_mail(
                            email_subject,
                            email_template,
                            email_context,
                            "pretix.event.order.email.order_placed",
                            attach_tickets=True,
                            attach_ical=target_event.settings.mail_attach_ical,
                        )
                    except SendMailException:
                        logger.exception(
                            "Order approved email could not be sent")

        except LockTimeoutException:
            self.retry()

        return

    op.order.log_action(
        "pretix_vacc_autosched.failed",
        data={
            "reason": _("No available time slot found"),
            "position": op.pk,
        },
    )
    return
예제 #14
0
def book_second_dose(*, op, item, variation, subevent, original_event):
    event = item.event
    with event.lock(), transaction.atomic():
        avcode, avnr = item.check_quotas(subevent=subevent,
                                         fail_on_no_quotas=True)
        if avcode != Quota.AVAILABILITY_OK:
            logger.info(
                f"SECOND DOSE: cannot use slot {subevent.pk}, sold out")
            # sold out, look for next one
            return

        childorder = Order.objects.create(
            event=event,
            status=Order.STATUS_PAID,
            require_approval=False,
            testmode=op.order.testmode,
            email=op.order.email,
            phone=op.order.phone,
            locale=op.order.locale,
            expires=now() + timedelta(days=30),
            total=Decimal("0.00"),
            expiry_reminder_sent=True,
            sales_channel=op.order.sales_channel,
            comment="Auto-generated through scheduling from order {}".format(
                op.order.code),
            meta_info=op.order.meta_info,
        )
        op.order.log_action(
            "pretix_vacc_autosched.scheduled",
            data={
                "position": op.pk,
                "event": event.pk,
                "event_slug": event.slug,
                "order": childorder.code,
            },
        )
        childorder.log_action(
            "pretix_vacc_autosched.created",
            data={
                "event": original_event.pk,
                "event_slug": original_event.slug,
                "order": op.order.code,
            },
        )
        childorder.log_action("pretix.event.order.placed",
                              data={"source": "vacc_autosched"})
        childpos = childorder.positions.create(
            positionid=1,
            tax_rate=Decimal("0.00"),
            tax_rule=None,
            tax_value=Decimal("0.00"),
            subevent=subevent,
            item=item,
            variation=variation,
            price=Decimal("0.00"),
            attendee_name_cached=op.attendee_name_cached,
            attendee_name_parts=op.attendee_name_parts,
            attendee_email=op.attendee_email,
            company=op.company,
            street=op.street,
            zipcode=op.zipcode,
            city=op.city,
            country=op.country,
            state=op.state,
            addon_to=None,
            voucher=None,
            meta_info=op.meta_info,
        )
        for answ in op.answers.all():
            q = childorder.event.questions.filter(
                identifier=answ.question.identifier).first()
            if not q:
                continue
            childansw = childpos.answers.create(question=q,
                                                answer=answ.answer,
                                                file=answ.file)
            if answ.options.all():
                childopts = list(
                    q.options.filter(identifier__in=[
                        o.identifier for o in answ.options.all()
                    ]))
                if childopts:
                    childansw.options.add(*childopts)

        LinkedOrderPosition.objects.create(base_position=op,
                                           child_position=childpos)
        childorder.create_transactions(is_new=True)
    order_placed.send(event, order=childorder)
    order_paid.send(event, order=childorder)

    if original_event.settings.vacc_autosched_mail:
        with language(childorder.locale, original_event.settings.region):
            email_template = original_event.settings.vacc_autosched_body
            email_subject = str(original_event.settings.vacc_autosched_subject)

            email_context = get_email_context(event=childorder.event,
                                              order=childorder)
            email_context["scheduled_datetime"] = date_format(
                subevent.date_from.astimezone(original_event.timezone),
                "SHORT_DATETIME_FORMAT",
            )
            try:
                childorder.send_mail(
                    email_subject,
                    email_template,
                    email_context,
                    "pretix.event.order.email.order_placed",
                    attach_tickets=True,
                    attach_ical=event.settings.mail_attach_ical,
                )
            except SendMailException:
                logger.exception("Order approved email could not be sent")
    if (original_event.settings.vacc_autosched_sms
            and can_use_juvare_api(original_event) and childorder.phone):
        with language(childorder.locale, original_event.settings.region):
            from pretix_juvare_notify.tasks import juvare_send_text

            template = original_event.settings.vacc_autosched_sms_text
            context = get_email_context(event=childorder.event,
                                        order=childorder)
            context["scheduled_datetime"] = date_format(
                subevent.date_from.astimezone(original_event.timezone),
                "SHORT_DATETIME_FORMAT",
            )
            message = str(template).format_map(TolerantDict(context))
            juvare_send_text.apply_async(
                kwargs={
                    "text": message,
                    "to": childorder.phone,
                    "event": original_event.pk,
                })
    logger.info(f"SECOND DOSE: done, created order {childorder.code}")
    return childorder