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)
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, })