mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-10-07 13:05:33 +00:00
* Port to Django 5.2 * Pin pluggy to 1.2.0 Any newer and the mystery importlib metadata error appears. Weird! >_> * Update for premailer changed default * Update view logic for is_ajax being changed to a template context processor * Port a few more tests to pytest proper Having two distinct test flavours is giving me a headache * Version 1 dockerfile Makes a VERY big image, I suspect we can optimise this a lot... * Optimise dockerfile a little lot a bit * fix(users): change logout link to POST request * fix(tests): fix some syntax errors in test code still got lots of failed tests :( * fix: replace deprecated Django APIs * ci: update Dockerfile * ci: update Dockerfile * fix(dependencies+tests): update EoL/vulnerable dependencies and improve test stability * Upgrade Python from 3.10 to 3.12 * Update frontend dependencies, replace node-sass with sass * chore(logging): ignore dangling obj reference warning from pypdf * ci: update compose.yml for prod deployment - Add Nginx as a reverse proxy - Add cert-selfsign.sh for generating self-signed certificates - Add certbot-issue.sh for Let's Encrypt certificate issuance and renewal - Add cron-install.sh and cron-uninstall.sh for system cron management - Add .env.example as an environment variable template * style: reformat code * ci: add more sleep trying to pass tests * ci: ignore browser-based tests during ci testing * fix: create home for the new user during Dockerfile building * chore: remove heroku conf file * fix: RIGS not franken anymore * fix: restore is_ajax as a boolean and split out the context processor * test: remove Selenium interaction tests and their CI workarounds * fix: harden production settings (CSRF origins, env casts, ADMINS) and drop dead debug toolbar code * deploy: serve static files from nginx, pin PGDATA, and make cert scripts loud on failure * build: switch .dockerignore to an allowlist * build: drop unused dependencies, soft-pin the rest and target Python 3.14 * build: move image to Python 3.14 / Node 24 and force DEBUG off * ci: add dependabot config for uv, npm, docker and actions * build: narrow Sass deprecation silencing to @import and require Node 24 * build: provide placeholder env for collectstatic now that DEBUG is off in the image * deploy: add plain-HTTP nginx config for local development and use it in compose * deploy: remove self-signed cert script * build: make the image multi-arch with official node and python base images * ci: lint and test on PRs, build the image on PRs and push it to GHCR on master * docs: add local running and sample data instructions * fix: report a form error instead of crashing when big power has no Power MIC * fix: upgrade pypdf and urllib3 to patched releases * fix: apply non-breaking npm audit fixes * fix: strip whitespace in ALLOWED_HOSTS and drop misleading HSTS preload * deploy: add a pyrigs healthcheck and make nginx wait for it * build: pin the uv image version * fix: correct the check-in person picker condition and use BeautifulSoup's string argument * refactor: replace unique_together with UniqueConstraint * build: replace pycodestyle with ruff and fix what it found Removes unused imports and variables, and fixes a few real problems it surfaced: - EventCheckIn.active() referenced an undefined name and raised NameError; it now returns whether the check-in has no end time - RIGS.admin defined EventChecklistAdmin twice; the second is now PowerTestRecordAdmin - RIGS/tests/conftest.py used date/timedelta without importing them - the signal-registering imports in apps.py are kept with noqa pycodestyle config in setup.cfg is dropped. * style: format the codebase with ruff * style: normalise line endings, trailing whitespace and end-of-file newlines * ci: run ruff and file hygiene through prek, and document it --------- Co-authored-by: Hang <me@hangxu.me> Co-authored-by: Joe Banks <joe@jb3.dev>
289 lines
9.4 KiB
Python
289 lines
9.4 KiB
Python
import random
|
|
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
from django.db import transaction
|
|
from django.db.utils import IntegrityError
|
|
from django.utils import timezone
|
|
from reversion import revisions as reversion
|
|
|
|
from RIGS import models as rigsmodels
|
|
from assets import models
|
|
from assets.models import get_available_asset_id
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Creates some sample data for testing"
|
|
|
|
categories = []
|
|
statuses = []
|
|
suppliers = []
|
|
connectors = []
|
|
assets = []
|
|
|
|
def handle(self, *args, **kwargs):
|
|
print("Generating sample assets data")
|
|
from django.conf import settings
|
|
|
|
if not (settings.DEBUG or settings.STAGING):
|
|
raise CommandError("You cannot run this command in production")
|
|
|
|
random.seed("Some object to see the random number generator")
|
|
|
|
with transaction.atomic():
|
|
self.create_categories()
|
|
self.create_statuses()
|
|
self.create_suppliers()
|
|
self.create_assets()
|
|
self.create_connectors()
|
|
self.create_cables()
|
|
print("Done generating sample assets data")
|
|
|
|
def create_categories(self):
|
|
choices = ["Case", "Video", "General", "Sound", "Lighting", "Rigging"]
|
|
for cat in choices:
|
|
self.categories.append(models.AssetCategory.objects.create(name=cat))
|
|
|
|
def create_statuses(self):
|
|
choices = [
|
|
("In Service", True, "success"),
|
|
("Lost", False, "warning"),
|
|
("Binned", False, "danger"),
|
|
("Sold", False, "danger"),
|
|
("Broken", False, "warning"),
|
|
]
|
|
for stat in choices:
|
|
self.statuses.append(
|
|
models.AssetStatus.objects.create(name=stat[0], should_show=stat[1], display_class=stat[2])
|
|
)
|
|
|
|
def create_suppliers(self):
|
|
choices = [
|
|
"Acme, inc.",
|
|
"Widget Corp",
|
|
"123 Warehousing",
|
|
"Demo Company",
|
|
"Smith and Co.",
|
|
"Foo Bars",
|
|
"ABC Telecom",
|
|
"Fake Brothers",
|
|
"QWERTY Logistics",
|
|
"Demo, inc.",
|
|
"Sample Company",
|
|
"Sample, inc",
|
|
"Acme Corp",
|
|
"Allied Biscuit",
|
|
"Ankh-Sto Associates",
|
|
"Extensive Enterprise",
|
|
"Galaxy Corp",
|
|
"Globo-Chem",
|
|
"Mr. Sparkle",
|
|
"Globex Corporation",
|
|
"LexCorp",
|
|
"LuthorCorp",
|
|
"North Central Positronics",
|
|
"Omni Consimer Products",
|
|
"Praxis Corporation",
|
|
"Sombra Corporation",
|
|
"Sto Plains Holdings",
|
|
"Tessier-Ashpool",
|
|
"Wayne Enterprises",
|
|
"Wentworth Industries",
|
|
"ZiffCorp",
|
|
"Bluth Company",
|
|
"Strickland Propane",
|
|
"Thatherton Fuels",
|
|
"Three Waters",
|
|
"Water and Power",
|
|
"Western Gas & Electric",
|
|
"Mammoth Pictures",
|
|
"Mooby Corp",
|
|
"Gringotts",
|
|
"Thrift Bank",
|
|
"Flowers By Irene",
|
|
"The Legitimate Businessmens Club",
|
|
"Osato Chemicals",
|
|
"Transworld Consortium",
|
|
"Universal Export",
|
|
"United Fried Chicken",
|
|
"Virtucon",
|
|
"Kumatsu Motors",
|
|
"Keedsler Motors",
|
|
"Powell Motors",
|
|
"Industrial Automation",
|
|
"Sirius Cybernetics Corporation",
|
|
"U.S. Robotics and Mechanical Men",
|
|
"Colonial Movers",
|
|
"Corellian Engineering Corporation",
|
|
"Incom Corporation",
|
|
"General Products",
|
|
"Leeding Engines Ltd.",
|
|
"Blammo", # noqa
|
|
"Input, Inc.",
|
|
"Mainway Toys",
|
|
"Videlectrix",
|
|
"Zevo Toys",
|
|
"Ajax",
|
|
"Axis Chemical Co.",
|
|
"Barrytron",
|
|
"Carrys Candles",
|
|
"Cogswell Cogs",
|
|
"Spacely Sprockets",
|
|
"General Forge and Foundry",
|
|
"Duff Brewing Company",
|
|
"Dunder Mifflin",
|
|
"General Services Corporation",
|
|
"Monarch Playing Card Co.",
|
|
"Krustyco",
|
|
"Initech",
|
|
"Roboto Industries",
|
|
"Primatech",
|
|
"Sonky Rubber Goods",
|
|
"St. Anky Beer",
|
|
"Stay Puft Corporation",
|
|
"Vandelay Industries",
|
|
"Wernham Hogg",
|
|
"Gadgetron",
|
|
"Burleigh and Stronginthearm",
|
|
"BLAND Corporation",
|
|
"Nordyne Defense Dynamics",
|
|
"Petrox Oil Company",
|
|
"Roxxon",
|
|
"McMahon and Tate",
|
|
"Sixty Second Avenue",
|
|
"Charles Townsend Agency",
|
|
"Spade and Archer",
|
|
"Megadodo Publications",
|
|
"Rouster and Sideways",
|
|
"C.H. Lavatory and Sons",
|
|
"Globo Gym American Corp",
|
|
"The New Firm",
|
|
"SpringShield",
|
|
"Compuglobalhypermeganet",
|
|
"Data Systems",
|
|
"Gizmonic Institute",
|
|
"Initrode",
|
|
"Taggart Transcontinental",
|
|
"Atlantic Northern",
|
|
"Niagular",
|
|
"Plow King",
|
|
"Big Kahuna Burger",
|
|
"Big T Burgers and Fries",
|
|
"Chez Quis",
|
|
"Chotchkies",
|
|
"The Frying Dutchman",
|
|
"Klimpys",
|
|
"The Krusty Krab",
|
|
"Monks Diner",
|
|
"Milliways",
|
|
"Minuteman Cafe",
|
|
"Taco Grande",
|
|
"Tip Top Cafe",
|
|
"Moes Tavern",
|
|
"Central Perk",
|
|
"Chasers",
|
|
] # noqa
|
|
for supplier in choices:
|
|
self.suppliers.append(models.Supplier.objects.create(name=supplier))
|
|
|
|
def create_assets(self):
|
|
asset_description = [
|
|
"Large cable",
|
|
"Shiny thing",
|
|
"New lights",
|
|
"Really expensive microphone",
|
|
"Box of fuse flaps",
|
|
"Expensive tool we didn't agree to buy",
|
|
"Cable drums",
|
|
"Boring amount of tape",
|
|
"Video stuff no one knows how to use",
|
|
"More amplifiers",
|
|
"Heatshrink",
|
|
]
|
|
|
|
for i in range(100):
|
|
with reversion.create_revision():
|
|
reversion.set_user(random.choice(rigsmodels.Profile.objects.all()))
|
|
asset_id = str(get_available_asset_id())
|
|
asset = models.Asset(
|
|
asset_id=asset_id,
|
|
description=random.choice(asset_description),
|
|
category=random.choice(self.categories),
|
|
status=random.choice(self.statuses),
|
|
date_acquired=timezone.now().date(),
|
|
)
|
|
|
|
if i % 4 == 0:
|
|
asset.parent = models.Asset.objects.order_by("?").first()
|
|
|
|
if i % 3 == 0:
|
|
asset.purchased_from = random.choice(self.suppliers)
|
|
|
|
asset.clean()
|
|
asset.save()
|
|
|
|
def create_connectors(self):
|
|
connectors = [
|
|
{"description": "13A UK", "current_rating": 13, "voltage_rating": 230, "num_pins": 3},
|
|
{"description": "16A", "current_rating": 16, "voltage_rating": 230, "num_pins": 3},
|
|
{"description": "32/3", "current_rating": 32, "voltage_rating": 400, "num_pins": 5},
|
|
{"description": "Socapex", "current_rating": 23, "voltage_rating": 600, "num_pins": 19},
|
|
]
|
|
for connector in connectors:
|
|
conn = models.Connector.objects.create(**connector)
|
|
conn.save()
|
|
self.connectors.append(conn)
|
|
|
|
def create_cables(self):
|
|
asset_description = [
|
|
"The worm",
|
|
"Harting without a cap",
|
|
"Heavy cable",
|
|
"Extension lead",
|
|
"IEC cable that we should remember to prep",
|
|
]
|
|
asset_prefixes = ["C", "C4P", "CBNC", "CDMX", "CDV", "CRCD", "CSOCA", "CXLR"]
|
|
|
|
csas = [0.75, 1.00, 1.25, 2.5, 4]
|
|
lengths = [1, 2, 5, 10, 15, 20, 25, 30, 50, 100]
|
|
cores = [3, 5]
|
|
circuits = [1, 2, 3, 6]
|
|
types = []
|
|
|
|
for i in range(len(self.connectors)):
|
|
types.append(
|
|
models.CableType.objects.create(
|
|
plug=random.choice(self.connectors),
|
|
socket=random.choice(self.connectors),
|
|
circuits=random.choice(circuits),
|
|
cores=random.choice(cores),
|
|
)
|
|
)
|
|
|
|
for i in range(100):
|
|
prefix = random.choice(asset_prefixes)
|
|
asset_id = get_available_asset_id(wanted_prefix=prefix)
|
|
asset = models.Asset(
|
|
asset_id=asset_id,
|
|
description=random.choice(asset_description),
|
|
category=random.choice(self.categories),
|
|
status=random.choice(self.statuses),
|
|
date_acquired=timezone.now().date(),
|
|
is_cable=True,
|
|
cable_type=random.choice(types),
|
|
csa=random.choice(csas),
|
|
length=random.choice(lengths),
|
|
)
|
|
|
|
if i % 4 == 0:
|
|
asset.parent = models.Asset.objects.order_by("?").first()
|
|
|
|
if i % 3 == 0:
|
|
asset.purchased_from = random.choice(self.suppliers)
|
|
|
|
with transaction.atomic():
|
|
try:
|
|
asset.clean()
|
|
asset.save()
|
|
except IntegrityError:
|
|
pass
|