membershipworks: Use django-simple-history for Member, Flag, and MemberFlag
This commit is contained in:
parent
ee61451759
commit
b98804e514
@ -54,6 +54,7 @@ class Base(Configuration):
|
||||
"django_db_views",
|
||||
"django_sendfile",
|
||||
"django_bootstrap5",
|
||||
"simple_history",
|
||||
# "tasks.apps.TasksConfig",
|
||||
"rentals.apps.RentalsConfig",
|
||||
"membershipworks.apps.MembershipworksConfig",
|
||||
|
@ -10,6 +10,7 @@ from django_object_actions import (
|
||||
)
|
||||
from django_q.models import Task
|
||||
from django_q.tasks import async_task
|
||||
from simple_history.admin import SimpleHistoryAdmin
|
||||
|
||||
from .models import (
|
||||
Event,
|
||||
@ -28,7 +29,7 @@ from .tasks.scrape import (
|
||||
from .tasks.ucsAccounts import sync_accounts
|
||||
|
||||
|
||||
class ReadOnlyAdmin(admin.ModelAdmin):
|
||||
class ReadOnlyAdminMixin:
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
@ -39,7 +40,9 @@ class ReadOnlyAdmin(admin.ModelAdmin):
|
||||
return False
|
||||
|
||||
|
||||
class BaseMembershipWorksAdmin(DjangoObjectActions, ReadOnlyAdmin):
|
||||
class BaseMembershipWorksAdmin(
|
||||
DjangoObjectActions, ReadOnlyAdminMixin, SimpleHistoryAdmin
|
||||
):
|
||||
changelist_actions = ("refresh_membershipworks_data", "sync_ucs_accounts")
|
||||
|
||||
# internal method from DjangoObjectActions
|
||||
|
453
membershipworks/migrations/0002_historical_member_and_flags.py
Normal file
453
membershipworks/migrations/0002_historical_member_and_flags.py
Normal file
@ -0,0 +1,453 @@
|
||||
# Generated by Django 5.1 on 2024-08-28 19:20
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import simple_history.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("membershipworks", "0001_initial"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="HistoricalFlag",
|
||||
fields=[
|
||||
("id", models.CharField(db_index=True, max_length=24)),
|
||||
("name", models.TextField(blank=True, null=True)),
|
||||
("type", models.CharField(max_length=6)),
|
||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
||||
("history_date", models.DateTimeField(db_index=True)),
|
||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
||||
(
|
||||
"history_type",
|
||||
models.CharField(
|
||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
||||
max_length=1,
|
||||
),
|
||||
),
|
||||
(
|
||||
"history_user",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="+",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "historical flag",
|
||||
"verbose_name_plural": "historical flags",
|
||||
"ordering": ("-history_date", "-history_id"),
|
||||
"get_latest_by": ("history_date", "history_id"),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="HistoricalMember",
|
||||
fields=[
|
||||
("uid", models.CharField(db_index=True, max_length=24)),
|
||||
(
|
||||
"year_of_birth",
|
||||
models.TextField(blank=True, db_column="Year of Birth", null=True),
|
||||
),
|
||||
(
|
||||
"account_name",
|
||||
models.TextField(blank=True, db_column="Account Name", null=True),
|
||||
),
|
||||
(
|
||||
"first_name",
|
||||
models.TextField(blank=True, db_column="First Name", null=True),
|
||||
),
|
||||
(
|
||||
"last_name",
|
||||
models.TextField(blank=True, db_column="Last Name", null=True),
|
||||
),
|
||||
("phone", models.TextField(blank=True, db_column="Phone", null=True)),
|
||||
("email", models.TextField(blank=True, db_column="Email", null=True)),
|
||||
(
|
||||
"volunteer_email",
|
||||
models.TextField(
|
||||
blank=True, db_column="Volunteer Email", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"address_street",
|
||||
models.TextField(
|
||||
blank=True, db_column="Address (Street)", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"address_city",
|
||||
models.TextField(blank=True, db_column="Address (City)", null=True),
|
||||
),
|
||||
(
|
||||
"address_state_province",
|
||||
models.TextField(
|
||||
blank=True, db_column="Address (State/Province)", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"address_postal_code",
|
||||
models.TextField(
|
||||
blank=True, db_column="Address (Postal Code)", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"address_country",
|
||||
models.TextField(
|
||||
blank=True, db_column="Address (Country)", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"profile_description",
|
||||
models.TextField(
|
||||
blank=True, db_column="Profile description", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"website",
|
||||
models.TextField(blank=True, db_column="Website", null=True),
|
||||
),
|
||||
("fax", models.TextField(blank=True, db_column="Fax", null=True)),
|
||||
(
|
||||
"contact_person",
|
||||
models.TextField(blank=True, db_column="Contact Person", null=True),
|
||||
),
|
||||
(
|
||||
"password",
|
||||
models.TextField(blank=True, db_column="Password", null=True),
|
||||
),
|
||||
(
|
||||
"position_relation",
|
||||
models.TextField(
|
||||
blank=True, db_column="Position/relation", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"parent_account_id",
|
||||
models.TextField(
|
||||
blank=True, db_column="Parent Account ID", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"closet_storage",
|
||||
models.TextField(
|
||||
blank=True, db_column="Closet Storage #", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"storage_shelf",
|
||||
models.TextField(
|
||||
blank=True, db_column="Storage Shelf #", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"personal_studio_space",
|
||||
models.TextField(
|
||||
blank=True, db_column="Personal Studio Space #", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_permitted_shops_during_extended_hours",
|
||||
models.BooleanField(
|
||||
db_column="Access Permitted Shops During Extended Hours?"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_front_door_and_studio_space_during_extended_hours",
|
||||
models.BooleanField(
|
||||
db_column="Access Front Door and Studio Space During Extended Hours?"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_wood_shop",
|
||||
models.BooleanField(db_column="Access Wood Shop?"),
|
||||
),
|
||||
(
|
||||
"access_metal_shop",
|
||||
models.BooleanField(db_column="Access Metal Shop?"),
|
||||
),
|
||||
(
|
||||
"access_storage_closet",
|
||||
models.BooleanField(db_column="Access Storage Closet?"),
|
||||
),
|
||||
(
|
||||
"access_studio_space",
|
||||
models.BooleanField(db_column="Access Studio Space?"),
|
||||
),
|
||||
(
|
||||
"access_front_door",
|
||||
models.BooleanField(db_column="Access Front Door?"),
|
||||
),
|
||||
(
|
||||
"access_card_number",
|
||||
models.TextField(
|
||||
blank=True, db_column="Access Card Number", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_card_facility_code",
|
||||
models.TextField(
|
||||
blank=True, db_column="Access Card Facility Code", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"auto_billing_id",
|
||||
models.TextField(
|
||||
blank=True, db_column="Auto Billing ID", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"billing_method",
|
||||
models.TextField(blank=True, db_column="Billing Method", null=True),
|
||||
),
|
||||
(
|
||||
"renewal_date",
|
||||
models.DateField(blank=True, db_column="Renewal Date", null=True),
|
||||
),
|
||||
(
|
||||
"join_date",
|
||||
models.DateField(blank=True, db_column="Join Date", null=True),
|
||||
),
|
||||
(
|
||||
"admin_note",
|
||||
models.TextField(blank=True, db_column="Admin note", null=True),
|
||||
),
|
||||
(
|
||||
"profile_gallery_image_url",
|
||||
models.TextField(
|
||||
blank=True, db_column="Profile gallery image URL", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"business_card_image_url",
|
||||
models.TextField(
|
||||
blank=True, db_column="Business card image URL", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"instagram",
|
||||
models.TextField(blank=True, db_column="Instagram", null=True),
|
||||
),
|
||||
(
|
||||
"pinterest",
|
||||
models.TextField(blank=True, db_column="Pinterest", null=True),
|
||||
),
|
||||
(
|
||||
"youtube",
|
||||
models.TextField(blank=True, db_column="Youtube", null=True),
|
||||
),
|
||||
("yelp", models.TextField(blank=True, db_column="Yelp", null=True)),
|
||||
(
|
||||
"google",
|
||||
models.TextField(blank=True, db_column="Google+", null=True),
|
||||
),
|
||||
("bbb", models.TextField(blank=True, db_column="BBB", null=True)),
|
||||
(
|
||||
"twitter",
|
||||
models.TextField(blank=True, db_column="Twitter", null=True),
|
||||
),
|
||||
(
|
||||
"facebook",
|
||||
models.TextField(blank=True, db_column="Facebook", null=True),
|
||||
),
|
||||
(
|
||||
"linked_in",
|
||||
models.TextField(blank=True, db_column="LinkedIn", null=True),
|
||||
),
|
||||
(
|
||||
"do_not_show_street_address_in_profile",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
db_column="Do not show street address in profile",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"do_not_list_in_directory",
|
||||
models.TextField(
|
||||
blank=True, db_column="Do not list in directory", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"how_did_you_hear",
|
||||
models.TextField(blank=True, db_column="HowDidYouHear", null=True),
|
||||
),
|
||||
(
|
||||
"authorize_charge",
|
||||
models.TextField(
|
||||
blank=True, db_column="authorizeCharge", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"policy_agreement",
|
||||
models.TextField(
|
||||
blank=True, db_column="policyAgreement", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"waiver_form_signed_and_on_file_date",
|
||||
models.DateField(
|
||||
blank=True,
|
||||
db_column="Waiver form signed and on file date.",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_agreement_signed_and_on_file_date",
|
||||
models.DateField(
|
||||
blank=True,
|
||||
db_column="Membership Agreement signed and on file date.",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"ip_address",
|
||||
models.TextField(blank=True, db_column="IP Address", null=True),
|
||||
),
|
||||
(
|
||||
"audit_date",
|
||||
models.DateField(blank=True, db_column="Audit Date", null=True),
|
||||
),
|
||||
(
|
||||
"agreement_version",
|
||||
models.TextField(
|
||||
blank=True, db_column="Agreement Version", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"paperwork_status",
|
||||
models.TextField(
|
||||
blank=True, db_column="Paperwork status", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_agreement_dated",
|
||||
models.BooleanField(db_column="Membership agreement dated"),
|
||||
),
|
||||
(
|
||||
"membership_agreement_acknowledgement_page_filled_out",
|
||||
models.BooleanField(
|
||||
db_column="Membership Agreement Acknowledgement Page Filled Out"
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_agreement_signed",
|
||||
models.BooleanField(db_column="Membership Agreement Signed"),
|
||||
),
|
||||
(
|
||||
"liability_form_filled_out",
|
||||
models.BooleanField(db_column="Liability Form Filled Out"),
|
||||
),
|
||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
||||
("history_date", models.DateTimeField(db_index=True)),
|
||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
||||
(
|
||||
"history_type",
|
||||
models.CharField(
|
||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
||||
max_length=1,
|
||||
),
|
||||
),
|
||||
(
|
||||
"history_user",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="+",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "historical member",
|
||||
"verbose_name_plural": "historical members",
|
||||
"ordering": ("-history_date", "-history_id"),
|
||||
"get_latest_by": ("history_date", "history_id"),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="HistoricalMemberFlag",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigIntegerField(
|
||||
auto_created=True, blank=True, db_index=True, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("history_id", models.AutoField(primary_key=True, serialize=False)),
|
||||
("history_date", models.DateTimeField(db_index=True)),
|
||||
("history_change_reason", models.CharField(max_length=100, null=True)),
|
||||
(
|
||||
"history_type",
|
||||
models.CharField(
|
||||
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
|
||||
max_length=1,
|
||||
),
|
||||
),
|
||||
(
|
||||
"flag",
|
||||
simple_history.models.HistoricForeignKey(
|
||||
blank=True,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
||||
related_name="+",
|
||||
to="membershipworks.flag",
|
||||
),
|
||||
),
|
||||
(
|
||||
"history_user",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="+",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"member",
|
||||
simple_history.models.HistoricForeignKey(
|
||||
blank=True,
|
||||
db_column="uid",
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
||||
related_name="+",
|
||||
to="membershipworks.member",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "historical member flag",
|
||||
"verbose_name_plural": "historical member flags",
|
||||
"ordering": ("-history_date", "-history_id"),
|
||||
"get_latest_by": ("history_date", "history_id"),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="memberflag",
|
||||
name="flag",
|
||||
field=simple_history.models.HistoricForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT, to="membershipworks.flag"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="memberflag",
|
||||
name="member",
|
||||
field=simple_history.models.HistoricForeignKey(
|
||||
db_column="uid",
|
||||
db_constraint=False,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="membershipworks.member",
|
||||
),
|
||||
),
|
||||
]
|
@ -28,6 +28,7 @@ from django.utils import timezone
|
||||
import nh3
|
||||
from django_db_views.db_view import DBView
|
||||
from django_stubs_ext import WithAnnotations
|
||||
from simple_history.models import HistoricalRecords, HistoricForeignKey
|
||||
|
||||
from reservations.models import Reservation
|
||||
|
||||
@ -89,6 +90,8 @@ class Flag(BaseModel):
|
||||
name = models.TextField(null=True, blank=True)
|
||||
type = models.CharField(max_length=6)
|
||||
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta:
|
||||
db_table = "flag"
|
||||
ordering = ("name",)
|
||||
@ -121,7 +124,6 @@ class MemberQuerySet(models.QuerySet):
|
||||
)
|
||||
|
||||
|
||||
# TODO: is this still a temporal table?
|
||||
class Member(BaseModel):
|
||||
uid = models.CharField(max_length=24, primary_key=True)
|
||||
year_of_birth = models.TextField(db_column="Year of Birth", null=True, blank=True)
|
||||
@ -248,6 +250,8 @@ class Member(BaseModel):
|
||||
)
|
||||
flags = models.ManyToManyField(Flag, through="MemberFlag", related_name="members")
|
||||
|
||||
history = HistoricalRecords()
|
||||
|
||||
_api_names_override = {
|
||||
"uid": "Account ID",
|
||||
"how_did_you_hear": "Please tell us how you heard about the Claremont MakerSpace and what tools or shops you are most excited to start using:",
|
||||
@ -300,10 +304,12 @@ class Member(BaseModel):
|
||||
|
||||
|
||||
class MemberFlag(BaseModel):
|
||||
member = models.ForeignKey(
|
||||
member = HistoricForeignKey(
|
||||
Member, on_delete=models.PROTECT, db_column="uid", db_constraint=False
|
||||
)
|
||||
flag = models.ForeignKey(Flag, on_delete=models.PROTECT)
|
||||
flag = HistoricForeignKey(Flag, on_delete=models.PROTECT)
|
||||
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta:
|
||||
db_table = "memberflag"
|
||||
|
17
pdm.lock
17
pdm.lock
@ -5,7 +5,7 @@
|
||||
groups = ["default", "debug", "dev", "lint", "server", "typing"]
|
||||
strategy = ["inherit_metadata"]
|
||||
lock_version = "4.5.0"
|
||||
content_hash = "sha256:0c560e1f2a81810e95ba8993538337bfc8b39576b6923280cfbfad91ad5b58f2"
|
||||
content_hash = "sha256:f908c755f35f0769821be54914ad53a3de6e9a0c654baf877045c161c7dacfc7"
|
||||
|
||||
[[metadata.targets]]
|
||||
requires_python = "==3.11.*"
|
||||
@ -650,6 +650,21 @@ files = [
|
||||
{file = "django_sendfile2-0.7.1-py3-none-any.whl", hash = "sha256:81971df1db77f688c4834b8540930902d0d929c64cf374bd604b81f5ac52c04a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-simple-history"
|
||||
version = "3.7.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Store model history and view/revert changes from admin site."
|
||||
groups = ["default"]
|
||||
marker = "python_version == \"3.11\""
|
||||
dependencies = [
|
||||
"django>=4.2",
|
||||
]
|
||||
files = [
|
||||
{file = "django_simple_history-3.7.0-py3-none-any.whl", hash = "sha256:282cb2c4aa63f51547f17da7f2130abaa81ba01694676d19b88d52c94a57a52c"},
|
||||
{file = "django_simple_history-3.7.0.tar.gz", hash = "sha256:ac3b7ca8b0d33f7ea6be8fe7fc98cf43415efa500ff5dfe736fbd1ebc0cf39f9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-stubs"
|
||||
version = "5.0.2"
|
||||
|
@ -43,6 +43,7 @@ dependencies = [
|
||||
"google-auth-oauthlib~=1.2",
|
||||
"django-model-utils~=4.5",
|
||||
"psycopg[binary,pool]~=3.2",
|
||||
"django-simple-history~=3.7",
|
||||
]
|
||||
requires-python = ">=3.11"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user