Example #1
0
    def test_sync_from_stripe_data(self):
        invoice = Invoice.sync_from_stripe_data(FAKE_INVOICE)

        self.assertEqual("in_xxxxxxxxxxxxxxx", invoice.stripe_id)
        self.assertEqual(False, invoice.attempted)
        self.assertEqual(False, invoice.closed)
        self.assertEqual(False, invoice.paid)
        self.assertEqual(Decimal("9.95"), invoice.subtotal)
        self.assertEqual(Decimal("9.95"), invoice.total)
        self.assertEqual("", invoice.charge)

        self.assertEqual(1, invoice.items.count())
        invoice_item = invoice.items.all()[0]

        self.assertEqual("sub_xxxxxxxxxxxxxxx", invoice_item.stripe_id)
        self.assertEqual(Decimal("9.95"), invoice_item.amount)
        self.assertEqual("usd", invoice_item.currency)
        self.assertEqual(False, invoice_item.proration)
        self.assertEqual("", invoice_item.description)
        self.assertEqual("subscription", invoice_item.line_type)
        self.assertEqual("test", invoice_item.plan)
        self.assertEqual(1, invoice_item.quantity)

        # period_end is determined by latest invoice_item
        self.assertEqual(invoice_item.period_end, invoice.period_end)

        # Update invoice
        Invoice.sync_from_stripe_data(FAKE_INVOICE)
Example #2
0
    def test_handle_event_payment_failed(self, invoice_retrieve_mock, sync_invoice_mock):
        fake_event = Event(kind="invoice.payment_failed", validated_message={"data": {"object": {"id": "door"}}})

        Invoice.handle_event(fake_event)

        invoice_retrieve_mock.assert_called_once_with("door")
        sync_invoice_mock.assert_called_once_with("lock", send_receipt=True)
Example #3
0
    def test_sync_from_stripe_data(self):
        invoice = Invoice.sync_from_stripe_data(FAKE_INVOICE)

        self.assertEqual("in_xxxxxxxxxxxxxxx", invoice.stripe_id)
        self.assertEqual(False, invoice.attempted)
        self.assertEqual(False, invoice.closed)
        self.assertEqual(False, invoice.paid)
        self.assertEqual(Decimal("9.95"), invoice.subtotal)
        self.assertEqual(Decimal("9.95"), invoice.total)
        self.assertEqual("", invoice.charge)

        self.assertEqual(1, invoice.items.count())
        invoice_item = invoice.items.all()[0]

        self.assertEqual("sub_xxxxxxxxxxxxxxx", invoice_item.stripe_id)
        self.assertEqual(Decimal("9.95"), invoice_item.amount)
        self.assertEqual("usd", invoice_item.currency)
        self.assertEqual(False, invoice_item.proration)
        self.assertEqual("", invoice_item.description)
        self.assertEqual("subscription", invoice_item.line_type)
        self.assertEqual("test", invoice_item.plan)
        self.assertEqual(1, invoice_item.quantity)

        # period_end is determined by latest invoice_item
        self.assertEqual(invoice_item.period_end, invoice.period_end)

        # Update invoice
        Invoice.sync_from_stripe_data(FAKE_INVOICE)
Example #4
0
    def test_handle_event_payment_succeeded(self, invoice_retrieve_mock, sync_invoice_mock):
        fake_event = Event(kind="invoice.payment_succeeded", validated_message={"data": {"object": {"id": "lock"}}})

        Invoice.webhook_handler(fake_event, fake_event.message["data"], "invoice", "payment_failed")

        invoice_retrieve_mock.assert_called_once_with("lock")
        sync_invoice_mock.assert_called_once_with("key", send_receipt=True)
