Skip to content

Commit

Permalink
Remove deprecated fields: Invoice.closed and Invoice.forgiven (dj-str…
Browse files Browse the repository at this point in the history
…ipe#1096)

Add Invoice.status and enums.InvoiceStatus

Fixes dj-stripe#1020
  • Loading branch information
PabloCastellano authored and therefromhere committed Jan 21, 2020
1 parent fcbe1f2 commit 891782a
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 251 deletions.
4 changes: 4 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ History
- Dropped support for Django 2.1 (#1056).
- Dropped support for python 3.5 (#1073).
- Fixed handling of ``TaxRate`` events (#1094).
- Dropped previously-deprecated ``Invoice`` fields (see https://stripe.com/docs/upgrades#2018-11-08 ):
- ``.closed``
- ``.forgiven``
- Added ``Invoice.status`` and ``enums.InvoiceStatus`` (#1020).

2.2.2 (2020-01-20)
------------------
Expand Down
4 changes: 0 additions & 4 deletions djstripe/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,6 @@ class InvoiceAdmin(StripeModelAdmin):
"customer",
"number",
"paid",
"forgiven",
"closed",
"period_start",
"period_end",
"subtotal",
Expand All @@ -330,8 +328,6 @@ class InvoiceAdmin(StripeModelAdmin):
)
list_filter = (
"paid",
"forgiven",
"closed",
"attempted",
"created",
"due_date",
Expand Down
8 changes: 8 additions & 0 deletions djstripe/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,14 @@ class InvoiceCollectionMethod(Enum):
InvoiceBilling = InvoiceCollectionMethod


class InvoiceStatus(Enum):
draft = _("Draft")
open = _("Open")
paid = _("Paid")
uncollectible = _("Uncollectible")
void = _("Void")


class IntentUsage(Enum):
on_session = _("On session")
off_session = _("Off session")
Expand Down
42 changes: 42 additions & 0 deletions djstripe/migrations/0006_invoice_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 2.2 on 2020-01-20 12:49

from django.db import migrations

import djstripe.enums
import djstripe.fields


class Migration(migrations.Migration):

dependencies = [
("djstripe", "0005_2_2"),
]

operations = [
migrations.RemoveField(model_name="invoice", name="closed",),
migrations.RemoveField(model_name="invoice", name="forgiven",),
migrations.RemoveField(model_name="upcominginvoice", name="closed",),
migrations.RemoveField(model_name="upcominginvoice", name="forgiven",),
migrations.AddField(
model_name="invoice",
name="status",
field=djstripe.fields.StripeEnumField(
blank=True,
default="",
enum=djstripe.enums.InvoiceStatus,
help_text="The status of the invoice, one of draft, open, paid, uncollectible, or void.",
max_length=13,
),
),
migrations.AddField(
model_name="upcominginvoice",
name="status",
field=djstripe.fields.StripeEnumField(
blank=True,
default="",
enum=djstripe.enums.InvoiceStatus,
help_text="The status of the invoice, one of draft, open, paid, uncollectible, or void.",
max_length=13,
),
),
]
85 changes: 13 additions & 72 deletions djstripe/models/billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,6 @@ class BaseInvoice(StripeModel):
related_name="latest_%(class)s",
help_text="The latest charge generated for this invoice, if any.",
)
# deprecated, will be removed in 2.3
closed = models.NullBooleanField(
default=False,
help_text="Whether or not the invoice is still trying to collect payment."
" An invoice is closed if it's either paid or it has been marked closed. "
"A closed invoice will no longer attempt to collect payment.",
)
collection_method = StripeEnumField(
enum=enums.InvoiceBilling,
null=True,
Expand Down Expand Up @@ -372,14 +365,6 @@ class BaseInvoice(StripeModel):
footer = models.TextField(
max_length=5000, blank=True, help_text="Footer displayed on the invoice."
)
# deprecated, will be removed in 2.3
forgiven = models.NullBooleanField(
default=False,
help_text="Whether or not the invoice has been forgiven. "
"Forgiving an invoice instructs us to update the subscription status as "
"if the invoice were successfully paid. Once an invoice has been forgiven, "
"it cannot be unforgiven or reopened.",
)
hosted_invoice_url = models.TextField(
max_length=799,
default="",
Expand Down Expand Up @@ -473,7 +458,13 @@ class BaseInvoice(StripeModel):
"While most banks display this information consistently, "
"some may display it incorrectly or not at all.",
)
# TODO status
status = StripeEnumField(
default="",
blank=True,
enum=enums.InvoiceStatus,
help_text="The status of the invoice, one of draft, open, paid, "
"uncollectible, or void.",
)
status_transitions = JSONField(null=True, blank=True)
subscription = models.ForeignKey(
"Subscription",
Expand Down Expand Up @@ -535,29 +526,6 @@ def __str__(self):
number=self.number or self.receipt_number or self.id
)

@classmethod
def _manipulate_stripe_object_hook(cls, data):
data = super()._manipulate_stripe_object_hook(data)
# Invoice.closed and .forgiven deprecated in API 2018-11-08 -
# see https://stripe.com/docs/upgrades#2018-11-08

if "closed" not in data:
# TODO - drop this in 2.3, use auto_advance instead
# https://stripe.com/docs/billing/invoices/migrating-new-invoice-states#autoadvance
if "auto_advance" in data:
data["closed"] = not data["auto_advance"]
else:
data["closed"] = False

if "forgiven" not in data:
# TODO - drop this in 2.3, use status == "uncollectible" instead
if "status" in data:
data["forgiven"] = data["status"] == "uncollectible"
else:
data["forgiven"] = False

return data

@classmethod
def upcoming(
cls,
Expand Down Expand Up @@ -653,9 +621,13 @@ def upcoming(
)

def retry(self):
""" Retry payment on this invoice if it isn't paid, closed, or forgiven."""
""" Retry payment on this invoice if it isn't paid or uncollectible."""

if not self.paid and not self.forgiven and not self.closed:
if (
self.status != enums.InvoiceStatus.paid
and self.status != enums.InvoiceStatus.uncollectible
and self.auto_advance
):
stripe_invoice = self.api_retrieve()
updated_stripe_invoice = (
stripe_invoice.pay()
Expand All @@ -664,37 +636,6 @@ def retry(self):
return True
return False

STATUS_PAID = "Paid"
STATUS_FORGIVEN = "Forgiven"
STATUS_CLOSED = "Closed"
STATUS_OPEN = "Open"

@property
def status(self):
warnings.warn(
"Invoice.status will be redefined in djstripe 2.3, use "
"Invoice.legacy_status to keep the old values",
DeprecationWarning,
)

return self.legacy_status

@property
def legacy_status(self):
"""
Attempts to label this invoice with a status.
Note that an invoice can be more than one of the choices.
We just set a priority on which status appears.
"""

if self.paid:
return self.STATUS_PAID
if self.forgiven:
return self.STATUS_FORGIVEN
if self.closed:
return self.STATUS_CLOSED
return self.STATUS_OPEN

@property
def billing(self):
warnings.warn(
Expand Down
2 changes: 1 addition & 1 deletion djstripe/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ def retry_unpaid_invoices(self):
""" Attempt to retry collecting payment on the customer's unpaid invoices."""

self._sync_invoices()
for invoice in self.invoices.filter(paid=False, closed=False):
for invoice in self.invoices.filter(auto_advance=True).exclude(status="paid"):
try:
invoice.retry() # Always retry unpaid invoices
except InvalidRequestError as exc:
Expand Down
1 change: 0 additions & 1 deletion docs/reference/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ Invoice

.. automethod:: djstripe.models.Invoice.upcoming
.. automethod:: djstripe.models.Invoice.retry
.. autoattribute:: djstripe.models.Invoice.status
.. autoattribute:: djstripe.models.Invoice.plan

.. automethod:: djstripe.models.Invoice.str_parts
Expand Down
Loading

0 comments on commit 891782a

Please sign in to comment.