Update company_site/financial/forms.py for Stripe invoices (#23)

This commit is contained in:
2026-07-31 12:01:59 -07:00
parent 88ee85dda3
commit e70ea3fb96
+154 -1
View File
@@ -2,7 +2,19 @@ import datetime
from django import forms
from django.contrib.auth.models import User
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):
first_name = forms.CharField(max_length=30, required=False, label="First Name")
@@ -99,3 +111,144 @@ class TimeLogForm(ModelForm):
cleaned_data['hour'] = duration
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,
)