Update company_site/financial/forms.py for Stripe invoices (#23)
This commit is contained in:
@@ -2,7 +2,19 @@ import datetime
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from .models import Employee, Contract, ChargeNumber, TimeCardCell, AddressModel, UserProfile, set_user_type
|
from .models import (
|
||||||
|
Employee,
|
||||||
|
Contract,
|
||||||
|
ChargeNumber,
|
||||||
|
TimeCardCell,
|
||||||
|
AddressModel,
|
||||||
|
UserProfile,
|
||||||
|
set_user_type,
|
||||||
|
BillingCustomer,
|
||||||
|
Invoice,
|
||||||
|
RecurringSubscription,
|
||||||
|
)
|
||||||
|
from .stripe_billing import dollars_to_cents
|
||||||
|
|
||||||
class NewEmployeeForm(ModelForm):
|
class NewEmployeeForm(ModelForm):
|
||||||
first_name = forms.CharField(max_length=30, required=False, label="First Name")
|
first_name = forms.CharField(max_length=30, required=False, label="First Name")
|
||||||
@@ -99,3 +111,144 @@ class TimeLogForm(ModelForm):
|
|||||||
cleaned_data['hour'] = duration
|
cleaned_data['hour'] = duration
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
|
class BillingCustomerForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = BillingCustomer
|
||||||
|
fields = ["name", "email", "company", "notes"]
|
||||||
|
|
||||||
|
|
||||||
|
class OneOffInvoiceForm(forms.Form):
|
||||||
|
customer = forms.ModelChoiceField(
|
||||||
|
queryset=BillingCustomer.objects.all(),
|
||||||
|
required=False,
|
||||||
|
help_text="Pick an existing customer, or fill New customer fields below.",
|
||||||
|
)
|
||||||
|
new_customer_name = forms.CharField(max_length=200, required=False, label="New customer name")
|
||||||
|
new_customer_email = forms.EmailField(required=False, label="New customer email")
|
||||||
|
new_customer_company = forms.CharField(
|
||||||
|
max_length=200, required=False, label="New customer company"
|
||||||
|
)
|
||||||
|
description = forms.CharField(max_length=500)
|
||||||
|
amount = forms.DecimalField(
|
||||||
|
max_digits=10,
|
||||||
|
decimal_places=2,
|
||||||
|
min_value=0.50,
|
||||||
|
label="Amount (USD)",
|
||||||
|
help_text="Minimum $0.50",
|
||||||
|
)
|
||||||
|
due_date = forms.DateField(
|
||||||
|
required=False,
|
||||||
|
widget=forms.DateInput(attrs={"type": "date"}),
|
||||||
|
)
|
||||||
|
notes = forms.CharField(required=False, widget=forms.Textarea(attrs={"rows": 3}))
|
||||||
|
send_email = forms.BooleanField(
|
||||||
|
required=False,
|
||||||
|
initial=True,
|
||||||
|
label="Email payment link to customer",
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned = super().clean()
|
||||||
|
customer = cleaned.get("customer")
|
||||||
|
name = (cleaned.get("new_customer_name") or "").strip()
|
||||||
|
email = (cleaned.get("new_customer_email") or "").strip()
|
||||||
|
if not customer and not (name and email):
|
||||||
|
raise forms.ValidationError(
|
||||||
|
"Select an existing customer or provide new customer name and email."
|
||||||
|
)
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
def resolve_customer(self, user):
|
||||||
|
customer = self.cleaned_data.get("customer")
|
||||||
|
if customer:
|
||||||
|
return customer
|
||||||
|
customer = BillingCustomer(
|
||||||
|
name=self.cleaned_data["new_customer_name"].strip(),
|
||||||
|
email=self.cleaned_data["new_customer_email"].strip(),
|
||||||
|
company=(self.cleaned_data.get("new_customer_company") or "").strip(),
|
||||||
|
created_by=user,
|
||||||
|
last_modified_BY=user,
|
||||||
|
)
|
||||||
|
customer.save()
|
||||||
|
return customer
|
||||||
|
|
||||||
|
def build_invoice(self, user) -> Invoice:
|
||||||
|
customer = self.resolve_customer(user)
|
||||||
|
return Invoice(
|
||||||
|
customer=customer,
|
||||||
|
description=self.cleaned_data["description"],
|
||||||
|
amount_cents=dollars_to_cents(self.cleaned_data["amount"]),
|
||||||
|
due_date=self.cleaned_data.get("due_date"),
|
||||||
|
notes=self.cleaned_data.get("notes") or "",
|
||||||
|
created_by=user,
|
||||||
|
last_modified_BY=user,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RecurringSubscriptionForm(forms.Form):
|
||||||
|
customer = forms.ModelChoiceField(
|
||||||
|
queryset=BillingCustomer.objects.all(),
|
||||||
|
required=False,
|
||||||
|
help_text="Pick an existing customer, or fill New customer fields below.",
|
||||||
|
)
|
||||||
|
new_customer_name = forms.CharField(max_length=200, required=False, label="New customer name")
|
||||||
|
new_customer_email = forms.EmailField(required=False, label="New customer email")
|
||||||
|
new_customer_company = forms.CharField(
|
||||||
|
max_length=200, required=False, label="New customer company"
|
||||||
|
)
|
||||||
|
description = forms.CharField(max_length=500)
|
||||||
|
amount = forms.DecimalField(
|
||||||
|
max_digits=10,
|
||||||
|
decimal_places=2,
|
||||||
|
min_value=0.50,
|
||||||
|
label="Amount per period (USD)",
|
||||||
|
)
|
||||||
|
interval = forms.ChoiceField(
|
||||||
|
choices=RecurringSubscription.Interval.choices,
|
||||||
|
initial=RecurringSubscription.Interval.MONTH,
|
||||||
|
)
|
||||||
|
notes = forms.CharField(required=False, widget=forms.Textarea(attrs={"rows": 3}))
|
||||||
|
send_email = forms.BooleanField(
|
||||||
|
required=False,
|
||||||
|
initial=True,
|
||||||
|
label="Email checkout / payment link to customer",
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned = super().clean()
|
||||||
|
customer = cleaned.get("customer")
|
||||||
|
name = (cleaned.get("new_customer_name") or "").strip()
|
||||||
|
email = (cleaned.get("new_customer_email") or "").strip()
|
||||||
|
if not customer and not (name and email):
|
||||||
|
raise forms.ValidationError(
|
||||||
|
"Select an existing customer or provide new customer name and email."
|
||||||
|
)
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
def resolve_customer(self, user):
|
||||||
|
customer = self.cleaned_data.get("customer")
|
||||||
|
if customer:
|
||||||
|
return customer
|
||||||
|
customer = BillingCustomer(
|
||||||
|
name=self.cleaned_data["new_customer_name"].strip(),
|
||||||
|
email=self.cleaned_data["new_customer_email"].strip(),
|
||||||
|
company=(self.cleaned_data.get("new_customer_company") or "").strip(),
|
||||||
|
created_by=user,
|
||||||
|
last_modified_BY=user,
|
||||||
|
)
|
||||||
|
customer.save()
|
||||||
|
return customer
|
||||||
|
|
||||||
|
def build_subscription(self, user) -> RecurringSubscription:
|
||||||
|
customer = self.resolve_customer(user)
|
||||||
|
return RecurringSubscription(
|
||||||
|
customer=customer,
|
||||||
|
description=self.cleaned_data["description"],
|
||||||
|
amount_cents=dollars_to_cents(self.cleaned_data["amount"]),
|
||||||
|
interval=self.cleaned_data["interval"],
|
||||||
|
notes=self.cleaned_data.get("notes") or "",
|
||||||
|
created_by=user,
|
||||||
|
last_modified_BY=user,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user