mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-17 13:32:15 +00:00
Compare commits
10 Commits
combine-pr
...
assets_mis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5696cf73ce | ||
|
|
096ca24336 | ||
| c779c24d63 | |||
| dad9797f74 | |||
| 69facd5dc6 | |||
| 406a9dad36 | |||
| 81c32baa8e | |||
| eef0682e4f | |||
| 2465390889 | |||
| fc9ce9f01c |
@@ -17,6 +17,7 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
|
||||
from RIGS import models, forms
|
||||
from assets import models as asset_models
|
||||
from functools import reduce
|
||||
|
||||
"""
|
||||
@@ -248,6 +249,7 @@ class SecureAPIRequest(generic.View):
|
||||
'organisation': models.Organisation,
|
||||
'profile': models.Profile,
|
||||
'event': models.Event,
|
||||
'supplier': asset_models.Supplier
|
||||
}
|
||||
|
||||
perms = {
|
||||
@@ -256,6 +258,7 @@ class SecureAPIRequest(generic.View):
|
||||
'organisation': 'RIGS.view_organisation',
|
||||
'profile': 'RIGS.view_profile',
|
||||
'event': None,
|
||||
'supplier': None
|
||||
}
|
||||
|
||||
'''
|
||||
|
||||
@@ -6,4 +6,4 @@ from assets import models
|
||||
class AssetFilter(django_filters.FilterSet):
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = ['asset_id', 'description', 'category', 'status']
|
||||
fields = ['asset_id', 'description', 'serial_number', 'category', 'status']
|
||||
|
||||
@@ -4,6 +4,11 @@ from assets import models
|
||||
|
||||
|
||||
class AssetForm(forms.ModelForm):
|
||||
related_models = {
|
||||
'asset': models.Asset,
|
||||
'supplier': models.Supplier
|
||||
}
|
||||
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = '__all__'
|
||||
|
||||
21
assets/migrations/0009_auto_20200102_1933.py
Normal file
21
assets/migrations/0009_auto_20200102_1933.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 2.0.13 on 2020-01-02 19:33
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0008_auto_20191206_2124'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='assetcategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Asset Category', 'verbose_name_plural': 'Asset Categories'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='assetstatus',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Asset Status', 'verbose_name_plural': 'Asset Statuses'},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 2.0.13 on 2020-01-02 20:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
replaces = [('assets', '0009_auto_20200102_1933'), ('assets', '0010_assetstatus_display_class'), ('assets', '0011_auto_20200102_2040')]
|
||||
|
||||
dependencies = [
|
||||
('assets', '0008_auto_20191206_2124'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='assetcategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Asset Category', 'verbose_name_plural': 'Asset Categories'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='assetstatus',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Asset Status', 'verbose_name_plural': 'Asset Statuses'},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='assetstatus',
|
||||
name='display_class',
|
||||
field=models.CharField(help_text='HTML class to be appended to alter display of assets with this status, such as in the list.', max_length=80),
|
||||
),
|
||||
]
|
||||
18
assets/migrations/0010_assetstatus_display_class.py
Normal file
18
assets/migrations/0010_assetstatus_display_class.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.13 on 2020-01-02 19:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0009_auto_20200102_1933'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='assetstatus',
|
||||
name='display_class',
|
||||
field=models.TextField(default='', help_text='HTML class to be appended to alter display of assets with this status, such as in the list.'),
|
||||
),
|
||||
]
|
||||
19
assets/migrations/0010_auto_20200103_2134.py
Normal file
19
assets/migrations/0010_auto_20200103_2134.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.0.13 on 2020-01-03 21:34
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0009_auto_20200102_1933_squashed_0011_auto_20200102_2040'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='purchased_from',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assets', to='assets.Supplier'),
|
||||
),
|
||||
]
|
||||
18
assets/migrations/0011_auto_20200102_2040.py
Normal file
18
assets/migrations/0011_auto_20200102_2040.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.13 on 2020-01-02 20:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0010_assetstatus_display_class'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='assetstatus',
|
||||
name='display_class',
|
||||
field=models.CharField(help_text='HTML class to be appended to alter display of assets with this status, such as in the list.', max_length=80),
|
||||
),
|
||||
]
|
||||
@@ -16,6 +16,7 @@ class AssetCategory(models.Model):
|
||||
class Meta:
|
||||
verbose_name = 'Asset Category'
|
||||
verbose_name_plural = 'Asset Categories'
|
||||
ordering = ['name']
|
||||
|
||||
name = models.CharField(max_length=80)
|
||||
|
||||
@@ -27,10 +28,12 @@ class AssetStatus(models.Model):
|
||||
class Meta:
|
||||
verbose_name = 'Asset Status'
|
||||
verbose_name_plural = 'Asset Statuses'
|
||||
ordering = ['name']
|
||||
|
||||
name = models.CharField(max_length=80)
|
||||
should_show = models.BooleanField(
|
||||
default=True, help_text="Should this be shown by default in the asset list.")
|
||||
display_class = models.CharField(max_length=80, help_text="HTML class to be appended to alter display of assets with this status, such as in the list.")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -78,7 +81,7 @@ class Asset(models.Model, RevisionMixin):
|
||||
category = models.ForeignKey(to=AssetCategory, on_delete=models.CASCADE)
|
||||
status = models.ForeignKey(to=AssetStatus, on_delete=models.CASCADE)
|
||||
serial_number = models.CharField(max_length=150, blank=True)
|
||||
purchased_from = models.ForeignKey(to=Supplier, on_delete=models.CASCADE, blank=True, null=True)
|
||||
purchased_from = models.ForeignKey(to=Supplier, on_delete=models.CASCADE, blank=True, null=True, related_name="assets")
|
||||
date_acquired = models.DateField()
|
||||
date_sold = models.DateField(blank=True, null=True)
|
||||
purchase_price = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
{% load asset_templatetags %}
|
||||
{% block title %}Asset {{ object.asset_id }}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="page-header">
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
<form id="asset-search-form" method="get" class="form-inline pull-right">
|
||||
<div class="input-group pull-right" style="width: auto;">
|
||||
{% render_field form.query|add_class:'form-control' placeholder='Search by Asset ID/Description' style="width: 250px"%}
|
||||
<label for="query" class="sr-only">Asset ID/Description:</label>
|
||||
{% render_field form.query|add_class:'form-control' placeholder='Search by Asset ID/Desc/Serial' style="width: 250px"%}
|
||||
<label for="query" class="sr-only">Asset ID/Description/Serial Number:</label>
|
||||
<span class="input-group-btn"><button type="submit" class="btn btn-default">Search</button></span>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
{% load asset_templatetags %}
|
||||
{% block title %}Asset {{ object.asset_id }}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="page-header">
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
{% for item in object_list %}
|
||||
{# <li><a href="{% url 'asset_detail' item.pk %}">{{ item.asset_id }} - {{ item.description }}</a></li>#}
|
||||
<!---TODO: When the ability to filter the list is added, remove the colours from the filter - specifically, stop greying out sold/binned stuff if it is being searched for--> <tr class="
|
||||
{% if item.status.name == 'Broken' %}
|
||||
danger
|
||||
{% elif item.status.name == 'Scrapped'%}
|
||||
warning
|
||||
{% elif item.status.name == 'Sold'%}
|
||||
warning
|
||||
{% elif item.status.name == 'Lost'%}
|
||||
danger
|
||||
{% elif item.status.name == 'Not Built Yet'%}
|
||||
info
|
||||
{% elif item.status.name == 'Active'%}
|
||||
success
|
||||
{% endif %}
|
||||
">
|
||||
<!---TODO: When the ability to filter the list is added, remove the colours from the filter - specifically, stop greying out sold/binned stuff if it is being searched for--> <tr class={{ item.status.display_class|default:"" }}>
|
||||
<td style="vertical-align: middle;"><a href="{% url 'asset_detail' item.asset_id %}">{{ item.asset_id }}</a></td>
|
||||
<td style="vertical-align: middle; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; max-width: 25vw">{{ item.description }}</td>
|
||||
<td style="vertical-align: middle;">{{ item.category }}</td>
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
{% load widget_tweaks %}
|
||||
{% load asset_templatetags %}
|
||||
{% load static %}
|
||||
|
||||
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="{% static "css/bootstrap-select.min.css" %}"/>
|
||||
<link rel="stylesheet" href="{% static "css/ajax-bootstrap-select.css" %}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block preload_js %}
|
||||
<script src="{% static "js/bootstrap-select.js" %}"></script>
|
||||
<script src="{% static "js/ajax-bootstrap-select.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "js/autocompleter.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Purchase Details
|
||||
@@ -7,8 +24,12 @@
|
||||
<div class="panel-body">
|
||||
{% if create or edit or duplicate %}
|
||||
<div class="form-group">
|
||||
<label for="{{ form.purchased_from.id_for_label }}">Purchased From</label>
|
||||
{% include 'partials/supplier_picker.html' %}
|
||||
<label for="{{ form.purchased_from.id_for_label }}">Supplier</label>
|
||||
<select id="{{ form.purchased_from.id_for_label }}" name="{{ form.purchased_from.name }}" class="form-control selectpicker" data-live-search="true" data-sourceurl="{% url 'api_secure' model='supplier' %}">
|
||||
{% if object.purchased_from %}
|
||||
<option value="{{form.purchased_from.value}}" selected="selected" data-update_url="{% url 'supplier_update' form.purchased_from.value %}">{{ object.purchased_from }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<select name="purchased_from" id="supplier_id" class="selectpicker">
|
||||
{% if object.parent%}
|
||||
<option value="{{object.parent.pk}}" selected>{{object.parent.name}}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
|
||||
{% load static %}
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="{% static "css/bootstrap-select.min.css" %}"/>
|
||||
<link rel="stylesheet" href="{% static "css/ajax-bootstrap-select.css" %}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block preload_js %}
|
||||
<script src="{% static "js/bootstrap-select.js" %}"></script>
|
||||
<script src="{% static "js/ajax-bootstrap-select.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ js.super }}
|
||||
<script>
|
||||
$('#supplier_id')
|
||||
.selectpicker({
|
||||
liveSearch: true
|
||||
})
|
||||
.ajaxSelectPicker({
|
||||
ajax: {
|
||||
url: '{% url 'supplier_search_json'%}',
|
||||
type: "get",
|
||||
data: function () {
|
||||
var params = {
|
||||
{% verbatim %}query: '{{{q}}}'{% endverbatim %}
|
||||
};
|
||||
return params;
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
emptyTitle: 'Search for supplier...'
|
||||
},
|
||||
preprocessData: function(data){
|
||||
var suppliers = [];
|
||||
if(data.length){
|
||||
var len = data.length;
|
||||
for(var i = 0; i < len; i++){
|
||||
var curr = data[i];
|
||||
suppliers.push(
|
||||
{
|
||||
'value': curr.id,
|
||||
'text': curr.name,
|
||||
'disabled': false
|
||||
}
|
||||
);
|
||||
}
|
||||
suppliers.push(
|
||||
{
|
||||
'value': null,
|
||||
'text': "(no selection)"
|
||||
});
|
||||
}
|
||||
return suppliers;
|
||||
},
|
||||
preserveSelected: false
|
||||
});
|
||||
</script>
|
||||
{% endblock js %}
|
||||
@@ -1,6 +1,73 @@
|
||||
{% extends 'base_assets.html' %}
|
||||
{% block title %}Detail{% endblock %}
|
||||
{% block title %}Supplier | {{ object.name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ object }}
|
||||
{% endblock %}
|
||||
<div class="row">
|
||||
{% if not request.is_ajax %}
|
||||
<div class="col-sm-12">
|
||||
<h1>Supplier | {{ object.name }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 text-right">
|
||||
<div class="btn-group btn-page">
|
||||
<a href="{% url 'supplier_update' object.pk %}" class="btn btn-default"><span
|
||||
class="glyphicon glyphicon-pencil"></span> Edit</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">Supplier Details</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Name</dt>
|
||||
<dd>{{ object.name }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Associated Assets</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Asset ID</th>
|
||||
<th>Description</th>
|
||||
<th>Category</th>
|
||||
<th>Status</th>
|
||||
<th class="hidden-xs">Quick Links</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="asset_table_body">
|
||||
{% with object.assets.all as object_list %}
|
||||
{% include 'partials/asset_list_table_body.html' %}
|
||||
{% endwith %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if not request.is_ajax %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-right">
|
||||
<div class="btn-group btn-page">
|
||||
<a href="{% url 'supplier_update' object.pk %}" class="btn btn-default"><span
|
||||
class="glyphicon glyphicon-pencil"></span> Edit</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="{% url 'supplier_update' object.pk %}" title="View Revision History">
|
||||
Last edited {{ object.last_edited_at }} by {{ object.last_edited_by.name }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<tr>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>
|
||||
<a href="{% url 'supplier_detail' item.pk %}" class="btn btn-default"><i class="glyphicon glyphicon-eye-open"></i> View</a>
|
||||
<a href="{% url 'supplier_update' item.pk %}" class="btn btn-default"><i class="glyphicon glyphicon-edit"></i> Edit</a>
|
||||
<a href="{% url 'supplier_history' item.pk %}" class="btn btn-default"><i class="glyphicon glyphicon-time"></i> History</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -39,7 +39,7 @@ class AssetList(LoginRequiredMixin, generic.ListView):
|
||||
queryset = self.model.objects.all()
|
||||
elif len(query_string) >= 3:
|
||||
queryset = self.model.objects.filter(
|
||||
Q(asset_id__exact=query_string) | Q(description__icontains=query_string))
|
||||
Q(asset_id__exact=query_string) | Q(description__icontains=query_string) | Q(serial_number__exact=query_string))
|
||||
else:
|
||||
queryset = self.model.objects.filter(Q(asset_id__exact=query_string))
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block extrahead %}
|
||||
<meta name="google" content="notranslate">
|
||||
{% endblock %}
|
||||
|
||||
{% block titleheader %}
|
||||
<a class="nav navbar-brand navbar-left" href="/"><i class="glyphicon glyphicon-circle-arrow-left" style="vertical-align: middle !important;"></i> RIGS</a>
|
||||
<a class="nav navbar-brand" href="{% url 'asset_index' %}">Assets</a>
|
||||
|
||||
Reference in New Issue
Block a user