from datetime import datetime
from django.core.management import BaseCommand
from ferrosoft.apps.ferrobase.models import Organization
from ferrosoft.apps.ferrobase.services.tenant_mgm import (
add_tenant,
TenantOptions,
SETTINGS_DATABASE_HOST,
DEFAULT_DATABASE_PORT,
STANDARD_FIXTURES,
)
[docs]
class Command(BaseCommand):
"""Management command that provisions a new tenant on the platform.
Creates the tenant record, sets up a dedicated PostgreSQL database, loads
the requested fixtures, and optionally configures contact details. The
organization must already exist in the master database.
"""
help = "Add tenants to Ferrosoft Platform"
[docs]
def add_arguments(self, parser):
parser.add_argument("name", type=str)
parser.add_argument("organization", type=str)
parser.add_argument(
"--fixtures",
default=STANDARD_FIXTURES,
help="Comma separated list of data fixtures to load",
type=lambda arg: [item for item in arg.split(",")],
)
parser.add_argument(
"--extra-fixtures",
default=[],
help="Comma separated list of data fixtures to load in addition to --fixtures",
type=lambda arg: [item for item in arg.split(",")],
)
parser.add_argument(
"--language",
default="en",
help="Language code of data fixtures",
type=str,
)
parser.add_argument(
"--id",
default="",
help="ID of newly created tenant (defaults to random ID)",
type=str,
)
parser.add_argument(
"--expiry",
default="",
help="Expiry date time of new tenant (defaults to no expiry)",
type=str,
)
parser.add_argument(
"--email",
default=None,
help="Contact email address",
type=str,
)
parser.add_argument(
"--firstname",
default="",
help="Contact first name",
type=str,
)
parser.add_argument(
"--lastname",
default="",
help="Contact last name",
type=str,
)
parser.add_argument(
"--company",
default="",
help="Contact company",
type=str,
)
parser.add_argument(
"--db-name",
default="",
help="Database name (by default derived from ID)",
type=str,
)
parser.add_argument(
"--db-host",
default="",
help="Database hostname (defaults to settings %s)" % SETTINGS_DATABASE_HOST,
type=str,
)
parser.add_argument(
"--db-port",
default=DEFAULT_DATABASE_PORT,
help="Database port",
type=int,
)
parser.add_argument(
"--db-username",
default="",
help="Database username (defaults to database name)",
type=str,
)
parser.add_argument(
"--db-password",
default="",
help="Database password",
type=str,
)
[docs]
def handle(self, *args, **options):
name = options["name"]
expiry = (
None if not options["expiry"] else datetime.fromisoformat(options["expiry"])
)
org = Organization.objects.filter(name=options["organization"]).first()
if org is None:
self.stdout.write(
self.style.ERROR("Organization not found: %s" % options["organization"])
)
return
try:
tenant = add_tenant(
TenantOptions(
id=options["id"],
name=name,
active=True,
expiry_date=expiry,
language=options["language"],
fixtures=options["fixtures"] + options["extra_fixtures"],
organization=org,
db_name=options["db_name"],
db_host=options["db_host"],
db_username=options["db_username"],
db_port=options["db_port"],
db_password=options["db_password"],
)
)
self.stdout.write(
self.style.SUCCESS("Created tenant %s with ID %s" % (tenant, tenant.pk))
)
except Exception as e:
self.stdout.write(
self.style.ERROR(
"Failed creating tenant %s: %s"
% (
name,
str(e),
)
)
)