Example #5
0
    def test___str__(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account
        # TODO - remove invoice sync
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        fake_refund = deepcopy(FAKE_REFUND)
        fake_refund["reason"] = enums.RefundReason.requested_by_customer

        balance_transaction_retrieve_mock.return_value = deepcopy(
            FAKE_BALANCE_TRANSACTION_REFUND)

        refund = Refund.sync_from_stripe_data(fake_refund)

        self.assertEqual(str(refund), "$20.00 USD (Succeeded)")

        self.assert_fks(refund,
                        expected_blank_fks=self.default_expected_blank_fks)
Example #6
0
    def test_upcoming_invoice_with_subscription_plan(
        self,
        product_retrieve_mock,
        invoice_upcoming_mock,
        subscription_retrieve_mock,
        plan_retrieve_mock,
        invoice_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        balance_transaction_retrieve_mock,
    ):
        # create invoice for latest_invoice in subscription to work.
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        invoice = Invoice.upcoming(subscription_plan=Plan(id=FAKE_PLAN["id"]))
        self.assertIsNotNone(invoice)
        self.assertIsNone(invoice.id)
        self.assertIsNone(invoice.save())

        subscription_retrieve_mock.assert_called_once_with(
            api_key=ANY,
            expand=ANY,
            id=FAKE_SUBSCRIPTION["id"],
            stripe_account=None)
        plan_retrieve_mock.assert_not_called()

        self.assertIsNotNone(invoice.plan)
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)
Example #7
0
    def test_handle_event_fake(self, invoice_retrieve_mock, sync_invoice_mock):
        fake_event = Event(kind="fake", message={"data": {"object": {"id": "door"}}})

        Invoice.handle_event(fake_event)

        self.assertFalse(invoice_retrieve_mock.called)
        self.assertFalse(sync_invoice_mock.called)
Example #8
0
    def test_upcoming_invoice(
        self,
        product_retrieve_mock,
        invoice_upcoming_mock,
        subscription_retrieve_mock,
        plan_retrieve_mock,
        invoice_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        balance_transaction_retrieve_mock,
    ):
        # create invoice for latest_invoice in subscription to work.
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        invoice = UpcomingInvoice.upcoming()
        self.assertIsNotNone(invoice)
        self.assertIsNone(invoice.id)
        self.assertIsNone(invoice.save())
        self.assertEqual(invoice.get_stripe_dashboard_url(), "")

        invoice.id = "foo"
        self.assertIsNone(invoice.id)

        subscription_retrieve_mock.assert_called_once_with(
            api_key=ANY,
            expand=ANY,
            id=FAKE_SUBSCRIPTION["id"],
            stripe_account=None)
        plan_retrieve_mock.assert_not_called()

        items = invoice.invoiceitems.all()
        self.assertEqual(1, len(items))
        self.assertEqual(FAKE_SUBSCRIPTION["id"], items[0].id)

        # delete/update should do nothing
        self.assertEqual(invoice.invoiceitems.update(), 0)
        self.assertEqual(invoice.invoiceitems.delete(), 0)

        self.assertIsNotNone(invoice.plan)
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)

        invoice._invoiceitems = []
        items = invoice.invoiceitems.all()
        self.assertEqual(0, len(items))
        self.assertIsNotNone(invoice.plan)

        self.assertEqual(invoice.default_tax_rates.count(), 1)
        self.assertEqual(invoice.default_tax_rates.first().id,
                         FAKE_TAX_RATE_EXAMPLE_1_VAT["id"])

        self.assertEqual(invoice.total_tax_amounts.count(), 1)

        first_tax_amount = invoice.total_tax_amounts.first()
        self.assertEqual(first_tax_amount.tax_rate.id,
                         FAKE_TAX_RATE_EXAMPLE_1_VAT["id"])
        self.assertEqual(first_tax_amount.inclusive,
                         FAKE_TAX_RATE_EXAMPLE_1_VAT["inclusive"])
        self.assertEqual(first_tax_amount.amount, 261)
    def test_sync_proration(
        self,
        invoice_retrieve_mock,
        charge_retrieve_mock,
        customer_retrieve_mock,
        paymentintent_retrieve_mock,
        paymentmethod_retrieve_mock,
        subscription_retrieve_mock,
        product_retrieve_mock,
        plan_retrieve_mock,
        price_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        fake_payment_intent = deepcopy(FAKE_PAYMENT_INTENT_II)
        fake_payment_intent["invoice"] = FAKE_INVOICE_II["id"]
        paymentintent_retrieve_mock.return_value = fake_payment_intent

        fake_subscription = deepcopy(FAKE_SUBSCRIPTION_III)
        fake_subscription["latest_invoice"] = FAKE_INVOICE_II["id"]
        subscription_retrieve_mock.return_value = fake_subscription

        fake_card = deepcopy(FAKE_CARD_II)
        fake_card["customer"] = None
        # create Card for FAKE_CUSTOMER_III
        Card.sync_from_stripe_data(fake_card)

        # create invoice
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE_II))

        default_account_mock.return_value = self.account

        invoiceitem_data = deepcopy(FAKE_INVOICEITEM)
        invoiceitem_data.update({
            "proration": True,
            "plan": FAKE_PLAN_II["id"],
            "price": FAKE_PRICE_II["id"],
        })
        invoiceitem = InvoiceItem.sync_from_stripe_data(invoiceitem_data)

        self.assertEqual(FAKE_PLAN_II["id"], invoiceitem.plan.id)
        self.assertEqual(FAKE_PRICE_II["id"], invoiceitem.price.id)

        expected_blank_fks = self.default_expected_blank_fks | {
            "djstripe.InvoiceItem.subscription"
        }
        expected_blank_fks.difference_update({
            "djstripe.PaymentIntent.invoice (related name)",
            "djstripe.Invoice.payment_intent",
        })

        self.assert_fks(
            invoiceitem,
            expected_blank_fks=expected_blank_fks,
        )
