def get(self, request, *args, **kwargs):
        proforma_pk = kwargs.get('pk')

        try:
            proforma = Proforma.objects.get(pk=proforma_pk)
        except Proforma.DoesNotExist:
            return Response({"detail": "Proforma not found"},
                            status=status.HTTP_404_NOT_FOUND)

        serializer = InvoiceSerializer(proforma.related_document,
                                       context={'request': request})
        return Response(serializer.data)
    def put(self, request, *args, **kwargs):
        invoice_pk = kwargs.get('pk')
        try:
            invoice = Invoice.objects.get(pk=invoice_pk)
        except Invoice.DoesNotExist:
            return Response({"detail": "Invoice not found"},
                            status=status.HTTP_404_NOT_FOUND)

        state = request.data.get('state', None)
        if state == Invoice.STATES.ISSUED:
            if invoice.state != Invoice.STATES.DRAFT:
                msg = "An invoice can be issued only if it is in draft state."
                return Response({"detail": msg},
                                status=status.HTTP_403_FORBIDDEN)

            issue_date = request.data.get('issue_date', None)
            due_date = request.data.get('due_date', None)
            invoice.issue(issue_date, due_date)
        elif state == Invoice.STATES.PAID:
            if invoice.state != Invoice.STATES.ISSUED:
                msg = "An invoice can be paid only if it is in issued state."
                return Response({"detail": msg},
                                status=status.HTTP_403_FORBIDDEN)

            paid_date = request.data.get('paid_date', None)
            invoice.pay(paid_date)
        elif state == Invoice.STATES.CANCELED:
            if invoice.state != Invoice.STATES.ISSUED:
                msg = "An invoice can be canceled only if it is in issued " \
                      "state."
                return Response({"detail": msg},
                                status=status.HTTP_403_FORBIDDEN)

            cancel_date = request.data.get('cancel_date', None)
            invoice.cancel(cancel_date)
        elif not state:
            msg = "You have to provide a value for the state field."
            return Response({"detail": msg}, status=status.HTTP_403_FORBIDDEN)
        else:
            msg = "Illegal state value."
            return Response({"detail": msg}, status=status.HTTP_403_FORBIDDEN)

        serializer = InvoiceSerializer(invoice, context={'request': request})
        return Response(serializer.data)
Example #3
0
    def post(self, request, *args, **kwargs):
        """ Create a one off transaction by way of creating an invoice,
        payment method and document, and return the created transaction.
        """

        rq = request.data

        customer_one_off_defaults = {
            "currency": "USD",
        }

        ## Customer creation
        #
        # Check to see if we're getting an `account_id`, and try to
        # retrieve that customer first.
        #
        customer = None
        has_uuid = rq.get('customer', {}).get('account_id', False)

        if has_uuid:
            _u = uuid.UUID(has_uuid)
            # This will raise Customer.DoesNotExist if an invalid UUID is given
            customer = Customer.objects.get(account_id=_u)

        # If we have no customer and no exceptions were raised, create a
        # new customer
        #
        if customer == None:
            new_customer = customer_one_off_defaults
            new_customer.update(**rq.get('customer'))
            customer = Customer(**new_customer)
            customer.save()

        ## Create a customer payment method
        #
        payment_processor_name = rq.get("payment_processor", "manual")

        # Check if a method for the customer with this payment_processor
        # exists already
        #
        try:
            has_method = PaymentMethod.objects.get(
                customer=customer, payment_processor=payment_processor_name)
        except PaymentMethod.DoesNotExist:
            has_method = False

        # Create a new method
        #
        if not has_method:
            # TODO: what are our sensible defaults?
            customer_default_payment_method = {
                "customer":
                customer,
                "payment_processor":
                payment_processor_name,
                "verified":
                True,
                "canceled":
                False,
                "valid_until":
                dt.now() + timedelta(days=7),
                "display_info":
                "pytest",
                "data":
                json.dumps({
                    "attempt_retries_after": 2,
                    "stop_retry_attempts": 5
                })
            }
            new_pm = PaymentMethod(**customer_default_payment_method)
            new_pm.save()
        else:
            new_pm = has_method

        ## Get a provider

        # First we'll try to get our internal provider, otherwise create
        # it if it doesn't exist.
        #
        # TODO: add a request parameter for the provider name or
        # something.
        #
        provider = Provider.objects.filter(
            invoice_series="BPInvoiceSeries").first()
        if provider is None:
            prv = {
                "name": "Internal Billing Provider",
                "company": "Internal Billing Provider",
                "invoice_series": "BPInvoiceSeries",
                "flow": "invoice",
                "email": "",
                "address_1": "1 Mulberry Lane",
                "address_2": "",
                "city": "Pacoima",
                "state": "CA",
                "zip_code": "",
                "country": "US",
                "invoice_starting_number": 1
            }
            provider = Provider(**prv)
            provider.save()

        ## Create an invoice

        # Some defaults to save effort from the client user
        #
        invoice_one_off_defaults = {
            "provider": provider,
            "series": provider.invoice_series,
            "customer": customer,
            "transaction_currency": "USD",
            "transaction_xe_rate": Decimal('1.0000'),
            "currency": "USD",
            "state": "draft",
        }

        invoice_entry_defaults = {
            "quantity": 1.0,
            "unit_price": rq.get("amount", 0.0),
            "start_date": None,
            "end_date": None,
            "prorated": False,
            "product_code": None
        }

        # Override these with any request data
        #
        new_entry = invoice_entry_defaults.copy()
        new_invoice = invoice_one_off_defaults.copy()
        new_invoice.update(**rq.get("invoice", {}))
        if 'issue_date' in new_invoice:
            new_invoice['issue_date'] = dtparse(
                new_invoice.get('issue_date')).date()

        # Create the invoice
        inv = Invoice(**new_invoice)
        inv.save()

        # Add the entry (save first, or else)
        entr = DocumentEntry(**new_entry)
        entr.save()
        inv.invoice_entries.add(entr)
        inv.save()

        # Issue the invoice to generate transactions.
        inv.issue()
        inv.save()

        transaction = Transaction.objects.filter(invoice=inv).first()

        _ser_kwargs = {"context": {"request": request}}

        return Response({
            "customer":
            CustomerSerializer(customer, **_ser_kwargs).data,
            "payment_method":
            PaymentMethodSerializer(new_pm, **_ser_kwargs).data,
            "provider":
            ProviderSerializer(provider, **_ser_kwargs).data,
            "invoice":
            InvoiceSerializer(inv, **_ser_kwargs).data,
            "transaction":
            TransactionSerializer(transaction, **_ser_kwargs).data,
        })