Example #1
0
import factory

from bluebottle.utils.model_dispatcher import get_order_model
from bluebottle.utils.utils import StatusDefinition
from bluebottle.payments.models import OrderPaymentAction
from .accounts import BlueBottleUserFactory

ORDER_MODEL = get_order_model()


class OrderFactory(factory.DjangoModelFactory):
    FACTORY_FOR = ORDER_MODEL

    user = factory.SubFactory(BlueBottleUserFactory)
    status = StatusDefinition.CREATED


class OrderActionFactory(factory.DjangoModelFactory):
    FACTORY_FOR = OrderPaymentAction

Example #2
0
    def form_valid(self, form):
        with db_transaction.atomic():
            order = get_order_model().objects.create(
                user=self.request.user, order_type="manual", total=form.cleaned_data["amount"]
            )

            form.instance.order = order
            form.instance.anonymous = True
            self.object = donation = form.save()

            order_payment = OrderPayment.objects.create(
                user=self.request.user, order=order, amount=donation.amount, payment_method="manual"
            )
            payment = ManualPayment.objects.create(
                amount=donation.amount,
                transaction=self.transaction,
                user=self.request.user,
                order_payment=order_payment,
            )

            # pull us through the statuses to consider it done
            payment.status = StatusDefinition.AUTHORIZED
            payment.save()
            payment.status = StatusDefinition.SETTLED
            payment.save()

            # update/create the required payout
            ProjectPayout = get_project_payout_model()
            project = donation.project
            project.update_amounts()
            payouts = ProjectPayout.objects.filter(project=project)

            # check the payouts and only update 'new' payouts, else create a new payout
            if payouts.exists():
                updateable = payouts.filter(status=StatusDefinition.NEW).first()  # only new payouts can be updated
                if updateable is None:
                    rules = payouts.values_list("payout_rule", flat=True).distinct()
                    if len(rules) == 1:
                        rule = rules[0]
                        _message = messages.success
                        msg = _("Created a new project payout with payment rule {rule}")
                    else:
                        _message = messages.warning
                        msg = _("There were {n} payout rules, the choosen rule was: '{rule}'")

                    # create a new payout, since the other payouts are on their way for processing and can't be altered
                    payout = ProjectPayout(
                        planned=ProjectPayout.get_next_planned_date(), project=project, payout_rule=rule, protected=True
                    )

                    # we need to manually calculate the amounts, else all project donations will be taken into account
                    # FIXME: this needs to be refactored on the BB_PAYOUT level!
                    calculator = payout.get_calculator()
                    payout.calculate_payable_and_fee(calculator, donation.amount)
                    payout.save()
                    rule = dict(ProjectPayout.PayoutRules.choices)[rule]
                    _message(self.request, msg.format(n=len(rules), rule=rule))
                else:
                    # there is a payout that is still 'new', update that one
                    if updateable.protected is False:
                        updateable.calculate_amounts()
                    else:
                        # this is already an 'irregular' payout, so add the diff
                        # manually. There should be a journal entry for the modification
                        updateable.amount_raised += donation.amount
                        calculator = updateable.get_calculator()
                        updateable.calculate_payable_and_fee(calculator, updateable.get_amount_raised())
                        updateable.save()

                    messages.success(
                        self.request, _("Created a manual donation and updated project payout %r") % updateable
                    )

                # NOTE theoretically there is a situation where the only updateable
                # payout is a payout for an open project and the payout is protected
                # It would then theoretically be possible to make a new donation via
                # the web interface and the project payout will not be re-calculateable

            self.transaction.status = BankTransaction.IntegrityStatus.Valid
            self.transaction.save()

            # TODO FIXME: organization payouts?! recalculate?

        return redirect(self.get_success_url())