Example #10
0
    def test_handle_event_fake(self, invoice_retrieve_mock, sync_invoice_mock):
        fake_event = Event(kind="fake",
                           message={"data": {
                               "object": {
                                   "id": "door"
                               }
                           }})

        Invoice.handle_event(fake_event)

        self.assertFalse(invoice_retrieve_mock.called)
        self.assertFalse(sync_invoice_mock.called)
Example #11
0
    def test_sync_from_stripe_data_with_charge_no_receipt(self, record_charge_mock, send_receipt_mock):
        record_charge_mock.return_value = Charge(customer=self.customer)

        FAKE_INVOICE_WITH_CHARGE = deepcopy(FAKE_INVOICE)
        FAKE_INVOICE_WITH_CHARGE["id"] = "in_zzzzzzzzzzzzzzz1"
        FAKE_INVOICE_WITH_CHARGE["subscription"] = "sub_zzzzzzzzzzzzzzz1"
        FAKE_INVOICE_WITH_CHARGE["lines"]["data"][0]["id"] = "sub_zzzzzzzzzzzzzzz1"

        FAKE_INVOICE_WITH_CHARGE["charge"] = "taco1"

        Invoice.sync_from_stripe_data(FAKE_INVOICE_WITH_CHARGE, send_receipt=False)
        record_charge_mock.assert_called_once_with("taco1")
        self.assertFalse(send_receipt_mock.called)
Example #12
0
    def test_sync_from_stripe_data_with_charge_no_receipt(self, record_charge_mock, send_receipt_mock):
        record_charge_mock.return_value = Charge(customer=self.customer)

        FAKE_INVOICE_WITH_CHARGE = deepcopy(FAKE_INVOICE)
        FAKE_INVOICE_WITH_CHARGE["id"] = "in_zzzzzzzzzzzzzzz1"
        FAKE_INVOICE_WITH_CHARGE["subscription"] = "sub_zzzzzzzzzzzzzzz1"
        FAKE_INVOICE_WITH_CHARGE["lines"]["data"][0]["id"] = "sub_zzzzzzzzzzzzzzz1"

        FAKE_INVOICE_WITH_CHARGE["charge"] = "taco1"

        Invoice.sync_from_stripe_data(FAKE_INVOICE_WITH_CHARGE, send_receipt=False)
        record_charge_mock.assert_called_once_with("taco1")
        self.assertFalse(send_receipt_mock.called)
