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)
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)
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)
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)
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)
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)
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, )
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)
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)
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)
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", }, )
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", }, )
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", }, )
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", }, )
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", }, )
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", }, )
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()
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", }, )
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", }, )
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")
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"}, )
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", }, )
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)
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", }, )
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()
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)
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)), )
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", }, )
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", }, )
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)
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)
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.")
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()))
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)
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)
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)
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)
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)
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()
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) )
def test_upcoming_invoice_error(self, invoice_upcoming_mock): with self.assertRaises(InvalidRequestError): Invoice.upcoming()
def test_no_upcoming_invoices(self, invoice_upcoming_mock): invoice = Invoice.upcoming() self.assertIsNone(invoice)