mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-03-18 18:05:57 +00:00
Compare commits
21 Commits
assets
...
asset_fixe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b3dca04a2 | ||
|
|
3731c5bba0 | ||
|
|
61a46fa1c2 | ||
|
ddc23ce4e5
|
|||
|
602ccc15ea
|
|||
|
|
b77615b9b9 | ||
| dea628e7a2 | |||
|
|
171d5d633e | ||
|
|
294c839bc3 | ||
|
|
228d72b7b2 | ||
|
|
73e8bc3326 | ||
|
|
5a081a97c4 | ||
|
|
1f0dc9f1ae | ||
|
|
8ad0bdf5f3 | ||
|
faa86dbe8d
|
|||
|
62541194ee
|
|||
|
0d8fd99d92
|
|||
|
9d51a82f31
|
|||
|
c059227d5d
|
|||
|
2c334196d5
|
|||
| 4f036af85a |
1
Procfile
1
Procfile
@@ -1 +1,2 @@
|
|||||||
|
release: python manage.py migrate
|
||||||
web: gunicorn PyRIGS.wsgi --log-file -
|
web: gunicorn PyRIGS.wsgi --log-file -
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ class AssetAdmin(admin.ModelAdmin):
|
|||||||
@admin.register(assets.Connector)
|
@admin.register(assets.Connector)
|
||||||
class ConnectorAdmin(admin.ModelAdmin):
|
class ConnectorAdmin(admin.ModelAdmin):
|
||||||
list_display = ['id', '__str__', 'current_rating', 'voltage_rating', 'num_pins']
|
list_display = ['id', '__str__', 'current_rating', 'voltage_rating', 'num_pins']
|
||||||
|
|
||||||
|
|
||||||
admin.AdminSite.site_header = 'PyAssets - TEC\'s Asset System'
|
|
||||||
admin.AdminSite.site_title = 'PyAssets Admin'
|
|
||||||
admin.AdminSite.index_title = 'System Administration'
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class AssetForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = models.Asset
|
model = models.Asset
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
exclude = ['asset_id_prefix', 'asset_id_number']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import random
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from assets import models
|
from assets import models
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class Command(BaseCommand):
|
|||||||
suppliers = models.Supplier.objects.all()
|
suppliers = models.Supplier.objects.all()
|
||||||
|
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
asset = models.Asset.objects.create(
|
asset = models.Asset(
|
||||||
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
||||||
description=random.choice(asset_description),
|
description=random.choice(asset_description),
|
||||||
category=random.choice(categories),
|
category=random.choice(categories),
|
||||||
@@ -62,11 +62,12 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
if i % 3 == 0:
|
if i % 3 == 0:
|
||||||
asset.purchased_from = random.choice(suppliers)
|
asset.purchased_from = random.choice(suppliers)
|
||||||
|
asset.clean()
|
||||||
asset.save()
|
asset.save()
|
||||||
|
|
||||||
def create_cables(self):
|
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_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]
|
csas = [0.75, 1.00, 1.25, 2.5, 4]
|
||||||
lengths = [1, 2, 5, 10, 15, 20, 25, 30, 50, 100]
|
lengths = [1, 2, 5, 10, 15, 20, 25, 30, 50, 100]
|
||||||
@@ -78,7 +79,7 @@ class Command(BaseCommand):
|
|||||||
connectors = models.Connector.objects.all()
|
connectors = models.Connector.objects.all()
|
||||||
|
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
asset = models.Asset.objects.create(
|
asset = models.Asset(
|
||||||
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
||||||
description=random.choice(asset_description),
|
description=random.choice(asset_description),
|
||||||
category=random.choice(categories),
|
category=random.choice(categories),
|
||||||
@@ -94,12 +95,17 @@ class Command(BaseCommand):
|
|||||||
cores=random.choice(circuits)
|
cores=random.choice(circuits)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if i % 5 == 0:
|
||||||
|
prefix = random.choice(asset_prefixes)
|
||||||
|
asset.asset_id = prefix + str(models.Asset.get_available_asset_id(wanted_prefix=prefix))
|
||||||
|
|
||||||
if i % 4 == 0:
|
if i % 4 == 0:
|
||||||
asset.parent = models.Asset.objects.order_by('?').first()
|
asset.parent = models.Asset.objects.order_by('?').first()
|
||||||
|
|
||||||
if i % 3 == 0:
|
if i % 3 == 0:
|
||||||
asset.purchased_from = random.choice(suppliers)
|
asset.purchased_from = random.choice(suppliers)
|
||||||
|
|
||||||
|
asset.clean()
|
||||||
asset.save()
|
asset.save()
|
||||||
|
|
||||||
def create_connectors(self):
|
def create_connectors(self):
|
||||||
|
|||||||
51
assets/migrations/0008_auto_20191206_2124.py
Normal file
51
assets/migrations/0008_auto_20191206_2124.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Generated by Django 2.0.13 on 2019-12-06 21:24
|
||||||
|
|
||||||
|
from django.db import migrations, models, transaction
|
||||||
|
import re
|
||||||
|
|
||||||
|
def forwards(apps, schema_editor):
|
||||||
|
AssetModel = apps.get_model('assets', 'Asset')
|
||||||
|
with transaction.atomic():
|
||||||
|
for row in AssetModel.objects.all():
|
||||||
|
|
||||||
|
row.asset_id = row.asset_id.upper()
|
||||||
|
asset_search = re.search("^([A-Z0-9]*?[A-Z]?)([0-9]+)$", row.asset_id)
|
||||||
|
if asset_search is None: # If the asset_id doesn't have a number at the end
|
||||||
|
row.asset_id += "1"
|
||||||
|
|
||||||
|
asset_search = re.search("^([A-Z0-9]*?[A-Z]?)([0-9]+)$", row.asset_id)
|
||||||
|
row.asset_id_prefix = asset_search.group(1)
|
||||||
|
row.asset_id_number = int(asset_search.group(2))
|
||||||
|
|
||||||
|
row.save(update_fields=['asset_id', 'asset_id_prefix', 'asset_id_number'])
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('assets', '0007_auto_20190108_0202_squashed_0014_auto_20191017_2052'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='asset',
|
||||||
|
options={'ordering': ['asset_id_prefix', 'asset_id_number'], 'permissions': (('asset_finance', 'Can see financial data for assets'), ('view_asset', 'Can view an asset'))},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='asset',
|
||||||
|
name='asset_id_number',
|
||||||
|
field=models.IntegerField(default=1),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='asset',
|
||||||
|
name='asset_id_prefix',
|
||||||
|
field=models.CharField(default='', max_length=8),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='asset',
|
||||||
|
name='asset_id',
|
||||||
|
field=models.CharField(max_length=15, unique=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
code=forwards,
|
||||||
|
reverse_code=migrations.operations.special.RunPython.noop,
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -3,6 +3,9 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db import models, connection
|
from django.db import models, connection
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from django.db.models.signals import pre_save
|
||||||
|
from django.dispatch.dispatcher import receiver
|
||||||
|
|
||||||
|
|
||||||
class AssetCategory(models.Model):
|
class AssetCategory(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -54,14 +57,14 @@ class Connector(models.Model):
|
|||||||
|
|
||||||
class Asset(models.Model):
|
class Asset(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['asset_id']
|
ordering = ['asset_id_prefix', 'asset_id_number']
|
||||||
permissions = (
|
permissions = (
|
||||||
('asset_finance', 'Can see financial data for assets'),
|
('asset_finance', 'Can see financial data for assets'),
|
||||||
('view_asset', 'Can view an asset')
|
('view_asset', 'Can view an asset')
|
||||||
)
|
)
|
||||||
|
|
||||||
parent = models.ForeignKey(to='self', related_name='asset_parent', blank=True, null=True, on_delete=models.SET_NULL)
|
parent = models.ForeignKey(to='self', related_name='asset_parent', blank=True, null=True, on_delete=models.SET_NULL)
|
||||||
asset_id = models.CharField(max_length=10, unique=True)
|
asset_id = models.CharField(max_length=15, unique=True)
|
||||||
description = models.CharField(max_length=120)
|
description = models.CharField(max_length=120)
|
||||||
category = models.ForeignKey(to=AssetCategory, on_delete=models.CASCADE)
|
category = models.ForeignKey(to=AssetCategory, on_delete=models.CASCADE)
|
||||||
status = models.ForeignKey(to=AssetStatus, on_delete=models.CASCADE)
|
status = models.ForeignKey(to=AssetStatus, on_delete=models.CASCADE)
|
||||||
@@ -83,18 +86,24 @@ class Asset(models.Model):
|
|||||||
circuits = models.IntegerField(blank=True, null=True)
|
circuits = models.IntegerField(blank=True, null=True)
|
||||||
cores = models.IntegerField(blank=True, null=True)
|
cores = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
def get_available_asset_id():
|
# Hidden asset_id components
|
||||||
|
# For example, if asset_id was "C1001" then asset_id_prefix would be "C" and number "1001"
|
||||||
|
asset_id_prefix = models.CharField(max_length=8, default="")
|
||||||
|
asset_id_number = models.IntegerField(default=1)
|
||||||
|
|
||||||
|
def get_available_asset_id(wanted_prefix=""):
|
||||||
sql = """
|
sql = """
|
||||||
SELECT MIN(CAST(a.asset_id AS int))+1
|
SELECT a.asset_id_number+1
|
||||||
FROM assets_asset a
|
FROM assets_asset a
|
||||||
LEFT OUTER JOIN assets_asset b ON
|
LEFT OUTER JOIN assets_asset b ON
|
||||||
(CAST(a.asset_id AS int) + 1 = CAST(b.asset_id AS int))
|
(a.asset_id_number + 1 = b.asset_id_number AND
|
||||||
WHERE b.asset_id IS NULL AND CAST(a.asset_id AS int) >= %s;
|
a.asset_id_prefix = b.asset_id_prefix)
|
||||||
|
WHERE b.asset_id IS NULL AND a.asset_id_number >= %s AND a.asset_id_prefix = %s;
|
||||||
"""
|
"""
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
cursor.execute(sql, [9000])
|
cursor.execute(sql, [9000, wanted_prefix])
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row[0] is None:
|
if row is None or row[0] is None:
|
||||||
return 9000
|
return 9000
|
||||||
else:
|
else:
|
||||||
return row[0]
|
return row[0]
|
||||||
@@ -114,8 +123,9 @@ class Asset(models.Model):
|
|||||||
errdict["date_sold"] = ["Cannot sell an item before it is acquired"]
|
errdict["date_sold"] = ["Cannot sell an item before it is acquired"]
|
||||||
|
|
||||||
self.asset_id = self.asset_id.upper()
|
self.asset_id = self.asset_id.upper()
|
||||||
if re.search("^[a-zA-Z0-9]+$", self.asset_id) is None:
|
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", self.asset_id)
|
||||||
errdict["asset_id"] = ["An Asset ID can only consist of letters and numbers"]
|
if asset_search is None:
|
||||||
|
errdict["asset_id"] = ["An Asset ID can only consist of letters and numbers, with a final number"]
|
||||||
|
|
||||||
if self.purchase_price and self.purchase_price < 0:
|
if self.purchase_price and self.purchase_price < 0:
|
||||||
errdict["purchase_price"] = ["A price cannot be negative"]
|
errdict["purchase_price"] = ["A price cannot be negative"]
|
||||||
@@ -139,3 +149,14 @@ class Asset(models.Model):
|
|||||||
|
|
||||||
if errdict != {}: # If there was an error when validation
|
if errdict != {}: # If there was an error when validation
|
||||||
raise ValidationError(errdict)
|
raise ValidationError(errdict)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(pre_save, sender=Asset)
|
||||||
|
def pre_save_asset(sender, instance, **kwargs):
|
||||||
|
"""Automatically fills in hidden members on database access"""
|
||||||
|
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", instance.asset_id)
|
||||||
|
if asset_search is None:
|
||||||
|
instance.asset_id += "1"
|
||||||
|
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", instance.asset_id)
|
||||||
|
instance.asset_id_prefix = asset_search.group(1)
|
||||||
|
instance.asset_id_number = int(asset_search.group(2))
|
||||||
|
|||||||
@@ -25,12 +25,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if perms.asset.asset_financial %}
|
{% if perms.assets.asset_finance %}
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{% include 'partials/purchasedetails_form.html' %}
|
{% include 'partials/purchasedetails_form.html' %}
|
||||||
</div>
|
</div>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
<div class="col-md-6"
|
<div class="col-md-6"
|
||||||
{% if not object.is_cable %} hidden="true" {% endif %} id="cable-table">
|
{% if not object.is_cable %} hidden="true" {% endif %} id="cable-table">
|
||||||
{% include 'partials/cable_form.html' %}
|
{% include 'partials/cable_form.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
<td style="vertical-align: middle;">{{ item.category }}</td>
|
<td style="vertical-align: middle;">{{ item.category }}</td>
|
||||||
<td style="vertical-align: middle;">{{ item.status }}</td>
|
<td style="vertical-align: middle;">{{ item.status }}</td>
|
||||||
<td class="hidden-xs">
|
<td class="hidden-xs">
|
||||||
|
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<a type="button" class="btn btn-default btn-sm" href="{% url 'asset_detail' item.asset_id %}"><i class="glyphicon glyphicon-eye-open"></i> View</a>
|
<a type="button" class="btn btn-default btn-sm" href="{% url 'asset_detail' item.asset_id %}"><i class="glyphicon glyphicon-eye-open"></i> View</a>
|
||||||
{% if perms.assets.change_asset %}
|
{% if perms.assets.change_asset %}
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ urlpatterns = [
|
|||||||
path('', views.AssetList.as_view(), name='asset_index'),
|
path('', views.AssetList.as_view(), name='asset_index'),
|
||||||
path('asset/list/', views.AssetList.as_view(), name='asset_list'),
|
path('asset/list/', views.AssetList.as_view(), name='asset_list'),
|
||||||
path('asset/id/<str:pk>/', views.AssetDetail.as_view(), name='asset_detail'),
|
path('asset/id/<str:pk>/', views.AssetDetail.as_view(), name='asset_detail'),
|
||||||
path('asset/create/', permission_required_with_403('assets.create_asset')(views.AssetCreate.as_view()), name='asset_create'),
|
path('asset/create/', permission_required_with_403('assets.add_asset')(views.AssetCreate.as_view()), name='asset_create'),
|
||||||
path('asset/id/<str:pk>/edit/', permission_required_with_403('assets.change_asset')(views.AssetEdit.as_view()), name='asset_update'),
|
path('asset/id/<str:pk>/edit/', permission_required_with_403('assets.change_asset')(views.AssetEdit.as_view()), name='asset_update'),
|
||||||
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.create_asset')(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.add_asset')(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
||||||
|
|
||||||
path('asset/search/', views.AssetSearch.as_view(), name='asset_search_json'),
|
path('asset/search/', views.AssetSearch.as_view(), name='asset_search_json'),
|
||||||
|
|
||||||
path('supplier/list', views.SupplierList.as_view(), name='supplier_list'),
|
path('supplier/list', views.SupplierList.as_view(), name='supplier_list'),
|
||||||
path('supplier/<int:pk>', views.SupplierDetail.as_view(), name='supplier_detail'),
|
path('supplier/<int:pk>', views.SupplierDetail.as_view(), name='supplier_detail'),
|
||||||
path('supplier/create', permission_required_with_403('assets.create_supplier')(views.SupplierCreate.as_view()), name='supplier_create'),
|
path('supplier/create', permission_required_with_403('assets.add_supplier')(views.SupplierCreate.as_view()), name='supplier_create'),
|
||||||
path('supplier/<int:pk>/edit', permission_required_with_403('assets.edit_supplier')(views.SupplierUpdate.as_view()), name='supplier_update'),
|
path('supplier/<int:pk>/edit', permission_required_with_403('assets.change_supplier')(views.SupplierUpdate.as_view()), name='supplier_update'),
|
||||||
|
|
||||||
path('supplier/search/', views.SupplierSearch.as_view(), name='supplier_search_json'),
|
path('supplier/search/', views.SupplierSearch.as_view(), name='supplier_search_json'),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user