Example #13
0
    def test_handle_event_payment_succeeded(self, invoice_retrieve_mock,
                                            sync_invoice_mock):
        fake_event = Event(
            kind="invoice.payment_failed",
            validated_message={"data": {
                "object": {
                    "id": "lock"
                }
            }})

        Invoice.handle_event(fake_event)

        invoice_retrieve_mock.assert_called_once_with("lock")
        sync_invoice_mock.assert_called_once_with("key", send_receipt=True)
    def test___str__(
        self,
        invoice_retrieve_mock,
        charge_retrieve_mock,
        customer_retrieve_mock,
        paymentintent_retrieve_mock,
        paymentmethod_retrieve_mock,
        subscription_retrieve_mock,
        product_retrieve_mock,
        plan_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):

        fake_subscription = deepcopy(FAKE_SUBSCRIPTION_III)
        fake_subscription["latest_invoice"] = FAKE_INVOICE["id"]
        subscription_retrieve_mock.side_effect = [
            deepcopy(FAKE_SUBSCRIPTION),
            fake_subscription,
        ]

        fake_customer = deepcopy(FAKE_CUSTOMER_II)
        customer_retrieve_mock.side_effect = [
            deepcopy(FAKE_CUSTOMER), fake_customer
        ]

        fake_card = deepcopy(FAKE_CARD_II)
        fake_card["customer"] = None
        # create Card for FAKE_CUSTOMER_III
        Card.sync_from_stripe_data(fake_card)

        # create invoice for latest_invoice in subscription to work.
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        # create invoice
        Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE_II))

        default_account_mock.return_value = self.account

        invoiceitem_data = deepcopy(FAKE_INVOICEITEM)
        invoiceitem_data["plan"] = FAKE_PLAN_II
        invoiceitem_data["price"] = FAKE_PRICE_II
        invoiceitem = InvoiceItem.sync_from_stripe_data(invoiceitem_data)
        self.assertEqual(
            invoiceitem.get_stripe_dashboard_url(),
            invoiceitem.invoice.get_stripe_dashboard_url(),
        )

        assert str(invoiceitem) == invoiceitem.description
    def test_status_paid(self, charge_retrieve_mock,
                         subscription_retrieve_mock, default_account_mock):
        default_account_mock.return_value = self.account

        invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        self.assertEqual(Invoice.STATUS_PAID, invoice.status)
Example #16
0
    def test_retry_false(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        default_account_mock,
        invoice_retrieve_mock,
    ):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        self.assertFalse(invoice_retrieve_mock.called)
        self.assertFalse(return_value)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
            },
        )
Example #17
0
    def test_invoice_with_non_subscription_invoice_items(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"]["data"].append(deepcopy(FAKE_INVOICEITEM_II))
        invoice_data["lines"]["total_count"] += 1
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertIsNotNone(invoice)
        self.assertEqual(2, len(invoice.invoiceitems.all()))

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
            },
        )
Example #18
0
    def test_invoice_with_no_invoice_items(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"] = []
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertIsNotNone(invoice.plan)  # retrieved from invoice item
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
            },
        )
Example #19
0
    def test_retry_true(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        default_account_mock,
        invoice_retrieve_mock,
    ):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        fake_invoice.update({"paid": False, "closed": False})
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        invoice_retrieve_mock.assert_called_once_with(
            id=invoice.id, api_key=STRIPE_SECRET_KEY, expand=[])
        self.assertTrue(return_value)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
            },
        )
Example #20
0
    def test_invoice_plan_from_subscription(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"]["data"][0]["plan"] = None
        invoice = Invoice.sync_from_stripe_data(invoice_data)
        self.assertIsNotNone(invoice.plan)  # retrieved from subscription
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.branding_logo",
                "djstripe.Account.branding_icon",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
                "djstripe.PaymentIntent.on_behalf_of",
                "djstripe.PaymentIntent.payment_method",
                "djstripe.Subscription.pending_setup_intent",
            },
        )
Example #21
0
    def test_status_forgiven(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data.update({"paid": False, "closed": False, "forgiven": True})
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertEqual(Invoice.STATUS_FORGIVEN, invoice.status)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.branding_logo",
                "djstripe.Account.branding_icon",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
                "djstripe.PaymentIntent.on_behalf_of",
                "djstripe.PaymentIntent.payment_method",
                "djstripe.Subscription.pending_setup_intent",
            },
        )
