mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-02-20 05:19:42 +00:00
Compare commits
43 Commits
optimisati
...
8c0c0941c2
| Author | SHA1 | Date | |
|---|---|---|---|
|
8c0c0941c2
|
|||
|
abb0e35690
|
|||
|
bec0d4aee5
|
|||
|
f1e43b707e
|
|||
| 796f5b44b0 | |||
| 6458f016f0 | |||
| 9ca953423f | |||
|
|
4c5d958c6d | ||
| 85ca7b0880 | |||
|
44f9509eda
|
|||
|
a2be4cbe5e
|
|||
|
|
bb2f369ab5 | ||
|
2fdb2f260f
|
|||
|
6de3cb5d8c
|
|||
|
7c38af66f6
|
|||
|
f1a624ec8f
|
|||
|
ab01beb2cd
|
|||
|
11636809ca
|
|||
|
d7458f6366
|
|||
| febf9cf3ed | |||
| 3322a5ddf8 | |||
|
|
673bee4215 | ||
|
|
bab31107f7 | ||
|
|
2d8473b698 | ||
| d81ecd9015 | |||
| b42c583897 | |||
| 57e966826e | |||
|
6a5de4a9d6
|
|||
| 56bbf4c17c | |||
|
|
698f0be281 | ||
|
|
483f06e96f | ||
|
|
22193f3c39 | ||
|
|
59b63fe7aa | ||
| 5976ce9ea2 | |||
|
780d05e27c
|
|||
| 8cfa4bd79d | |||
|
36f83ee59b
|
|||
|
6d768832f4
|
|||
|
38da8642fa
|
|||
|
f75e1d5bfc
|
|||
|
3f959f8d56
|
|||
|
b63a01120b
|
|||
| 911336ceec |
5
.github/workflows/django.yml
vendored
5
.github/workflows/django.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.9
|
python-version: 3.9.1
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
id: pcache
|
id: pcache
|
||||||
with:
|
with:
|
||||||
@@ -27,8 +27,7 @@ jobs:
|
|||||||
${{ runner.os }}-pipenv-
|
${{ runner.os }}-pipenv-
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip pipenv
|
||||||
pip install pipenv
|
|
||||||
pipenv install -d
|
pipenv install -d
|
||||||
# if: steps.pcache.outputs.cache-hit != 'true'
|
# if: steps.pcache.outputs.cache-hit != 'true'
|
||||||
- name: Cache Static Files
|
- name: Cache Static Files
|
||||||
|
|||||||
13
Pipfile
13
Pipfile
@@ -19,11 +19,10 @@ cssselect = "~=1.1.0"
|
|||||||
cssutils = "~=1.0.2"
|
cssutils = "~=1.0.2"
|
||||||
dj-database-url = "~=0.5.0"
|
dj-database-url = "~=0.5.0"
|
||||||
dj-static = "~=0.0.6"
|
dj-static = "~=0.0.6"
|
||||||
Django = "~=3.1.5"
|
Django = "~=3.1.12"
|
||||||
django-debug-toolbar = "~=3.2"
|
django-debug-toolbar = "~=3.2"
|
||||||
django-filter = "~=2.4.0"
|
django-filter = "~=2.4.0"
|
||||||
django-ical = "~=1.7.1"
|
django-ical = "~=1.7.1"
|
||||||
django-recaptcha = "~=2.0.6"
|
|
||||||
django-recurrence = "~=1.10.3"
|
django-recurrence = "~=1.10.3"
|
||||||
django-registration-redux = "~=2.9"
|
django-registration-redux = "~=2.9"
|
||||||
django-reversion = "~=3.0.9"
|
django-reversion = "~=3.0.9"
|
||||||
@@ -35,11 +34,11 @@ gunicorn = "~=20.0.4"
|
|||||||
icalendar = "~=4.0.7"
|
icalendar = "~=4.0.7"
|
||||||
idna = "~=2.10"
|
idna = "~=2.10"
|
||||||
importlib-metadata = "~=3.4.0"
|
importlib-metadata = "~=3.4.0"
|
||||||
lxml = "~=4.6.2"
|
lxml = "~=4.6.3"
|
||||||
Markdown = "~=3.3.3"
|
Markdown = "~=3.3.3"
|
||||||
msgpack = "~=1.0.2"
|
msgpack = "~=1.0.2"
|
||||||
pep517 = "~=0.9.1"
|
pep517 = "~=0.9.1"
|
||||||
Pillow = "~=8.1.0"
|
Pillow = "~=8.3.2"
|
||||||
premailer = "~=3.7.0"
|
premailer = "~=3.7.0"
|
||||||
progress = "~=1.5"
|
progress = "~=1.5"
|
||||||
psutil = "~=5.8.0"
|
psutil = "~=5.8.0"
|
||||||
@@ -57,12 +56,12 @@ retrying = "~=1.3.3"
|
|||||||
simplejson = "~=3.17.2"
|
simplejson = "~=3.17.2"
|
||||||
six = "~=1.15.0"
|
six = "~=1.15.0"
|
||||||
soupsieve = "~=2.1"
|
soupsieve = "~=2.1"
|
||||||
sqlparse = "~=0.4.1"
|
sqlparse = "~=0.4.2"
|
||||||
static3 = "~=0.7.0"
|
static3 = "~=0.7.0"
|
||||||
svg2rlg = "~=0.3"
|
svg2rlg = "~=0.3"
|
||||||
tini = "~=3.0.1"
|
tini = "~=3.0.1"
|
||||||
tornado = "~=6.1"
|
tornado = "~=6.1"
|
||||||
urllib3 = "~=1.26.2"
|
urllib3 = "~=1.26.5"
|
||||||
whitenoise = "~=5.2.0"
|
whitenoise = "~=5.2.0"
|
||||||
yolk = "~=0.4.3"
|
yolk = "~=0.4.3"
|
||||||
"z3c.rml" = "~=4.1.2"
|
"z3c.rml" = "~=4.1.2"
|
||||||
@@ -77,6 +76,8 @@ zipp = "~=3.4.0"
|
|||||||
"zope.schema" = "~=6.0.1"
|
"zope.schema" = "~=6.0.1"
|
||||||
sentry-sdk = "*"
|
sentry-sdk = "*"
|
||||||
diff-match-patch = "*"
|
diff-match-patch = "*"
|
||||||
|
python-barcode = "*"
|
||||||
|
django-hCaptcha = "*"
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
selenium = "~=3.141.0"
|
selenium = "~=3.141.0"
|
||||||
|
|||||||
776
Pipfile.lock
generated
776
Pipfile.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -65,8 +65,8 @@ INSTALLED_APPS = (
|
|||||||
'debug_toolbar',
|
'debug_toolbar',
|
||||||
'registration',
|
'registration',
|
||||||
'reversion',
|
'reversion',
|
||||||
'captcha',
|
|
||||||
'widget_tweaks',
|
'widget_tweaks',
|
||||||
|
'hcaptcha',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE = (
|
MIDDLEWARE = (
|
||||||
@@ -186,12 +186,13 @@ LOGOUT_URL = '/user/logout/'
|
|||||||
|
|
||||||
ACCOUNT_ACTIVATION_DAYS = 7
|
ACCOUNT_ACTIVATION_DAYS = 7
|
||||||
|
|
||||||
# reCAPTCHA settings
|
# CAPTCHA settings
|
||||||
RECAPTCHA_PUBLIC_KEY = env('RECAPTCHA_PUBLIC_KEY', default="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI") # If not set, use development key
|
if DEBUG or CI:
|
||||||
RECAPTCHA_PRIVATE_KEY = env('RECAPTCHA_PUBLIC_KEY', default="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe") # If not set, use development key
|
HCAPTCHA_SITEKEY = '10000000-ffff-ffff-ffff-000000000001'
|
||||||
NOCAPTCHA = True
|
HCAPTCHA_SECRET = '0x0000000000000000000000000000000000000000'
|
||||||
|
else:
|
||||||
SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error']
|
HCAPTCHA_SITEKEY = env('HCAPTCHA_SITEKEY')
|
||||||
|
HCAPTCHA_SECRET = env('HCAPTCHA_SECRET')
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
EMAILER_TEST = False
|
EMAILER_TEST = False
|
||||||
|
|||||||
@@ -55,7 +55,13 @@ class InvoiceDetail(generic.DetailView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(InvoiceDetail, self).get_context_data(**kwargs)
|
context = super(InvoiceDetail, self).get_context_data(**kwargs)
|
||||||
context['page_title'] = "Invoice {} ({})".format(self.object.display_id, self.object.invoice_date.strftime("%d/%m/%Y"))
|
context['page_title'] = "Invoice {} ({}) ".format(self.object.display_id, self.object.invoice_date.strftime("%d/%m/%Y"))
|
||||||
|
if self.object.void:
|
||||||
|
context['page_title'] += "<span class='badge badge-warning float-right'>VOID</span>"
|
||||||
|
elif self.object.is_closed:
|
||||||
|
context['page_title'] += "<span class='badge badge-success float-right'>PAID</span>"
|
||||||
|
else:
|
||||||
|
context['page_title'] += "<span class='badge badge-info float-right'>OUTSTANDING</span>"
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@@ -173,24 +179,7 @@ class InvoiceWaiting(generic.ListView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.get_objects()
|
return self.model.objects.waiting_invoices()
|
||||||
|
|
||||||
def get_objects(self):
|
|
||||||
# TODO find a way to select items
|
|
||||||
events = self.model.objects.filter(
|
|
||||||
(
|
|
||||||
Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end
|
|
||||||
Q(end_date__lte=datetime.date.today()) # Has end date, finishes before
|
|
||||||
) & Q(invoice__isnull=True) & # Has not already been invoiced
|
|
||||||
Q(is_rig=True) # Is a rig (not non-rig)
|
|
||||||
|
|
||||||
).order_by('start_date') \
|
|
||||||
.select_related('person',
|
|
||||||
'organisation',
|
|
||||||
'venue', 'mic') \
|
|
||||||
.prefetch_related('items')
|
|
||||||
|
|
||||||
return events
|
|
||||||
|
|
||||||
|
|
||||||
class InvoiceEvent(generic.View):
|
class InvoiceEvent(generic.View):
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ class EventRiskAssessmentDetail(generic.DetailView):
|
|||||||
model = models.RiskAssessment
|
model = models.RiskAssessment
|
||||||
template_name = 'risk_assessment_detail.html'
|
template_name = 'risk_assessment_detail.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(EventRiskAssessmentDetail, self).get_context_data(**kwargs)
|
||||||
|
context['page_title'] = "Risk Assessment for Event <a href='{}'>{} {}</a>".format(self.object.event.get_absolute_url(), self.object.event.display_id, self.object.event.name)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class EventRiskAssessmentList(generic.ListView):
|
class EventRiskAssessmentList(generic.ListView):
|
||||||
paginate_by = 20
|
paginate_by = 20
|
||||||
@@ -107,7 +112,7 @@ class EventChecklistDetail(generic.DetailView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(EventChecklistDetail, self).get_context_data(**kwargs)
|
context = super(EventChecklistDetail, self).get_context_data(**kwargs)
|
||||||
context['page_title'] = "Event Checklist for Event {} {}".format(self.object.event.display_id, self.object.event.name)
|
context['page_title'] = "Event Checklist for Event <a href='{}'>{} {}</a>".format(self.object.event.get_absolute_url(), self.object.event.display_id, self.object.event.name)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
67
RIGS/migrations/0040_auto_20210302_1148.py
Normal file
67
RIGS/migrations/0040_auto_20210302_1148.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Generated by Django 3.1.7 on 2021-03-02 11:48
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def postgres_migration_prep(apps, schema_editor):
|
||||||
|
model = apps.get_model("RIGS", "Event")
|
||||||
|
for field in ["auth_request_to", "collector", "description", "notes", "purchase_order"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "EventAuthorisation")
|
||||||
|
for field in ["account_code", "uni_id"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "EventChecklist")
|
||||||
|
for field in ["extinguishers_location", "hs_location", "w1_description", "w2_description", "w3_description"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "EventItem")
|
||||||
|
for field in ["description"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "Organisation")
|
||||||
|
for field in ["address", "email", "notes", "phone"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "Payment")
|
||||||
|
for field in ["method"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "Person")
|
||||||
|
for field in ["address", "email", "notes", "phone"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "Profile")
|
||||||
|
for field in ["phone"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "RiskAssessment")
|
||||||
|
for field in ["general_notes", "persons_responsible_structures", "power_notes", "rigging_plan", "sound_notes"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
model = apps.get_model("RIGS", "Venue")
|
||||||
|
for field in ["address", "email", "notes", "phone"]:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('RIGS', '0039_auto_20210123_1910'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(postgres_migration_prep, migrations.RunPython.noop)
|
||||||
|
]
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 3.1.5 on 2021-02-06 10:43
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('RIGS', '0039_auto_20210123_1910'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='profile',
|
|
||||||
name='dark_theme',
|
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.5 on 2021-02-08 16:03
|
# Generated by Django 3.1.7 on 2021-03-02 12:04
|
||||||
|
|
||||||
import RIGS.models
|
import RIGS.models
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
@@ -7,10 +7,27 @@ from django.db import migrations, models
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('RIGS', '0040_profile_dark_theme'),
|
('RIGS', '0040_auto_20210302_1148'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='event',
|
||||||
|
name='meet_info',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='event',
|
||||||
|
name='payment_method',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='event',
|
||||||
|
name='payment_received',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='profile',
|
||||||
|
name='dark_theme',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='event',
|
model_name='event',
|
||||||
name='auth_request_to',
|
name='auth_request_to',
|
||||||
@@ -26,26 +43,11 @@ class Migration(migrations.Migration):
|
|||||||
name='description',
|
name='description',
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=''),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
|
||||||
model_name='event',
|
|
||||||
name='meet_info',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=255),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='event',
|
model_name='event',
|
||||||
name='notes',
|
name='notes',
|
||||||
field=models.TextField(blank=True, default=''),
|
field=models.TextField(blank=True, default=''),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
|
||||||
model_name='event',
|
|
||||||
name='payment_method',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=255),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='event',
|
|
||||||
name='payment_received',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=255),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='event',
|
model_name='event',
|
||||||
name='purchase_order',
|
name='purchase_order',
|
||||||
@@ -144,7 +146,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='profile',
|
model_name='profile',
|
||||||
name='phone',
|
name='phone',
|
||||||
field=models.CharField(default='', max_length=13, null=True),
|
field=models.CharField(blank=True, default='', max_length=13),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='riskassessment',
|
model_name='riskassessment',
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 3.1.7 on 2021-03-02 11:21
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('RIGS', '0041_auto_20210208_1603'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='profile',
|
|
||||||
name='phone',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=13),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -278,6 +278,19 @@ class EventManager(models.Manager):
|
|||||||
).count()
|
).count()
|
||||||
return event_count
|
return event_count
|
||||||
|
|
||||||
|
def waiting_invoices(self):
|
||||||
|
events = self.filter(
|
||||||
|
(
|
||||||
|
models.Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end
|
||||||
|
models.Q(end_date__lte=datetime.date.today()) # Or has end date, finishes before
|
||||||
|
) & models.Q(invoice__isnull=True) & # Has not already been invoiced
|
||||||
|
models.Q(is_rig=True) # Is a rig (not non-rig)
|
||||||
|
).order_by('start_date') \
|
||||||
|
.select_related('person', 'organisation', 'venue', 'mic') \
|
||||||
|
.prefetch_related('items')
|
||||||
|
|
||||||
|
return events
|
||||||
|
|
||||||
|
|
||||||
@reversion.register(follow=['items'])
|
@reversion.register(follow=['items'])
|
||||||
class Event(models.Model, RevisionMixin):
|
class Event(models.Model, RevisionMixin):
|
||||||
@@ -312,7 +325,6 @@ class Event(models.Model, RevisionMixin):
|
|||||||
end_time = models.TimeField(blank=True, null=True)
|
end_time = models.TimeField(blank=True, null=True)
|
||||||
access_at = models.DateTimeField(blank=True, null=True)
|
access_at = models.DateTimeField(blank=True, null=True)
|
||||||
meet_at = models.DateTimeField(blank=True, null=True)
|
meet_at = models.DateTimeField(blank=True, null=True)
|
||||||
meet_info = models.CharField(max_length=255, blank=True, default='')
|
|
||||||
|
|
||||||
# Crew management
|
# Crew management
|
||||||
checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True,
|
checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True,
|
||||||
@@ -321,8 +333,6 @@ class Event(models.Model, RevisionMixin):
|
|||||||
verbose_name="MIC", on_delete=models.CASCADE)
|
verbose_name="MIC", on_delete=models.CASCADE)
|
||||||
|
|
||||||
# Monies
|
# Monies
|
||||||
payment_method = models.CharField(max_length=255, blank=True, default='')
|
|
||||||
payment_received = models.CharField(max_length=255, blank=True, default='')
|
|
||||||
purchase_order = models.CharField(max_length=255, blank=True, default='', verbose_name='PO')
|
purchase_order = models.CharField(max_length=255, blank=True, default='', verbose_name='PO')
|
||||||
collector = models.CharField(max_length=255, blank=True, default='', verbose_name='collected by')
|
collector = models.CharField(max_length=255, blank=True, default='', verbose_name='collected by')
|
||||||
|
|
||||||
|
|||||||
BIN
RIGS/static/imgs/square_logo.png
Normal file
BIN
RIGS/static/imgs/square_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
RIGS/static/imgs/wof2014-1-small.jpg
Normal file
BIN
RIGS/static/imgs/wof2014-1-small.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
@@ -1,9 +1,10 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load invoices_waiting from filters %}
|
||||||
|
|
||||||
{% block titleheader %}
|
{% block titleheader %}
|
||||||
<a class="navbar-brand" href="/">RIGS</a>
|
<a class="navbar-brand" style="margin-left: auto; margin-right: auto;" href="/">RIGS</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block titleelements %}
|
{% block titleelements %}
|
||||||
@@ -45,11 +46,11 @@
|
|||||||
{% if perms.RIGS.view_invoice %}
|
{% if perms.RIGS.view_invoice %}
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownInvoices" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownInvoices" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
Invoices
|
Invoices <span class="badge badge-danger badge-pill">{% invoices_waiting %}</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdownInvoices">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdownInvoices">
|
||||||
{% if perms.RIGS.add_invoice %}
|
{% if perms.RIGS.add_invoice %}
|
||||||
<a class="dropdown-item" href="{% url 'invoice_waiting' %}"><span class="fas fa-briefcase text-danger"></span> Waiting</a>
|
<a class="dropdown-item text-nowrap" href="{% url 'invoice_waiting' %}"><span class="fas fa-briefcase text-danger"></span> Waiting <span class="badge badge-danger badge-pill">{% invoices_waiting %}</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="dropdown-item" href="{% url 'invoice_list' %}"><span class="fas fa-pound-sign text-warning"></span> Outstanding</a>
|
<a class="dropdown-item" href="{% url 'invoice_list' %}"><span class="fas fa-pound-sign text-warning"></span> Outstanding</a>
|
||||||
<a class="dropdown-item" href="{% url 'invoice_archive' %}"><span class="fas fa-book"></span> Archive</a>
|
<a class="dropdown-item" href="{% url 'invoice_archive' %}"><span class="fas fa-book"></span> Archive</a>
|
||||||
|
|||||||
@@ -32,7 +32,11 @@
|
|||||||
</dd>
|
</dd>
|
||||||
<dt class="col-6">{{ object|help_text:'power_mic' }}</dt>
|
<dt class="col-6">{{ object|help_text:'power_mic' }}</dt>
|
||||||
<dd class="col-6">
|
<dd class="col-6">
|
||||||
|
{% if object.power_mic %}
|
||||||
<a href="{% url 'profile_detail' object.power_mic.pk %}">{{ object.power_mic.name }}</a>
|
<a href="{% url 'profile_detail' object.power_mic.pk %}">{{ object.power_mic.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
None
|
||||||
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p>List vehicles and their drivers</p>
|
<p>List vehicles and their drivers</p>
|
||||||
|
|||||||
@@ -244,12 +244,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% elif event.riskassessment.event_size == 1 %}
|
{% else %}
|
||||||
<div class="row my-3" id="size-1">
|
<div class="row my-3" id="size-1">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
{% if event.riskassessment.event_size == 1 %}
|
||||||
<div class="card border-warning">
|
<div class="card border-warning">
|
||||||
<div class="card-header">Electrical Checks <small>for ‘Medium’ TEC Events </small></div>
|
<div class="card-header">Electrical Checks <small>for ‘Medium’ TEC Events </small></div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
{% else %}
|
||||||
|
<div class="card border-danger">
|
||||||
|
<div class="card-header">Electrical Checks <small>for ‘Large’ TEC Events</small></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="alert alert-danger"><strong>Here be dragons. Ensure you have appeased the Power Gods before continuing... (If you didn't check with a Supervisor, <em>you cannot continue your event!</em>)</strong></div>
|
||||||
|
{% endif %}
|
||||||
{% include 'partials/checklist_checkbox.html' with formitem=form.source_rcd %}
|
{% include 'partials/checklist_checkbox.html' with formitem=form.source_rcd %}
|
||||||
{% include 'partials/checklist_checkbox.html' with formitem=form.labelling %}
|
{% include 'partials/checklist_checkbox.html' with formitem=form.labelling %}
|
||||||
{% include 'partials/checklist_checkbox.html' with formitem=form.earthing %}
|
{% include 'partials/checklist_checkbox.html' with formitem=form.earthing %}
|
||||||
@@ -339,17 +346,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
|
||||||
<div class="row my-3" id="size-2">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card border-danger">
|
|
||||||
<div class="card-header">Electrical Checks <small>for ‘Large’ TEC Events</small></div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Outside the scope of this assessment. <strong>I really hope you checked with a supervisor...</strong></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-sm-12 text-right">
|
<div class="col-sm-12 text-right">
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
||||||
{% load linkornone from filters %}
|
|
||||||
{% load namewithnotes from filters %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row my-3 py-3">
|
<div class="row my-3 py-3">
|
||||||
@@ -14,50 +12,7 @@
|
|||||||
{% if object.is_rig and perms.RIGS.view_event %}
|
{% if object.is_rig and perms.RIGS.view_event %}
|
||||||
{# only need contact details for a rig #}
|
{# only need contact details for a rig #}
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{% if event.person %}
|
{% include 'partials/contact_details.html' %}
|
||||||
<div class="card card-default mb-3">
|
|
||||||
<div class="card-header">Contact Details</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<dl class="row">
|
|
||||||
<dt class="col-sm-6">Person</dt>
|
|
||||||
<dd class="col-sm-6">
|
|
||||||
{% if object.person %}
|
|
||||||
<a href="{% url 'person_detail' object.person.pk %}" class="modal-href">
|
|
||||||
{{ object.person|namewithnotes:'person_detail' }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-6">Email</dt>
|
|
||||||
<dd class="col-sm-6">{{ object.person.email|linkornone:'mailto' }}</dd>
|
|
||||||
<dt class="col-sm-6">Phone Number</dt>
|
|
||||||
<dd class="col-sm-6">{{ object.person.phone|linkornone:'tel' }}</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if event.organisation %}
|
|
||||||
<div class="card card-default">
|
|
||||||
<div class="card-header">Organisation</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<dl class="row">
|
|
||||||
<dt class="col-sm-6">Organisation</dt>
|
|
||||||
<dd class="col-sm-6">
|
|
||||||
{% if object.organisation %}
|
|
||||||
<a href="{% url 'organisation_detail' object.organisation.pk %}" class="modal-href">
|
|
||||||
{{ object.organisation|namewithnotes:'organisation_detail' }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-6">Email</dt>
|
|
||||||
<dd class="col-sm-6">{{ object.organisation.email|linkornone:'mailto' }}</dd>
|
|
||||||
<dt class="col-sm-6">Phone Number</dt>
|
|
||||||
<dd class="col-sm-6">{{ object.organisation.phone|linkornone:'tel' }}</dd>
|
|
||||||
<dt class="col-sm-6">Has SU Account</dt>
|
|
||||||
<dd class="col-sm-6">{{ event.organisation.union_account|yesno|capfirst }}</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|||||||
@@ -27,18 +27,26 @@
|
|||||||
const matches = window.matchMedia("(prefers-reduced-motion: reduce)").matches || window.matchMedia("(update: slow)").matches;
|
const matches = window.matchMedia("(prefers-reduced-motion: reduce)").matches || window.matchMedia("(update: slow)").matches;
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
dur = matches ? 0 : 500;
|
dur = matches ? 0 : 500;
|
||||||
{% if not object.pk and not form.errors %}
|
{% if object.pk %}
|
||||||
$('.form-hws').slideUp(dur, function () {
|
// Editing
|
||||||
$('.form-is_rig').slideUp(dur);
|
{% if not object.is_rig %}
|
||||||
});
|
|
||||||
{% elif not object.pk and form.errors %}
|
|
||||||
if ($('#{{form.is_rig.auto_id}}').attr('checked') !== 'checked') {
|
|
||||||
$('.form-is_rig').hide();
|
$('.form-is_rig').hide();
|
||||||
}
|
{% endif %}
|
||||||
{% endif %}
|
//Creation
|
||||||
{% if not object.pk %}
|
{% else %}
|
||||||
|
// If there were errors, apply the previous Rig/not-Rig selection
|
||||||
|
{% if form.errors %}
|
||||||
|
$('.form-hws').show();
|
||||||
|
if ($('#{{form.is_rig.auto_id}}').attr('checked') !== 'checked') {
|
||||||
|
$('.form-is_rig').hide();
|
||||||
|
}
|
||||||
|
{% else %}
|
||||||
|
//Initial hide
|
||||||
|
$('.form-hws').slideUp(dur);
|
||||||
|
{% endif %}
|
||||||
|
//Button handling
|
||||||
$('#is_rig-selector button').on('click', function () {
|
$('#is_rig-selector button').on('click', function () {
|
||||||
$('.form-non_rig').slideDown(dur);
|
$('.form-non_rig').slideDown(dur); //Non rig stuff also needed for rig, so always slide down
|
||||||
if ($(this).data('is_rig') === 1) {
|
if ($(this).data('is_rig') === 1) {
|
||||||
$('#{{form.is_rig.auto_id}}').prop('checked', true);
|
$('#{{form.is_rig.auto_id}}').prop('checked', true);
|
||||||
if ($('.form-non_rig').is(':hidden')) {
|
if ($('.form-non_rig').is(':hidden')) {
|
||||||
@@ -48,7 +56,6 @@
|
|||||||
}
|
}
|
||||||
$('.form-hws, .form-hws .form-is_rig').css('overflow', 'visible');
|
$('.form-hws, .form-hws .form-is_rig').css('overflow', 'visible');
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$('#{{form.is_rig.auto_id}}').prop('checked', false);
|
$('#{{form.is_rig.auto_id}}').prop('checked', false);
|
||||||
$('.form-is_rig').slideUp(dur);
|
$('.form-is_rig').slideUp(dur);
|
||||||
}
|
}
|
||||||
@@ -62,13 +69,6 @@
|
|||||||
$('[data-toggle="tooltip"]').tooltip();
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<noscript>
|
|
||||||
<style>
|
|
||||||
.form-hws {
|
|
||||||
display: inherit !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</noscript>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|||||||
@@ -2,102 +2,88 @@
|
|||||||
{% load button from filters %}
|
{% load button from filters %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-sm-12">
|
<div class="row py-4">
|
||||||
<div class="row justify-content-end py-3">
|
<div class="col-sm-12 text-right px-0">
|
||||||
<div class="col-sm-4 text-right">
|
<div class="btn-group">
|
||||||
<div class="btn-group btn-page">
|
<a href="{% url 'event_detail' object.event.pk %}" class="btn btn-primary">Open Event Page <span class="fas fa-eye"></span></a>
|
||||||
<a href="{% url 'invoice_delete' object.pk %}" class="btn btn-danger" title="Delete Invoice">
|
<a href="{% url 'invoice_delete' object.pk %}" class="btn btn-danger" title="Delete Invoice">
|
||||||
<span class="fas fa-times"></span> <span
|
<span class="fas fa-times"></span> <span
|
||||||
class="d-none d-sm-inline">Delete</span>
|
class="d-none d-sm-inline">Delete</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'invoice_void' object.pk %}" class="btn btn-warning" title="Void Invoice">
|
<a href="{% url 'invoice_void' object.pk %}" class="btn btn-warning" title="Void Invoice">
|
||||||
<span class="fas fa-ban"></span> <span
|
<span class="fas fa-ban"></span> <span
|
||||||
class="d-none d-sm-inline">Void</span>
|
class="d-none d-sm-inline">Void</span>
|
||||||
</a>
|
</a>
|
||||||
{% button 'print' url='invoice_print' pk=object.pk %}
|
{% button 'print' url='invoice_print' pk=object.pk %}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="card card-default">
|
|
||||||
<div class="card-header">Invoice Details<span class="float-right">
|
|
||||||
{% if object.void %}(VOID){% elif object.is_closed %}(PAID){% else %}(OUTSTANDING){% endif %}
|
|
||||||
</span></div>
|
|
||||||
<div class="card-body">
|
|
||||||
{% if object.event.organisation %}
|
|
||||||
{{ object.event.organisation.name }}<br/>
|
|
||||||
{{ object.event.organisation.address|linebreaksbr }}
|
|
||||||
{% else %}
|
|
||||||
{{ object.event.person.name }}<br/>
|
|
||||||
{{ object.event.person.address|linebreaksbr }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
{% include 'partials/event_details.html' %}
|
|
||||||
</div>
|
|
||||||
{% if object.event.internal %}
|
|
||||||
<div class="col-sm-6">
|
|
||||||
{% include 'partials/auth_details.html' %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row py-4">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="card card-default">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="text-right py-3">
|
|
||||||
<a href="{% url 'payment_create' %}?invoice={{ object.pk }}"
|
|
||||||
class="btn btn-success modal-href"
|
|
||||||
data-target="#{{ form.person.id_for_label }}">
|
|
||||||
<span class="fas fa-plus"></span> Add
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Date</th>
|
|
||||||
<th scope="col">Amount</th>
|
|
||||||
<th scope="col">Method</th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for payment in object.payment_set.all %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{{ payment.date }}</th>
|
|
||||||
<td>{{ payment.amount|floatformat:2 }}</td>
|
|
||||||
<td>{{ payment.get_method_display }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'payment_delete' payment.pk %}" class="btn btn-small btn-danger"><span class="fas fa-times"></span></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
<tr>
|
|
||||||
<td class="text-right"><strong>Balance:</strong></td>
|
|
||||||
<td>{{ object.balance|floatformat:2 }}</td>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="card">
|
|
||||||
{% with object.event as object %}
|
|
||||||
{% include 'item_table.html' %}
|
|
||||||
{% endwith %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 text-right">
|
|
||||||
{% include 'partials/last_edited.html' with target="invoice_history" %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="row py-4">
|
||||||
|
{% with object.event as object %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% include 'partials/contact_details.html' %}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% include 'partials/event_details.html' %}
|
||||||
|
</div>
|
||||||
|
{% if object.event.internal %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% include 'partials/auth_details.html' %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
</div>
|
||||||
|
<div class="row py-4">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="card card-default">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="text-right py-3">
|
||||||
|
<a href="{% url 'payment_create' %}?invoice={{ object.pk }}"
|
||||||
|
class="btn btn-success modal-href"
|
||||||
|
data-target="#{{ form.person.id_for_label }}">
|
||||||
|
<span class="fas fa-plus"></span> Add
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
<th scope="col">Amount</th>
|
||||||
|
<th scope="col">Method</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for payment in object.payment_set.all %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ payment.date }}</th>
|
||||||
|
<td>{{ payment.amount|floatformat:2 }}</td>
|
||||||
|
<td>{{ payment.get_method_display }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'payment_delete' payment.pk %}" class="btn btn-small btn-danger"><span class="fas fa-times"></span></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-right"><strong>Balance:</strong></td>
|
||||||
|
<td>{{ object.balance|floatformat:2 }}</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="card">
|
||||||
|
{% with object.event as object %}
|
||||||
|
{% include 'item_table.html' %}
|
||||||
|
{% endwith %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 text-right">
|
||||||
|
{% include 'partials/last_edited.html' with target="invoice_history" %}
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
47
RIGS/templates/partials/contact_details.html
Normal file
47
RIGS/templates/partials/contact_details.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{% load linkornone from filters %}
|
||||||
|
{% load namewithnotes from filters %}
|
||||||
|
|
||||||
|
{% if object.person %}
|
||||||
|
<div class="card card-default mb-3">
|
||||||
|
<div class="card-header">Person Details</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<dl class="row">
|
||||||
|
<dt class="col-sm-6">Person</dt>
|
||||||
|
<dd class="col-sm-6">
|
||||||
|
{% if object.person %}
|
||||||
|
<a href="{% url 'person_detail' object.person.pk %}" class="modal-href">
|
||||||
|
{{ object.person|namewithnotes:'person_detail' }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-6">Email</dt>
|
||||||
|
<dd class="col-sm-6">{{ object.person.email|linkornone:'mailto' }}</dd>
|
||||||
|
<dt class="col-sm-6">Phone Number</dt>
|
||||||
|
<dd class="col-sm-6">{{ object.person.phone|linkornone:'tel' }}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if object.organisation %}
|
||||||
|
<div class="card card-default">
|
||||||
|
<div class="card-header">Organisation Details</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<dl class="row">
|
||||||
|
<dt class="col-sm-6">Organisation</dt>
|
||||||
|
<dd class="col-sm-6">
|
||||||
|
{% if object.organisation %}
|
||||||
|
<a href="{% url 'organisation_detail' object.organisation.pk %}" class="modal-href">
|
||||||
|
{{ object.organisation|namewithnotes:'organisation_detail' }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-6">Email</dt>
|
||||||
|
<dd class="col-sm-6">{{ object.organisation.email|linkornone:'mailto' }}</dd>
|
||||||
|
<dt class="col-sm-6">Phone Number</dt>
|
||||||
|
<dd class="col-sm-6">{{ object.organisation.phone|linkornone:'tel' }}</dd>
|
||||||
|
<dt class="col-sm-6">Has SU Account</dt>
|
||||||
|
<dd class="col-sm-6">{{ event.organisation.union_account|yesno|capfirst }}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
@@ -47,5 +47,7 @@
|
|||||||
class="fas fa-pound-sign"></span>
|
class="fas fa-pound-sign"></span>
|
||||||
<span class="d-none d-sm-inline">Invoice</span></a>
|
<span class="d-none d-sm-inline">Invoice</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<a href="https://docs.google.com/forms/d/e/1FAIpQLSf-TBOuJZCTYc2L8DWdAaC3_Werq0ulsUs8-6G85I6pA9WVsg/viewform" class="btn btn-danger"><span class="fas fa-file-invoice-dollar"></span> <span class="d-none d-sm-inline">Subhire Insurance Form</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
<span class="badge badge-success">PO: {{ event.purchase_order }}</span>
|
<span class="badge badge-success">PO: {{ event.purchase_order }}</span>
|
||||||
{% elif event.authorised %}
|
{% elif event.authorised %}
|
||||||
<span class="badge badge-success">Authorisation: Complete <span class="fas fa-check"></span></span>
|
<span class="badge badge-success">Authorisation: Complete <span class="fas fa-check"></span></span>
|
||||||
|
{% elif event.authorisation and event.authorisation.amount != event.total and event.authorisation.last_edited_at > event.auth_request_at %}
|
||||||
|
<span class="badge badge-warning"> Authorisation: Issue <span class="fas fa-exclamation-circle"></span></span>
|
||||||
|
{% elif event.auth_request_to %}
|
||||||
|
<span class="badge badge-info"> Authorisation: Sent <span class="fas fa-paper-plane"></span></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge badge-danger">Authorisation: <span class="fas fa-times"></span></span>
|
<span class="badge badge-danger">Authorisation: <span class="fas fa-times"></span></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -30,25 +30,25 @@
|
|||||||
<th scope="row" id="event_number">{{ event.display_id }}</th>
|
<th scope="row" id="event_number">{{ event.display_id }}</th>
|
||||||
<!--Dates & Times-->
|
<!--Dates & Times-->
|
||||||
<td id="event_dates">
|
<td id="event_dates">
|
||||||
<span class="text-nowrap">Start: <strong>{{ event.start_date|date:"D d/m/Y" }}</strong>
|
<span class="text-nowrap">Start: <strong>{{ event.start_date|date:"D d/m/Y" }}
|
||||||
{% if event.has_start_time %}
|
{% if event.has_start_time %}
|
||||||
{{ event.start_time|date:"H:i" }}
|
{{ event.start_time|date:"H:i" }}
|
||||||
{% endif %}
|
{% endif %}</strong>
|
||||||
</span>
|
</span>
|
||||||
{% if event.end_date %}
|
{% if event.end_date %}
|
||||||
<br>
|
<br>
|
||||||
<span class="text-nowrap">End: {% if event.end_date != event.start_date %}<strong>{{ event.end_date|date:"D d/m/Y" }}</strong>{% endif %}
|
<span class="text-nowrap">End: {% if event.end_date != event.start_date %}<strong>{{ event.end_date|date:"D d/m/Y" }}{% endif %}
|
||||||
{% if event.has_end_time %}
|
{% if event.has_end_time %}
|
||||||
{{ event.end_time|date:"H:i" }}
|
{{ event.end_time|date:"H:i" }}
|
||||||
{% endif %}
|
{% endif %}</strong>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not event.cancelled %}
|
{% if not event.cancelled %}
|
||||||
{% if event.meet_at %}
|
{% if event.meet_at %}
|
||||||
<br><span>Crew meet: <strong>{{ event.meet_at|date:"H:i" }}</strong> {{ event.meet_at|date:"(d/m/Y)" }}</span>
|
<br><span class="text-nowrap">Meet: <strong>{{ event.meet_at|date:"D d/m/Y H:i" }}</strong></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if event.access_at %}
|
{% if event.access_at %}
|
||||||
<br><span>Access at: <strong>{{ event.access_at|date:"H:i" }}</strong> {{ event.access_at|date:"(d/m/Y)" }}</span>
|
<br><span class="text-nowrap">Access: <strong>{{ event.access_at|date:" D d/m/Y H:i" }}</strong></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
@@ -67,9 +67,9 @@
|
|||||||
</h4>
|
</h4>
|
||||||
{% if event.is_rig and not event.cancelled %}
|
{% if event.is_rig and not event.cancelled %}
|
||||||
<h5>
|
<h5>
|
||||||
{{ event.person.name }}
|
<a href="{{ event.person.get_absolute_url }}">{{ event.person.name }}</a>
|
||||||
{% if event.organisation %}
|
{% if event.organisation %}
|
||||||
for {{ event.organisation.name }}
|
for <a href="{{ event.organisation.get_absolute_url }}">{{ event.organisation.name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h5>
|
</h5>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif event.is_rig %}
|
{% elif event.is_rig %}
|
||||||
<span class="fas fa-exclamation"></span>
|
<span class="fas fa-user-slash"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
||||||
{% block title %}Risk Assessment for Event N{{ object.event.pk|stringformat:"05d" }} {{ object.event.name }}{% endblock %}
|
|
||||||
{% load help_text from filters %}
|
{% load help_text from filters %}
|
||||||
{% load yesnoi from filters %}
|
{% load yesnoi from filters %}
|
||||||
{% load linkornone from filters %}
|
{% load linkornone from filters %}
|
||||||
@@ -7,7 +6,6 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row py-3">
|
<div class="row py-3">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h3>Risk Assessment for Event N{{ object.event.pk|stringformat:"05d" }} {{ object.event.name }}</h3>
|
|
||||||
<div class="card card-default mb-3">
|
<div class="card card-default mb-3">
|
||||||
<div class="card-header">General</div>
|
<div class="card-header">General</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -51,11 +49,11 @@
|
|||||||
<dd class="col-sm-6">
|
<dd class="col-sm-6">
|
||||||
{{ object.power_mic.name|default:'None' }}
|
{{ object.power_mic.name|default:'None' }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-6">{{ object|help_text:'generators' }}</dt>
|
<dt class="col-sm-6">{{ object|help_text:'outside' }}</dt>
|
||||||
<dd class="col-sm-6">
|
<dd class="col-sm-6">
|
||||||
{{ object.outside|yesnoi:'invert' }}
|
{{ object.outside|yesnoi:'invert' }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-6">{{ object|help_text:'outside' }}</dt>
|
<dt class="col-sm-6">{{ object|help_text:'generators' }}</dt>
|
||||||
<dd class="col-sm-6">
|
<dd class="col-sm-6">
|
||||||
{{ object.generators|yesnoi:'invert' }}
|
{{ object.generators|yesnoi:'invert' }}
|
||||||
</dd>
|
</dd>
|
||||||
@@ -97,58 +95,64 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-default mb-3">
|
<div class="row">
|
||||||
<div class="card-header">Site Details</div>
|
<div class="col-lg-6 col-12">
|
||||||
<div class="card-body">
|
<div class="card card-default mb-3">
|
||||||
<dl class="row">
|
<div class="card-header">Site Details</div>
|
||||||
<dt class="col-sm-6">{{ object|help_text:'known_venue' }}</dt>
|
<div class="card-body">
|
||||||
<dd class="col-sm-6">
|
<dl class="row">
|
||||||
{{ object.known_venue|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'known_venue' }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'safe_loading'|safe }}</dt>
|
{{ object.known_venue|yesnoi:'invert' }}
|
||||||
<dd class="col-sm-6">
|
</dd>
|
||||||
{{ object.safe_loading|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'safe_loading'|safe }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'safe_storage' }}</dt>
|
{{ object.safe_loading|yesnoi:'invert' }}
|
||||||
<dd class="col-sm-6">
|
</dd>
|
||||||
{{ object.safe_storage|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'safe_storage' }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'area_outside_of_control' }}</dt>
|
{{ object.safe_storage|yesnoi:'invert' }}
|
||||||
<dd class="col-sm-6">
|
</dd>
|
||||||
{{ object.area_outside_of_control|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'area_outside_of_control' }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'barrier_required' }}</dt>
|
{{ object.area_outside_of_control|yesnoi:'invert' }}
|
||||||
<dd class="col-sm-6">
|
</dd>
|
||||||
{{ object.barrier_required|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'barrier_required' }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'nonstandard_emergency_procedure' }}</dt>
|
{{ object.barrier_required|yesnoi:'invert' }}
|
||||||
<dd class="col-sm-6">
|
</dd>
|
||||||
{{ object.nonstandard_emergency_procedure|yesnoi:'invert' }}
|
<dt class="col-10">{{ object|help_text:'nonstandard_emergency_procedure' }}</dt>
|
||||||
</dd>
|
<dd class="col-2">
|
||||||
</dl>
|
{{ object.nonstandard_emergency_procedure|yesnoi:'invert' }}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-lg-6 col-12">
|
||||||
<div class="card card-default mb-3">
|
<div class="card card-default mb-3">
|
||||||
<div class="card-header">Structures</div>
|
<div class="card-header">Structures</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-sm-6">{{ object|help_text:'special_structures' }}</dt>
|
<dt class="col-10">{{ object|help_text:'special_structures' }}</dt>
|
||||||
<dd class="col-sm-6">
|
<dd class="col-2">
|
||||||
{{ object.special_structures|yesnoi:'invert' }}
|
{{ object.special_structures|yesnoi:'invert' }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-6">{{ object|help_text:'suspended_structures' }}</dt>
|
<dt class="col-10">{{ object|help_text:'suspended_structures' }}</dt>
|
||||||
<dd class="col-sm-6">
|
<dd class="col-2">
|
||||||
{{ object.suspended_structures|yesnoi:'invert' }}
|
{{ object.suspended_structures|yesnoi:'invert' }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-6">{{ object|help_text:'persons_responsible_structures' }}</dt>
|
<dt class="col-12">{{ object|help_text:'persons_responsible_structures' }}</dt>
|
||||||
<dd class="col-sm-6">
|
<dd class="col-12">
|
||||||
{{ object.persons_responsible_structures.name|default:'N/A'|linebreaks }}
|
{{ object.persons_responsible_structures.name|default:'N/A'|linebreaks }}
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-6">{{ object|help_text:'rigging_plan'|safe }}</dt>
|
<dt class="col-12">{{ object|help_text:'rigging_plan'|safe }}</dt>
|
||||||
<dd class="col-6">
|
<dd class="col-12">
|
||||||
{{ object.rigging_plan|linkornone }}
|
{{ object.rigging_plan|linkornone|default:'N/A' }}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,13 +11,12 @@
|
|||||||
|
|
||||||
{% block preload_js %}
|
{% block preload_js %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<script src="{% static 'js/selects.js' %}" async></script>
|
<script src="{% static 'js/selects.js' %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<script src="{% static 'js/autocompleter.js' %}"></script>
|
<script src="{% static 'js/autocompleter.js' %}"></script>
|
||||||
<script src="{% static 'js/tooltip.js' %}"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function parseBool(str) {
|
function parseBool(str) {
|
||||||
|
|||||||
@@ -217,3 +217,8 @@ def button(type, url=None, pk=None, clazz="", icon=None, text="", id=None, style
|
|||||||
elif type == 'submit':
|
elif type == 'submit':
|
||||||
return {'submit': True, 'class': 'btn-primary', 'icon': 'fa-save', 'text': 'Save', 'id': id, 'style': style}
|
return {'submit': True, 'class': 'btn-primary', 'icon': 'fa-save', 'text': 'Save', 'id': id, 'style': style}
|
||||||
return {'target': url, 'pk': pk, 'class': clazz, 'icon': icon, 'text': text, 'id': id, 'style': style}
|
return {'target': url, 'pk': pk, 'class': clazz, 'icon': icon, 'text': text, 'id': id, 'style': style}
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def invoices_waiting():
|
||||||
|
return len(models.Event.objects.waiting_invoices())
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class EventDetail(BasePage):
|
|||||||
|
|
||||||
# TODO Refactor into regions to match template fragmentation
|
# TODO Refactor into regions to match template fragmentation
|
||||||
_event_name_selector = (By.XPATH, '//h2')
|
_event_name_selector = (By.XPATH, '//h2')
|
||||||
_person_panel_selector = (By.XPATH, '//div[contains(text(), "Contact Details")]/..')
|
_person_panel_selector = (By.XPATH, '//div[contains(text(), "Person Details")]/..')
|
||||||
_name_selector = (By.XPATH, '//dt[text()="Person"]/following-sibling::dd[1]')
|
_name_selector = (By.XPATH, '//dt[text()="Person"]/following-sibling::dd[1]')
|
||||||
_email_selector = (By.XPATH, '//dt[text()="Email"]/following-sibling::dd[1]')
|
_email_selector = (By.XPATH, '//dt[text()="Email"]/following-sibling::dd[1]')
|
||||||
_phone_selector = (By.XPATH, '//dt[text()="Phone Number"]/following-sibling::dd[1]')
|
_phone_selector = (By.XPATH, '//dt[text()="Phone Number"]/following-sibling::dd[1]')
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ def add_default(apps, schema_editor):
|
|||||||
Connector = apps.get_model('assets', 'Connector')
|
Connector = apps.get_model('assets', 'Connector')
|
||||||
for cable_type in CableType.objects.all():
|
for cable_type in CableType.objects.all():
|
||||||
if cable_type.plug is None:
|
if cable_type.plug is None:
|
||||||
cable_type.plug = Connector.first()
|
cable_type.plug = Connector.objects.first()
|
||||||
if cable_type.socket is None:
|
if cable_type.socket is None:
|
||||||
cable_type.socket = Connector.first()
|
cable_type.socket = Connector.objects.first()
|
||||||
cable_type.save()
|
cable_type.save()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
23
assets/migrations/0020_auto_20210302_1201.py
Normal file
23
assets/migrations/0020_auto_20210302_1201.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 3.1.7 on 2021-03-02 12:01
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def postgres_migration_prep(apps, schema_editor):
|
||||||
|
model = apps.get_model("assets", "Supplier")
|
||||||
|
fields = ["address", "email", "notes", "phone"]
|
||||||
|
for field in fields:
|
||||||
|
filter_param = {"{}__isnull".format(field): True}
|
||||||
|
update_param = {field: ""}
|
||||||
|
model.objects.filter(**filter_param).update(**update_param)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('assets', '0019_fix_cabletype'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(postgres_migration_prep, migrations.RunPython.noop)
|
||||||
|
]
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.5 on 2021-02-08 16:03
|
# Generated by Django 3.1.7 on 2021-03-02 12:04
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@@ -7,7 +7,7 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('assets', '0019_fix_cabletype'),
|
('assets', '0020_auto_20210302_1201'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@@ -49,7 +49,7 @@ class Supplier(models.Model, RevisionMixin):
|
|||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('supplier_list')
|
return reverse('supplier_detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -82,6 +82,9 @@ class CableType(models.Model):
|
|||||||
else:
|
else:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('cable_type_detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
|
|
||||||
def get_available_asset_id(wanted_prefix=""):
|
def get_available_asset_id(wanted_prefix=""):
|
||||||
sql = """
|
sql = """
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
{% load widget_tweaks %}
|
{% load widget_tweaks %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="row justify-content-end">
|
||||||
|
{% include 'partials/asset_buttons.html' %}
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
{% include 'partials/asset_detail_form.html' %}
|
{% include 'partials/asset_detail_form.html' %}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
})
|
})
|
||||||
.ajaxSelectPicker({
|
.ajaxSelectPicker({
|
||||||
ajax: {
|
ajax: {
|
||||||
url: '{% url 'asset_search_json' %}',
|
url: "{% url 'asset_search_json' %}",
|
||||||
type: "GET",
|
type: "GET",
|
||||||
data: function () {
|
data: function () {
|
||||||
let params = {
|
let params = {
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
{% button 'edit' url='asset_update' pk=object.asset_id %}
|
{% button 'edit' url='asset_update' pk=object.asset_id %}
|
||||||
{% button 'duplicate' url='asset_duplicate' pk=object.asset_id %}
|
{% button 'duplicate' url='asset_duplicate' pk=object.asset_id %}
|
||||||
<a type="button" class="btn btn-info" href="{% url 'asset_audit' object.asset_id %}"><i class="fas fa-certificate"></i> Audit</a>
|
<a type="button" class="btn btn-info" href="{% url 'asset_audit' object.asset_id %}"><span class="fas fa-certificate"></span> Audit</a>
|
||||||
|
{% if object.is_cable %}
|
||||||
|
<a type="button" class="btn btn-primary" href="{% url 'generate_label' object.asset_id %}"><span class="fas fa-barcode"></span> Generate Label</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if create or edit or duplicate %}
|
{% if create or edit or duplicate %}
|
||||||
|
|||||||
@@ -17,11 +17,9 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Cable Type</dt>
|
<dt>Cable Type</dt>
|
||||||
<dd>{{ object.cable_type|default_if_none:'-' }}</dd>
|
<dd>{% if object.cable_type %}<a href="{{object.cable_type.get_absolute_url}}">{{ object.cable_type }}</a>{%else%}-{%endif%}</dd>
|
||||||
|
|
||||||
<dt>Length</dt>
|
<dt>Length</dt>
|
||||||
<dd>{{ object.length|default_if_none:'-' }}m</dd>
|
<dd>{{ object.length|default_if_none:'-' }}m</dd>
|
||||||
|
|
||||||
<dt>Cross Sectional Area</dt>
|
<dt>Cross Sectional Area</dt>
|
||||||
<dd>{{ object.csa|default_if_none:'-' }}mm²</dd>
|
<dd>{{ object.csa|default_if_none:'-' }}mm²</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
@@ -28,13 +28,13 @@
|
|||||||
|
|
||||||
<dt>Children</dt>
|
<dt>Children</dt>
|
||||||
{% if object.asset_parent.all %}
|
{% if object.asset_parent.all %}
|
||||||
|
<div style="max-height: 200px; overflow-y: auto; -webkit-overflow-scrolling: touch; ">
|
||||||
{% for child in object.asset_parent.all %}
|
{% for child in object.asset_parent.all %}
|
||||||
<dd>
|
<dd>
|
||||||
<a href="{% url 'asset_detail' child.asset_id %}">
|
<a href="{% url 'asset_detail' child.asset_id %}">{{ child }}</a>
|
||||||
{{ child.asset_id }} - {{ child.description }}
|
|
||||||
</a>
|
|
||||||
</dd>
|
</dd>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<dd><span>-</span></dd>
|
<dd><span>-</span></dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{% load widget_tweaks %}
|
{% load widget_tweaks %}
|
||||||
|
{% load linkornone from filters %}
|
||||||
<div class="card mb-2">
|
<div class="card mb-2">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
Purchase Details
|
Purchase Details
|
||||||
@@ -51,14 +52,11 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Purchased From</dt>
|
<dt>Purchased From</dt>
|
||||||
<dd>{{ object.purchased_from|default_if_none:'-' }}</dd>
|
<dd>{% if object.purchased_from %}<a href="{{object.purchased_from.get_absolute_url}}">{{ object.purchased_from }}</a>{%else%}-{%endif%}</dd>
|
||||||
|
|
||||||
<dt>Purchase Price</dt>
|
<dt>Purchase Price</dt>
|
||||||
<dd>£{{ object.purchase_price|default_if_none:'-' }}</dd>
|
<dd>£{{ object.purchase_price|default_if_none:'-' }}</dd>
|
||||||
|
|
||||||
<dt>Salvage Value</dt>
|
<dt>Salvage Value</dt>
|
||||||
<dd>£{{ object.salvage_value|default_if_none:'-' }}</dd>
|
<dd>£{{ object.salvage_value|default_if_none:'-' }}</dd>
|
||||||
|
|
||||||
<dt>Date Acquired</dt>
|
<dt>Date Acquired</dt>
|
||||||
<dd>{{ object.date_acquired|default_if_none:'-' }}</dd>
|
<dd>{{ object.date_acquired|default_if_none:'-' }}</dd>
|
||||||
{% if object.date_sold %}
|
{% if object.date_sold %}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ urlpatterns = [
|
|||||||
(views.AssetEdit.as_view()), name='asset_update'),
|
(views.AssetEdit.as_view()), name='asset_update'),
|
||||||
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.add_asset')
|
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.add_asset')
|
||||||
(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
||||||
|
path('asset/id/<str:pk>/label', login_required(views.GenerateLabel.as_view()), name='generate_label'),
|
||||||
|
|
||||||
path('cabletype/list/', login_required(views.CableTypeList.as_view()), name='cable_type_list'),
|
path('cabletype/list/', login_required(views.CableTypeList.as_view()), name='cable_type_list'),
|
||||||
path('cabletype/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'),
|
path('cabletype/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import simplejson
|
import simplejson
|
||||||
|
import random
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
@@ -9,6 +10,11 @@ from django.utils import timezone
|
|||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
from barcode import Code39
|
||||||
|
from barcode.writer import ImageWriter
|
||||||
|
|
||||||
from PyRIGS.views import GenericListView, GenericDetailView, GenericUpdateView, GenericCreateView, ModalURLMixin, \
|
from PyRIGS.views import GenericListView, GenericDetailView, GenericUpdateView, GenericCreateView, ModalURLMixin, \
|
||||||
is_ajax, OEmbedView
|
is_ajax, OEmbedView
|
||||||
@@ -338,3 +344,37 @@ class CableTypeUpdate(generic.UpdateView):
|
|||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse("cable_type_detail", kwargs={"pk": self.object.pk})
|
return reverse("cable_type_detail", kwargs={"pk": self.object.pk})
|
||||||
|
|
||||||
|
|
||||||
|
class GenerateLabel(generic.View):
|
||||||
|
def get(self, request, pk):
|
||||||
|
black = (0, 0, 0)
|
||||||
|
white = (255, 255, 255)
|
||||||
|
size = (700, 200)
|
||||||
|
font = ImageFont.truetype("static/fonts/OpenSans-Regular.tff", 20)
|
||||||
|
obj = get_object_or_404(models.Asset, asset_id=pk)
|
||||||
|
|
||||||
|
asset_id = "Asset: {}".format(obj.asset_id)
|
||||||
|
length = "Length: {}m".format(obj.length)
|
||||||
|
csa = "CSA: {}mm²".format(obj.csa)
|
||||||
|
|
||||||
|
image = Image.new("RGB", size, white)
|
||||||
|
logo = Image.open("static/imgs/square_logo.png")
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
|
||||||
|
draw.text((210, 140), asset_id, fill=black, font=font)
|
||||||
|
draw.text((210, 170), length, fill=black, font=font)
|
||||||
|
draw.text((350, 170), csa, fill=black, font=font)
|
||||||
|
draw.multiline_text((500, 140), "TEC PA & Lighting\n(0115) 84 68720", fill=black, font=font)
|
||||||
|
|
||||||
|
barcode = Code39(str(obj.asset_id), writer=ImageWriter())
|
||||||
|
|
||||||
|
logo_size = (200, 200)
|
||||||
|
image.paste(logo.resize(logo_size, Image.ANTIALIAS))
|
||||||
|
barcode_image = barcode.render(writer_options={"quiet_zone": 0, "write_text": False})
|
||||||
|
width, height = barcode_image.size
|
||||||
|
image.paste(barcode_image.crop((0, 0, width, 135)), (int(((size[0] + logo_size[0]) - width) / 2), 0))
|
||||||
|
|
||||||
|
response = HttpResponse(content_type="image/png")
|
||||||
|
image.save(response, "PNG")
|
||||||
|
return response
|
||||||
|
|||||||
@@ -119,4 +119,18 @@
|
|||||||
background: #222;
|
background: #222;
|
||||||
color: $gray-100;
|
color: $gray-100;
|
||||||
}
|
}
|
||||||
|
input:-webkit-autofill,
|
||||||
|
input:-webkit-autofill:hover,
|
||||||
|
input:-webkit-autofill:focus,
|
||||||
|
textarea:-webkit-autofill,
|
||||||
|
textarea:-webkit-autofill:hover,
|
||||||
|
textarea:-webkit-autofill:focus,
|
||||||
|
select:-webkit-autofill,
|
||||||
|
select:-webkit-autofill:hover,
|
||||||
|
select:-webkit-autofill:focus {
|
||||||
|
border: 1px solid $info;
|
||||||
|
-webkit-text-fill-color: white;
|
||||||
|
-webkit-box-shadow: 0 0 0px 1000px rgba($info, .3) inset;
|
||||||
|
transition: background-color 5000s ease-in-out 0s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,11 @@ svg {
|
|||||||
white-space: no-wrap;
|
white-space: no-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.fas {
|
||||||
|
padding-left: 0.1em !important;
|
||||||
|
padding-right: 0.1em !important;
|
||||||
|
}
|
||||||
|
|
||||||
html.embedded {
|
html.embedded {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/png" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
<link rel="icon" type="image/png" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
||||||
<link rel="apple-touch-icon" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
<link rel="apple-touch-icon" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
||||||
<link rel="preload" href="{% static 'fonts/fa-solid-900.woff2' %}" as="font" type="font/woff2" crossorigin>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/screen.css' %}">
|
<link rel="stylesheet" type="text/css" href="{% static 'css/screen.css' %}">
|
||||||
{% block css %}
|
{% block css %}
|
||||||
@@ -32,26 +31,26 @@
|
|||||||
<a class="skip-link" href='#main'>Skip to content</a>
|
<a class="skip-link" href='#main'>Skip to content</a>
|
||||||
{% include "analytics.html" %}
|
{% include "analytics.html" %}
|
||||||
{% block navbar %}
|
{% block navbar %}
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark flex-nowrap" role="navigation">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark" role="navigation">
|
||||||
<a class="navbar-brand" href="{% if request.user.is_authenticated %}https://members.nottinghamtec.co.uk{%else%}https://nottinghamtec.co.uk{%endif%}">
|
|
||||||
<img src="{% static 'imgs/logo.webp' %}" width="40" height="40" alt="TEC's Logo: Serif 'TEC' vertically next to a blue box with the words 'PA and Lighting', surrounded by graduated rings">
|
|
||||||
</a>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% block titleheader %}
|
<a class="navbar-brand" style="position: absolute; left:0.5em; top: 2px;" href="{% if request.user.is_authenticated %}https://members.nottinghamtec.co.uk{%else%}https://nottinghamtec.co.uk{%endif%}">
|
||||||
{% endblock %}
|
<img src="{% static 'imgs/logo.webp' %}" width="40" height="40" alt="TEC's Logo: Serif 'TEC' vertically next to a blue box with the words 'PA and Lighting', surrounded by graduated rings" id="logo">
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
</a>
|
||||||
<span class="navbar-toggler-icon"></span>
|
{% block titleheader %}
|
||||||
</button>
|
{% endblock %}
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
<button class="navbar-toggler ml-auto" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation" onclick="document.getElementById('logo').classList.toggle('d-none');">
|
||||||
<ul class="navbar-nav">
|
<span class="navbar-toggler-icon"></span>
|
||||||
{% block titleelements %}
|
</button>
|
||||||
{% endblock %}
|
<div class="collapse navbar-collapse justify-content-between" id="navbarSupportedContent">
|
||||||
</ul>
|
<ul class="navbar-nav">
|
||||||
<ul class="navbar-nav ml-auto">
|
{% block titleelements %}
|
||||||
{% block titleelements_right %}
|
{% endblock %}
|
||||||
{% endblock %}
|
</ul>
|
||||||
</ul>
|
<ul class="navbar-nav align-self-end">
|
||||||
</div>
|
{% block titleelements_right %}
|
||||||
|
{% endblock %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<form id="searchForm" class="form-inline flex-nowrap mx-md-3 px-2 border border-light rounded" role="form" method="GET" action="{% url 'event_archive' %}">
|
<form id="searchForm" class="form-inline flex-nowrap mx-md-3 px-2 border border-light rounded w-75" role="form" method="GET" action="{% url 'event_archive' %}">
|
||||||
<div class="input-group input-group-sm flex-nowrap">
|
<div class="input-group input-group-sm flex-nowrap">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<input id="id_search_input" type="search" name="q" class="form-control form-control-sm" placeholder="Search..." value="{{ request.GET.q }}" />
|
<input id="id_search_input" type="search" name="q" class="form-control form-control-sm" placeholder="Search..." value="{{ request.GET.q }}" />
|
||||||
</div>
|
</div>
|
||||||
<select id="search-options" class="custom-select form-control" style="border-top-right-radius: 0px; border-bottom-right-radius: 0px; width: 20ch;">
|
<select id="search-options" class="custom-select form-control" style="border-top-right-radius: 0px; border-bottom-right-radius: 0px; width: 15ch;">
|
||||||
<option selected data-action="{% url 'event_archive' %}" href="#">Events</option>
|
<option selected data-action="{% url 'event_archive' %}" href="#">Events</option>
|
||||||
<option data-action="{% url 'person_list' %}" href="#">People</option>
|
<option data-action="{% url 'person_list' %}" href="#">People</option>
|
||||||
<option data-action="{% url 'organisation_list' %}" href="#">Organisations</option>
|
<option data-action="{% url 'organisation_list' %}" href="#">Organisations</option>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-info form-control form-control-sm btn-sm w-25" style="border-top-left-radius: 0px;border-bottom-left-radius: 0px;"><span class="fas fa-search"></span><span class="sr-only"> Search</span></button>
|
<button class="btn btn-info form-control form-control-sm btn-sm w-25" style="border-top-left-radius: 0px;border-bottom-left-radius: 0px;"><span class="fas fa-search"></span><span class="sr-only"> Search</span></button>
|
||||||
<a href="{% url 'search_help' %}" class="nav-link modal-href ml-2"><span class="fas fa-question-circle"></span></a>
|
<a href="{% url 'search_help' %}" class="nav-link modal-href ml-1"><span class="fas fa-question-circle"></span></a>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,36 @@
|
|||||||
{% extends 'base_rigs.html' %}
|
{% extends 'base_rigs.html' %}
|
||||||
{% load widget_tweaks %}
|
{% load widget_tweaks %}
|
||||||
|
{% load static %}
|
||||||
{% block title %}Registration{% endblock %}
|
{% block title %}Registration{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-sm-10 col-sm-offset-1">
|
<div style="background-image: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)), url({% static 'imgs/wof2014-1-small.jpg' %}); background-repeat: no-repeat; background-size: cover; width: 100vw; height: 100vh; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw; margin-top: -24px; padding-top: 24px;">
|
||||||
<h3>New User Registration</h3>
|
<div class="container">
|
||||||
{% if form.errors or supplement_form.errors %}
|
<div class="card">
|
||||||
<div class="alert alert-danger">
|
<h3 class="card-header">New User Registration</h3>
|
||||||
{{form.errors}}
|
<div class="card-body">
|
||||||
{{supplement_form.errors}}
|
{% if form.errors or supplement_form.errors %}
|
||||||
</div>
|
<div class="alert alert-danger">
|
||||||
{% endif %}
|
{{form.errors}}
|
||||||
|
{{supplement_form.errors}}
|
||||||
<div class="col-sm-8 col-sm-offset-2">
|
</div>
|
||||||
<form action="" method="post" class="" role="form">{% csrf_token %}
|
{% endif %}
|
||||||
{% for field in form %}
|
<div class="col-sm-8 col-sm-offset-2">
|
||||||
<div class="form-group">
|
<form method="post" role="form">{% csrf_token %}
|
||||||
<label for="{{ field.id_for_label }}" class="col-form-label col-sm-4">{{ field.label }}</label>
|
{% for field in form %}
|
||||||
<div class="controls col-sm-8">
|
<div class="form-group form-row">
|
||||||
{% render_field field class+="form-control" placeholder=field.label %}
|
<label for="{{ field.id_for_label }}" class="col-form-label col-sm-4">{{ field.label }}</label>
|
||||||
</div>
|
<div class="controls col-sm-8">
|
||||||
</div>
|
{% render_field field class+="form-control" placeholder=field.label %}
|
||||||
{% endfor %}
|
</div>
|
||||||
<p><input type="submit" value="Register" class="btn btn-primary pull-right"></p>
|
</div>
|
||||||
</form>
|
{% endfor %}
|
||||||
|
<p><input type="submit" value="Register" class="btn btn-primary pull-right"></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,15 +1,24 @@
|
|||||||
from captcha.fields import ReCaptchaField
|
from hcaptcha.fields import hCaptchaField
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
|
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
|
||||||
UserChangeForm, UserCreationForm)
|
UserChangeForm, UserCreationForm)
|
||||||
|
from django.conf import settings
|
||||||
from registration.forms import RegistrationFormUniqueEmail
|
from registration.forms import RegistrationFormUniqueEmail
|
||||||
|
|
||||||
from RIGS import models
|
from RIGS import models
|
||||||
|
|
||||||
|
|
||||||
|
class CaptchaField(hCaptchaField):
|
||||||
|
def validate(self, value):
|
||||||
|
# Skip validation if we're testing FIXME: Arona, y u so lazy
|
||||||
|
if settings.HCAPTCHA_SITEKEY != '10000000-ffff-ffff-ffff-000000000001':
|
||||||
|
super().validate(value)
|
||||||
|
|
||||||
# Registration
|
# Registration
|
||||||
|
|
||||||
|
|
||||||
class ProfileRegistrationFormUniqueEmail(RegistrationFormUniqueEmail):
|
class ProfileRegistrationFormUniqueEmail(RegistrationFormUniqueEmail):
|
||||||
captcha = ReCaptchaField()
|
hcaptcha = CaptchaField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Profile
|
model = models.Profile
|
||||||
@@ -41,7 +50,7 @@ class EmbeddedAuthenticationForm(CheckApprovedForm):
|
|||||||
|
|
||||||
|
|
||||||
class PasswordReset(PasswordResetForm):
|
class PasswordReset(PasswordResetForm):
|
||||||
captcha = ReCaptchaField(label='Captcha')
|
hcaptcha = CaptchaField()
|
||||||
|
|
||||||
|
|
||||||
class ProfileCreationForm(UserCreationForm):
|
class ProfileCreationForm(UserCreationForm):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<li class="nav-item dropdown" id="user">
|
<li class="nav-item dropdown align-self-end" id="user">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
Hi {{ user.first_name }}
|
Hi {{ user.first_name }}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.test import LiveServerTestCase
|
from django.test import LiveServerTestCase
|
||||||
|
from django.test.utils import override_settings
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
|
|
||||||
from PyRIGS.tests.base import create_browser
|
from PyRIGS.tests.base import create_browser
|
||||||
@@ -13,14 +15,12 @@ from RIGS import models
|
|||||||
class UserRegistrationTest(LiveServerTestCase):
|
class UserRegistrationTest(LiveServerTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.browser = create_browser()
|
self.browser = create_browser()
|
||||||
|
self.browser.implicitly_wait(5) # Set implicit wait session wide
|
||||||
self.browser.implicitly_wait(3) # Set implicit wait session wide
|
|
||||||
os.environ['RECAPTCHA_TESTING'] = 'True'
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.browser.quit()
|
self.browser.quit()
|
||||||
os.environ['RECAPTCHA_TESTING'] = 'False'
|
|
||||||
|
|
||||||
|
@override_settings(DEBUG=True)
|
||||||
def test_registration(self):
|
def test_registration(self):
|
||||||
# Navigate to the registration page
|
# Navigate to the registration page
|
||||||
self.browser.get(self.live_server_url + '/user/register/')
|
self.browser.get(self.live_server_url + '/user/register/')
|
||||||
@@ -61,9 +61,11 @@ class UserRegistrationTest(LiveServerTestCase):
|
|||||||
last_name.send_keys('Smith')
|
last_name.send_keys('Smith')
|
||||||
initials.send_keys('JS')
|
initials.send_keys('JS')
|
||||||
# phone.send_keys('0123456789')
|
# phone.send_keys('0123456789')
|
||||||
self.browser.execute_script(
|
time.sleep(1)
|
||||||
"return function() {jQuery('#g-recaptcha-response').val('PASSED'); return 0}()")
|
self.browser.switch_to.frame(self.browser.find_element_by_tag_name("iframe"))
|
||||||
|
self.browser.find_element_by_id('anchor').click()
|
||||||
|
self.browser.switch_to.default_content()
|
||||||
|
time.sleep(3)
|
||||||
# Submit incorrect form
|
# Submit incorrect form
|
||||||
submit = self.browser.find_element_by_xpath("//input[@type='submit']")
|
submit = self.browser.find_element_by_xpath("//input[@type='submit']")
|
||||||
submit.click()
|
submit.click()
|
||||||
@@ -85,9 +87,6 @@ class UserRegistrationTest(LiveServerTestCase):
|
|||||||
# Correct error
|
# Correct error
|
||||||
password1.send_keys('correcthorsebatterystaple')
|
password1.send_keys('correcthorsebatterystaple')
|
||||||
password2.send_keys('correcthorsebatterystaple')
|
password2.send_keys('correcthorsebatterystaple')
|
||||||
self.browser.execute_script("console.log('Hello, world!')")
|
|
||||||
self.browser.execute_script(
|
|
||||||
"return function() {jQuery('#g-recaptcha-response').val('PASSED'); return 0}()")
|
|
||||||
|
|
||||||
# Submit again
|
# Submit again
|
||||||
password2.send_keys(Keys.ENTER)
|
password2.send_keys(Keys.ENTER)
|
||||||
@@ -126,8 +125,6 @@ class UserRegistrationTest(LiveServerTestCase):
|
|||||||
# Expected to fail as not approved
|
# Expected to fail as not approved
|
||||||
username.send_keys('TestUsername')
|
username.send_keys('TestUsername')
|
||||||
password.send_keys('correcthorsebatterystaple')
|
password.send_keys('correcthorsebatterystaple')
|
||||||
self.browser.execute_script(
|
|
||||||
"return function() {jQuery('#g-recaptcha-response').val('PASSED'); return 0}()")
|
|
||||||
password.send_keys(Keys.ENTER)
|
password.send_keys(Keys.ENTER)
|
||||||
|
|
||||||
# Test approval
|
# Test approval
|
||||||
@@ -149,8 +146,6 @@ class UserRegistrationTest(LiveServerTestCase):
|
|||||||
username.send_keys('TestUsername')
|
username.send_keys('TestUsername')
|
||||||
password = self.browser.find_element_by_id('id_password')
|
password = self.browser.find_element_by_id('id_password')
|
||||||
password.send_keys('correcthorsebatterystaple')
|
password.send_keys('correcthorsebatterystaple')
|
||||||
self.browser.execute_script(
|
|
||||||
"return function() {jQuery('#g-recaptcha-response').val('PASSED'); return 0}()")
|
|
||||||
password.send_keys(Keys.ENTER)
|
password.send_keys(Keys.ENTER)
|
||||||
|
|
||||||
# Check we are logged in
|
# Check we are logged in
|
||||||
|
|||||||
Reference in New Issue
Block a user