diff options
| -rw-r--r-- | generalresearch/gr_django/__init__.py | 0 | ||||
| -rw-r--r-- | generalresearch/gr_django/app/__init__.py | 0 | ||||
| -rw-r--r-- | generalresearch/gr_django/app/manage.py | 13 | ||||
| -rw-r--r-- | generalresearch/gr_django/app/settings.py | 24 | ||||
| -rw-r--r-- | generalresearch/gr_django/apps.py | 7 | ||||
| -rw-r--r-- | generalresearch/gr_django/migrations/0001_initial.py | 98 | ||||
| -rw-r--r-- | generalresearch/gr_django/migrations/0002_business_balance_business_balance_net_7d_and_more.py | 38 | ||||
| -rw-r--r-- | generalresearch/gr_django/migrations/__init__.py | 0 | ||||
| -rw-r--r-- | generalresearch/gr_django/models.py | 146 | ||||
| -rw-r--r-- | generalresearch/gr_django/readme.MD | 5 |
10 files changed, 331 insertions, 0 deletions
diff --git a/generalresearch/gr_django/__init__.py b/generalresearch/gr_django/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/generalresearch/gr_django/__init__.py diff --git a/generalresearch/gr_django/app/__init__.py b/generalresearch/gr_django/app/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/generalresearch/gr_django/app/__init__.py diff --git a/generalresearch/gr_django/app/manage.py b/generalresearch/gr_django/app/manage.py new file mode 100644 index 0000000..77700ed --- /dev/null +++ b/generalresearch/gr_django/app/manage.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault( + "DJANGO_SETTINGS_MODULE", + "generalresearch.gr_django.app.settings", + ) + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv)
\ No newline at end of file diff --git a/generalresearch/gr_django/app/settings.py b/generalresearch/gr_django/app/settings.py new file mode 100644 index 0000000..857870e --- /dev/null +++ b/generalresearch/gr_django/app/settings.py @@ -0,0 +1,24 @@ +import os + +INSTALLED_APPS = [ + "django.contrib.postgres", + "django.contrib.contenttypes", + "generalresearch.gr_django.apps.GRSchemaConfig", +] + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": os.environ.get("GR_DB_NAME", "gr"), + "USER": os.environ.get("GR_DB_USER", "postgres"), + "PASSWORD": os.environ.get("GR_DB_PASSWORD", "password"), + "HOST": os.environ.get("GR_DB_HOST", "127.0.0.1"), + "PORT": os.environ.get("GR_DB_PORT", "5432"), + } +} + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" +LANGUAGE_CODE = "en-us" +TIME_ZONE = "UTC" +USE_I18N = True +USE_TZ = True
\ No newline at end of file diff --git a/generalresearch/gr_django/apps.py b/generalresearch/gr_django/apps.py new file mode 100644 index 0000000..f6a2b62 --- /dev/null +++ b/generalresearch/gr_django/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class GRSchemaConfig(AppConfig): + name = "generalresearch.gr_django" + label = "common" # preserves the existing gr-carer migration identity + default_auto_field = "django.db.models.BigAutoField"
\ No newline at end of file diff --git a/generalresearch/gr_django/migrations/0001_initial.py b/generalresearch/gr_django/migrations/0001_initial.py new file mode 100644 index 0000000..712592b --- /dev/null +++ b/generalresearch/gr_django/migrations/0001_initial.py @@ -0,0 +1,98 @@ +# Generated by Django 5.2.6 on 2025-09-26 19:41 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Business', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('kind', models.CharField(choices=[('i', 'Individual'), ('c', 'Company')], default='i', max_length=1)), + ('name', models.CharField(blank=True, max_length=255)), + ('tax_number', models.CharField(blank=True, max_length=20, null=True)), + ], + ), + migrations.CreateModel( + name='Membership', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('user_id', models.BigIntegerField(db_index=True, null=True)), + ('team_id', models.BigIntegerField(db_index=True, null=True)), + ('privilege', models.PositiveSmallIntegerField(choices=[(0, 'Admin'), (1, 'Maintain'), (2, 'Read')], default=1)), + ('owner', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ], + ), + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('sub', models.CharField(max_length=200)), + ('is_superuser', models.BooleanField(default=False)), + ('date_joined', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'db_table': 'gr_user', + }, + ), + migrations.CreateModel( + name='UserToken', + fields=[ + ('key', models.CharField(max_length=255, primary_key=True, serialize=False)), + ('user_id', models.BigIntegerField(db_index=True, null=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'db_table': 'gr_token', + }, + ), + migrations.CreateModel( + name='BankAccount', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('transfer_method', models.PositiveSmallIntegerField(choices=[(0, 'ACH'), (1, 'Wire')], default=0)), + ('account_number', models.CharField(blank=True, max_length=50, null=True)), + ('routing_number', models.CharField(blank=True, max_length=50, null=True)), + ('iban', models.CharField(blank=True, max_length=50, null=True)), + ('swift', models.CharField(blank=True, max_length=50, null=True)), + ('business', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='common.business')), + ], + ), + migrations.CreateModel( + name='BusinessAddress', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('line_1', models.CharField(blank=True, max_length=255, null=True)), + ('line_2', models.CharField(blank=True, max_length=255, null=True)), + ('city', models.CharField(blank=True, max_length=255, null=True)), + ('country', models.CharField(blank=True, max_length=2, null=True)), + ('state', models.CharField(blank=True, max_length=255, null=True)), + ('postal_code', models.CharField(blank=True, max_length=12, null=True)), + ('phone_number', models.CharField(max_length=20, null=True)), + ('business', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='common.business')), + ], + ), + migrations.CreateModel( + name='Team', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, unique=True)), + ('name', models.CharField(blank=True, max_length=255, null=True)), + ('businesses', models.ManyToManyField(to='common.business')), + ], + ), + ] diff --git a/generalresearch/gr_django/migrations/0002_business_balance_business_balance_net_7d_and_more.py b/generalresearch/gr_django/migrations/0002_business_balance_business_balance_net_7d_and_more.py new file mode 100644 index 0000000..d355368 --- /dev/null +++ b/generalresearch/gr_django/migrations/0002_business_balance_business_balance_net_7d_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 6.1.1 on 2026-10-09 16:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='business', + name='balance', + field=models.JSONField(default=None, null=True), + ), + migrations.AddField( + model_name='business', + name='balance_net_7d', + field=models.IntegerField(default=None, null=True), + ), + migrations.AddField( + model_name='business', + name='task_completes_7d', + field=models.IntegerField(default=None, null=True), + ), + migrations.AddField( + model_name='business', + name='user_wallet_balance', + field=models.JSONField(default=None, null=True), + ), + migrations.AddField( + model_name='business', + name='users_active_7d', + field=models.IntegerField(default=None, null=True), + ), + ] diff --git a/generalresearch/gr_django/migrations/__init__.py b/generalresearch/gr_django/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/generalresearch/gr_django/migrations/__init__.py diff --git a/generalresearch/gr_django/models.py b/generalresearch/gr_django/models.py new file mode 100644 index 0000000..01bf749 --- /dev/null +++ b/generalresearch/gr_django/models.py @@ -0,0 +1,146 @@ +import uuid + +from django.db import models + + +class User(models.Model): + id = models.BigAutoField(primary_key=True) + sub = models.CharField(max_length=200, blank=False, null=False) + + is_superuser = models.BooleanField(default=False) + date_joined = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "gr_user" + + +class UserToken(models.Model): + key = models.CharField(max_length=255, primary_key=True) + user_id = models.BigIntegerField(null=True, db_index=True) + created = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "gr_token" + + +class Membership(models.Model): + """ + A User on generalresearch.com can be a member of many teams, that relationship can have different + permission to manage a team or accounts and business entities owned by that team + """ + + id = models.BigAutoField(primary_key=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + + user_id = models.BigIntegerField(null=True, db_index=True) + team_id = models.BigIntegerField(null=True, db_index=True) + + PRIVILEGES = ( + (0, "Admin"), + (1, "Maintain"), + (2, "Read"), + ) + privilege = models.PositiveSmallIntegerField(default=1, choices=PRIVILEGES) + owner = models.BooleanField(default=False) + + created = models.DateTimeField(auto_now_add=True, null=False) + + +class Team(models.Model): + """ + This is a collection of users / accounts that work as a team and share + access to the same BPID However, an Organization can have many Bank + Accounts as each BPID doesn't need to deposit funds into the same Bank + account or Business + """ + + id = models.BigAutoField(primary_key=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + + name = models.CharField(max_length=255, null=True, blank=True) + + businesses = models.ManyToManyField(to="common.Business") + + +class Business(models.Model): + """ + A Team can manage multiple Businesses + A Business can have multiple Brokerage Products + + # The IRS responsible entity that our accounts care about for issuing 1099s. + # We have this seperated from the Team as some Teams have different + # bank accounts + corporate entities for the activity of an app + """ + + id = models.BigAutoField(primary_key=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + + BUSINESS_KINDS = (("i", "Individual"), ("c", "Company")) + kind = models.CharField(max_length=1, choices=BUSINESS_KINDS, default="i") + name = models.CharField(max_length=255, blank=True, null=False) + + tax_number = models.CharField(max_length=20, blank=True, null=True) + + # BusinessBalances model + balance = models.JSONField(default=None, null=True) + # BusinessUserWalletBalances model + user_wallet_balance = models.JSONField(default=None, null=True) + + users_active_7d = models.IntegerField(default=None, null=True) + task_completes_7d = models.IntegerField(default=None, null=True) + # Net Earnings over the last 7 days (in USD Cents, this can be positive or negative) + balance_net_7d = models.IntegerField(default=None, null=True) + + +class BusinessAddress(models.Model): + id = models.BigAutoField(primary_key=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + + business = models.ForeignKey( + "common.Business", + null=True, + on_delete=models.SET_NULL, + ) + + # Location Details + line_1 = models.CharField(max_length=255, blank=True, null=True) + line_2 = models.CharField(max_length=255, blank=True, null=True) + city = models.CharField(max_length=255, blank=True, null=True) + country = models.CharField( + max_length=2, blank=True, null=True + ) # Validate this with pycountry + state = models.CharField(max_length=255, blank=True, null=True) + postal_code = models.CharField(max_length=12, blank=True, null=True) + phone_number = models.CharField(max_length=20, null=True) + + +class BankAccount(models.Model): + """ + A Business can have a single active Bank Account at the time. + This is used to deposit funds earned from the Business's Brokerage Products. + """ + + id = models.BigAutoField(primary_key=True) + uuid = models.UUIDField(default=uuid.uuid4, unique=True) + + business = models.ForeignKey( + "common.Business", + null=True, + on_delete=models.SET_NULL, + ) + + TRANSFER_METHOD = ( + (0, "ACH"), + (1, "Wire"), + ) + transfer_method = models.PositiveSmallIntegerField( + choices=TRANSFER_METHOD, default=0 + ) + + # ACH requirements + account_number = models.CharField(max_length=50, blank=True, null=True) + routing_number = models.CharField(max_length=50, blank=True, null=True) + + # Wire requirements + iban = models.CharField(max_length=50, blank=True, null=True) + swift = models.CharField(max_length=50, blank=True, null=True) diff --git a/generalresearch/gr_django/readme.MD b/generalresearch/gr_django/readme.MD new file mode 100644 index 0000000..1a6e682 --- /dev/null +++ b/generalresearch/gr_django/readme.MD @@ -0,0 +1,5 @@ +Run migrations with: +```shell +python -m generalresearch.gr_django.app.manage makemigrations common +python -m generalresearch.gr_django.app.manage migrate +```
\ No newline at end of file |