Example #22
0
    def test_billing_reason_enum(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account
        fake_invoice = deepcopy(FAKE_INVOICE)

        for billing_reason in (
            "subscription_cycle",
            "subscription_create",
            "subscription_update",
            "subscription",
            "manual",
            "upcoming",
            "subscription_threshold",
        ):
            fake_invoice["billing_reason"] = billing_reason

            invoice = Invoice.sync_from_stripe_data(fake_invoice)
            self.assertEqual(invoice.billing_reason, billing_reason)

            # trigger model field validation (including enum value choices check)
            invoice.full_clean()
Example #23
0
	def test_invoice_without_plan(
		self,
		charge_retrieve_mock,
		subscription_retrieve_mock,
		balance_transaction_retrieve_mock,
		default_account_mock,
	):
		default_account_mock.return_value = self.account

		invoice_data = deepcopy(FAKE_INVOICE)
		invoice_data["lines"]["data"][0]["plan"] = None
		invoice_data["subscription"] = None
		invoice = Invoice.sync_from_stripe_data(invoice_data)
		self.assertIsNone(invoice.plan)

		self.assert_fks(
			invoice,
			expected_blank_fks={
				"djstripe.Account.business_logo",
				"djstripe.Charge.dispute",
				"djstripe.Charge.transfer",
				"djstripe.Customer.coupon",
				"djstripe.Invoice.subscription",
				"djstripe.Plan.product",
			},
		)
Example #24
0
	def test_status_closed(
		self,
		product_retrieve_mock,
		charge_retrieve_mock,
		subscription_retrieve_mock,
		balance_transaction_retrieve_mock,
		default_account_mock,
	):
		default_account_mock.return_value = self.account

		invoice_data = deepcopy(FAKE_INVOICE)
		invoice_data.update({"paid": False})
		invoice = Invoice.sync_from_stripe_data(invoice_data)

		self.assertEqual(Invoice.STATUS_CLOSED, invoice.status)

		self.assert_fks(
			invoice,
			expected_blank_fks={
				"djstripe.Account.business_logo",
				"djstripe.Charge.dispute",
				"djstripe.Charge.transfer",
				"djstripe.Customer.coupon",
			},
		)
Example #25
0
    def test_retry_true(
        self,
        product_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
        invoice_retrieve_mock,
    ):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        fake_invoice.update({"paid": False, "closed": False})
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        invoice_retrieve_mock.assert_called_once_with(
            id=invoice.id, api_key=STRIPE_SECRET_KEY, expand=[], stripe_account=None
        )
        self.assertTrue(return_value)

        self.assert_fks(invoice, expected_blank_fks=self.default_expected_blank_fks)
 def test_str(self, charge_retrieve_mock, subscription_retrive_mock,
              default_account_mock):
     default_account_mock.return_value = self.account
     invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))
     self.assertEqual(invoice.get_stripe_dashboard_url(),
                      self.customer.get_stripe_dashboard_url())
     self.assertEqual(str(invoice), "Invoice #XXXXXXX-0001")
Example #27
0
    def test_sync_no_subscription(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        plan_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data.update({"subscription": None})
        invoice_data["lines"]["data"][0]["subscription"] = None
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertEqual(None, invoice.subscription)

        self.assertEqual(FAKE_CHARGE["id"], invoice.charge.id)
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)

        # charge_retrieve_mock.assert_not_called()
        plan_retrieve_mock.assert_not_called()
        subscription_retrieve_mock.assert_not_called()

        self.assert_fks(
            invoice,
            expected_blank_fks=self.default_expected_blank_fks
            | {"djstripe.Invoice.subscription"},
        )
Example #28
0
 def test_sync_from_stripe_data(
     self,
     product_retrieve_mock,
     payment_intent_retrieve_mock,
     charge_retrieve_mock,
     subscription_retrieve_mock,
     balance_transaction_retrieve_mock,
     default_account_mock,
 ):
     default_account_mock.return_value = self.account
     invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))
     self.assertEqual(
         invoice.get_stripe_dashboard_url(), self.customer.get_stripe_dashboard_url()
     )
     self.assertEqual(str(invoice), "Invoice #{}".format(FAKE_INVOICE["number"]))
     self.assertGreater(len(invoice.status_transitions.keys()), 1)
     self.assert_fks(
         invoice,
         expected_blank_fks={
             "djstripe.Account.branding_logo",
             "djstripe.Account.branding_icon",
             "djstripe.Charge.dispute",
             "djstripe.Charge.transfer",
             "djstripe.Customer.coupon",
             "djstripe.PaymentIntent.on_behalf_of",
             "djstripe.PaymentIntent.payment_method",
             "djstripe.Subscription.pending_setup_intent",
         },
     )
Example #29
0
    def test_invoice_with_subscription_invoice_items(
        self,
        product_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        items = invoice.invoiceitems.all()
        self.assertEqual(1, len(items))

        # Previously the test asserted item_id="{invoice_id}-{subscription_id}",
        # but this doesn't match what I'm seeing from Stripe
        # I'm not sure if it's possible to predict the whole item id now,
        # sli seems to not reference anything
        item_id_prefix = "{invoice_id}-sli_".format(invoice_id=invoice.id)
        self.assertTrue(items[0].id.startswith(item_id_prefix))
        self.assertEqual(items[0].subscription.id, FAKE_SUBSCRIPTION["id"])

        self.assert_fks(invoice, expected_blank_fks=self.default_expected_blank_fks)
Example #30
0
    def test_retry_false(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
        invoice_retrieve_mock,
    ):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        self.assertFalse(invoice_retrieve_mock.called)
        self.assertFalse(return_value)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.branding_logo",
                "djstripe.Account.branding_icon",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
                "djstripe.PaymentIntent.on_behalf_of",
                "djstripe.PaymentIntent.payment_method",
                "djstripe.Subscription.pending_setup_intent",
            },
        )
Example #31
0
    def test_invoice_status_enum(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account
        fake_invoice = deepcopy(FAKE_INVOICE)

        for status in (
            "draft",
            "open",
            "paid",
            "uncollectible",
            "void",
        ):
            fake_invoice["status"] = status

            invoice = Invoice.sync_from_stripe_data(fake_invoice)
            self.assertEqual(invoice.status, status)

            # trigger model field validation (including enum value choices check)
            invoice.full_clean()
Example #32
0
    def test_sync_from_stripe_data(
        self,
        product_retrieve_mock,
        payment_intent_retrieve_mock,
        paymentmethod_card_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        balance_transaction_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account
        invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))
        self.assertEqual(
            invoice.get_stripe_dashboard_url(), self.customer.get_stripe_dashboard_url()
        )
        self.assertEqual(str(invoice), "Invoice #{}".format(FAKE_INVOICE["number"]))
        self.assertGreater(len(invoice.status_transitions.keys()), 1)
        self.assertTrue(bool(invoice.account_country))
        self.assertTrue(bool(invoice.account_name))
        self.assertTrue(bool(invoice.collection_method))

        with self.assertWarns(DeprecationWarning):
            self.assertEqual(invoice.billing, invoice.collection_method)

        self.assert_fks(invoice, expected_blank_fks=self.default_expected_blank_fks)
Example #33
0
    def action_create_draft_invoice(self, request, queryset):
        """Create a draft invoice for this customer with metadata attached."""
        if not settings.STRIPE_ENABLED:
            messages.add_message(
                request,
                messages.ERROR,
                _("Stripe is not configured. Please set the envvar STRIPE_SECRET_KEY."
                  ),
            )
            return

        flight_start = timezone.now()
        flight_end = flight_start + timedelta(days=30)

        for advertiser in queryset:
            if advertiser.djstripe_customer:
                # Amounts, prices, and description can be customized before sending
                stripe.InvoiceItem.create(
                    customer=advertiser.djstripe_customer.id,
                    description="Advertising - per 1k impressions",
                    quantity=200,
                    unit_amount=300,  # in US cents
                    currency="USD",
                )

                # https://stripe.com/docs/api/invoices/create
                inv = stripe.Invoice.create(
                    customer=advertiser.djstripe_customer.id,
                    auto_advance=False,  # Draft invoice
                    collection_method="send_invoice",
                    custom_fields=[
                        {
                            "name": "Advertiser",
                            "value": advertiser.slug
                        },
                        {
                            "name": "Estimated Start",
                            "value": flight_start.strftime("%Y-%m-%d"),
                        },
                        {
                            "name": "Estimated End",
                            "value": flight_end.strftime("%Y-%m-%d"),
                        },
                    ],
                    days_until_due=30,
                )
                invoice = Invoice.sync_from_stripe_data(inv)

                messages.add_message(
                    request,
                    messages.SUCCESS,
                    _("New Stripe invoice for {}: {}".format(
                        advertiser, invoice.get_stripe_dashboard_url())),
                )
            else:
                messages.add_message(
                    request,
                    messages.ERROR,
                    _("No Stripe customer ID for {}".format(advertiser)),
                )
Example #34
0
    def test_sync_no_subscription(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        plan_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data.update({"subscription": None})
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertEqual(None, invoice.subscription)

        self.assertEqual(FAKE_CHARGE["id"], invoice.charge.id)
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)

        # charge_retrieve_mock.assert_not_called()
        plan_retrieve_mock.assert_not_called()
        subscription_retrieve_mock.assert_not_called()

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
                "djstripe.Invoice.subscription",
            },
        )
Example #35
0
    def test_invoice_with_subscription_invoice_items(
        self,
        product_retrieve_mock,
        charge_retrieve_mock,
        subscription_retrieve_mock,
        default_account_mock,
    ):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        items = invoice.invoiceitems.all()
        self.assertEqual(1, len(items))
        item_id = "{invoice_id}-{subscription_id}".format(
            invoice_id=invoice.id, subscription_id=FAKE_SUBSCRIPTION["id"])
        self.assertEqual(item_id, items[0].id)

        self.assert_fks(
            invoice,
            expected_blank_fks={
                "djstripe.Account.business_logo",
                "djstripe.Charge.dispute",
                "djstripe.Charge.transfer",
                "djstripe.Customer.coupon",
            },
        )
Example #36
0
    def test_status_open(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data.update({"paid": False, "closed": False})
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertEqual(Invoice.STATUS_OPEN, invoice.status)
Example #37
0
    def test_invoice_without_plan(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"]["data"][0]["plan"] = None
        invoice_data["subscription"] = None
        invoice = Invoice.sync_from_stripe_data(invoice_data)
        self.assertIsNone(invoice.plan)
Example #38
0
    def test_invoice_plan_from_subscription(self, charge_retrieve_mock, subscription_retrieve_mock,
                                            default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"]["data"][0]["plan"] = None
        invoice = Invoice.sync_from_stripe_data(invoice_data)
        self.assertIsNotNone(invoice.plan)  # retrieved from subscription
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.stripe_id)
def sync_invoices(apps, schema_editor):
    # This is okay, since we're only doing a forward migration.
    from djstripe.models import Invoice

    from djstripe.context_managers import stripe_temporary_api_version

    with stripe_temporary_api_version("2016-03-07"):
        if Invoice.objects.count():
            print("syncing invoices. This may take a while.")

            for invoice in tqdm(iterable=Invoice.objects.all(), desc="Sync", unit=" invoices"):
                try:
                    Invoice.sync_from_stripe_data(invoice.api_retrieve())
                except InvalidRequestError:
                    tqdm.write("There was an error while syncing invoice \
                    ({invoice_id}).".format(invoice_id=invoice.stripe_id))

            print("Invoice sync complete.")
Example #40
0
    def test_invoice_with_non_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock,
                                                         default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data["lines"]["data"].append(deepcopy(FAKE_INVOICEITEM_II))
        invoice_data["lines"]["total_count"] += 1
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertIsNotNone(invoice)
        self.assertEqual(2, len(invoice.invoiceitems.all()))
Example #41
0
    def test_retry_false(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock,
                         invoice_retrieve_mock):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        self.assertFalse(invoice_retrieve_mock.called)
        self.assertFalse(return_value)
Example #42
0
    def test_upcoming_invoice_with_subscription_plan(self, invoice_upcoming_mock, subscription_retrieve_mock,
                                                     plan_retrieve_mock):
        invoice = Invoice.upcoming(subscription_plan=Plan(stripe_id=FAKE_PLAN["id"]))
        self.assertIsNotNone(invoice)
        self.assertIsNone(invoice.stripe_id)
        self.assertIsNone(invoice.save())

        subscription_retrieve_mock.assert_called_once_with(api_key=ANY, expand=ANY, id=FAKE_SUBSCRIPTION["id"])
        plan_retrieve_mock.assert_not_called()

        self.assertIsNotNone(invoice.plan)
        self.assertEqual(FAKE_PLAN["id"], invoice.plan.stripe_id)
Example #43
0
    def test_invoice_with_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock,
                                                     default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        items = invoice.invoiceitems.all()
        self.assertEqual(1, len(items))
        item_id = "{invoice_id}-{subscription_id}".format(invoice_id=invoice.stripe_id,
                                                          subscription_id=FAKE_SUBSCRIPTION["id"])
        self.assertEqual(item_id, items[0].stripe_id)
Example #44
0
    def test_sync_from_stripe_data_no_plan(self):
        FAKE_INVOICE_NO_PLAN = deepcopy(FAKE_INVOICE)
        FAKE_INVOICE_NO_PLAN["id"] = "in_yyyyyyyyyyyyyyy"
        FAKE_INVOICE_NO_PLAN["subscription"] = "sub_yyyyyyyyyyyyyyy"
        FAKE_INVOICE_NO_PLAN["lines"]["data"][0]["id"] = "sub_yyyyyyyyyyyyyyy"

        FAKE_INVOICE_NO_PLAN["lines"]["data"][0]["plan"] = None

        invoice = Invoice.sync_from_stripe_data(FAKE_INVOICE_NO_PLAN)
        self.assertEqual(1, invoice.items.count())
        invoice_item = invoice.items.all()[0]

        self.assertEqual("", invoice_item.plan)
Example #45
0
    def test_retry_true(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock,
                        invoice_retrieve_mock):
        default_account_mock.return_value = self.account

        fake_invoice = deepcopy(FAKE_INVOICE)
        fake_invoice.update({"paid": False, "closed": False})
        invoice_retrieve_mock.return_value = fake_invoice

        invoice = Invoice.sync_from_stripe_data(fake_invoice)
        return_value = invoice.retry()

        invoice_retrieve_mock.assert_called_once_with(id=invoice.stripe_id, api_key=settings.STRIPE_SECRET_KEY,
                                                      expand=None)
        self.assertTrue(return_value)
Example #46
0
    def test_sync_no_subscription(self, charge_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock,
                                  default_account_mock):
        default_account_mock.return_value = self.account

        invoice_data = deepcopy(FAKE_INVOICE)
        invoice_data.update({"subscription": None})
        invoice = Invoice.sync_from_stripe_data(invoice_data)

        self.assertEqual(None, invoice.subscription)

        charge_retrieve_mock.assert_called_once_with(api_key=ANY, expand=ANY, id=FAKE_CHARGE["id"])
        plan_retrieve_mock.assert_called_once_with(api_key=ANY, expand=ANY, id=FAKE_PLAN["id"])

        subscription_retrieve_mock.assert_not_called()
Example #47
0
    def test_str(self, charge_retrieve_mock, subscription_retrive_mock, default_account_mock):
        default_account_mock.return_value = self.account
        invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))
        self.assertEqual(invoice.get_stripe_dashboard_url(), self.customer.get_stripe_dashboard_url())

        self.assertEqual(
            "<amount_due={amount_due}, date={date}, status={status}, stripe_id={stripe_id}>".format(
                amount_due=invoice.amount_due,
                date=invoice.date,
                status=invoice.status,
                stripe_id=invoice.stripe_id
            ),
            str(invoice)
        )
Example #48
0
 def test_upcoming_invoice_error(self, invoice_upcoming_mock):
     with self.assertRaises(InvalidRequestError):
         Invoice.upcoming()
Example #49
0
    def test_status_paid(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock):
        default_account_mock.return_value = self.account

        invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE))

        self.assertEqual(Invoice.STATUS_PAID, invoice.status)
Example #50
0
 def test_no_upcoming_invoices(self, invoice_upcoming_mock):
     invoice = Invoice.upcoming()
     self.assertIsNone(invoice)