WIP: Basic work on audit

This commit is contained in:
2020-02-09 00:04:54 +00:00
parent ae151ed45e
commit e9a9250027
12 changed files with 192 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
<div class="modal fade" id="itemModal" role="dialog" aria-labelledby="itemModal" aria-hidded="true"> <div class="modal fade" id="itemModal" role="dialog" aria-labelledby="itemModal" aria-hidden="true">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@@ -71,4 +71,4 @@
</form> </form>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -12,7 +12,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'] exclude = ['asset_id_prefix', 'asset_id_number', 'last_audited_at', 'last_audited_by']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View File

@@ -0,0 +1,26 @@
# Generated by Django 2.0.13 on 2020-02-08 23:04
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0010_auto_20200207_1737'),
]
operations = [
migrations.AddField(
model_name='asset',
name='last_audited_at',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='asset',
name='last_audited_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='audited_by', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -9,7 +9,7 @@ from django.dispatch.dispatcher import receiver
from reversion import revisions as reversion from reversion import revisions as reversion
from reversion.models import Version from reversion.models import Version
from RIGS.models import RevisionMixin from RIGS.models import RevisionMixin, Profile
class AssetCategory(models.Model): class AssetCategory(models.Model):
@@ -88,8 +88,13 @@ class Asset(models.Model, RevisionMixin):
purchase_price = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10) purchase_price = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10)
salvage_value = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10) salvage_value = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10)
comments = models.TextField(blank=True) comments = models.TextField(blank=True)
# TODO Remove
next_sched_maint = models.DateField(blank=True, null=True) next_sched_maint = models.DateField(blank=True, null=True)
# Audit
last_audited_at = models.DateTimeField(blank=True, null=True)
last_audited_by = models.ForeignKey(Profile, on_delete=models.SET_NULL, related_name='audited_by', blank=True, null=True)
# Cable assets # Cable assets
is_cable = models.BooleanField(default=False) is_cable = models.BooleanField(default=False)
plug = models.ForeignKey(Connector, on_delete=models.SET_NULL, plug = models.ForeignKey(Connector, on_delete=models.SET_NULL,

View File

@@ -0,0 +1,82 @@
{% extends 'base_assets.html' %}
{% load widget_tweaks %}
{% block title %}Audit Asset {{ object.asset_id }}{% endblock %}
{% block content %}
<div class="page-header">
<h1>
Audit Asset: {{ object.asset_id }}
</h1>
</div>
<form class="form-horizontal" method="post" id="asset_update_form" action="{% url 'asset_audit' pk=object.asset_id%}">
{% include 'form_errors.html' %}
{% csrf_token %}
<input type="hidden" name="id" value="{{ object.id|default:0 }}" hidden=true>
<div class="col-sm-12">
<div class="form-group">
<label for="{{ form.asset_id.id_for_label }}" class="col-sm-2 control-label">Asset ID</label>
<div class="col-sm-10">
{% render_field form.asset_id|add_class:'form-control' value=object.asset_id %}
</div>
</div>
<div class="form-group">
<label for="{{ form.description.id_for_label }}" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
{% render_field form.description|add_class:'form-control' value=object.description %}
</div>
</div>
<div class="form-group">
<label for="{{ form.category.id_for_label }}" class="col-sm-2 control-label">Category</label>
<div class="col-sm-10">
{% render_field form.category|add_class:'form-control'%}
</div>
</div>
<div class="form-group">
<label for="{{ form.status.id_for_label }}" class="col-sm-2 control-label">Status</label>
<div class="col-sm-10">
{% render_field form.status|add_class:'form-control'%}
</div>
</div>
<div class="form-group">
<label for="{{ form.serial_number.id_for_label }}" class="col-sm-2 control-label">Serial Number</label>
<div class="col-sm-10">
{% render_field form.serial_number|add_class:'form-control' value=object.serial_number %}
</div>
</div>
<div class="form-group">
<label for="{{ form.date_acquired.id_for_label }}" class="col-sm-2 control-label">Date Acquired</label>
<div class="col-sm-10">
{% render_field form.date_acquired|add_class:'form-control' value=object.date_acquired %}
</div>
<!--- TODO Add buttons for 'today' and 'unknown' (sets to beginning of time)--->
</div>
<div class="form-group">
<label for="{{ form.is_cable.id_for_label }}" class="col-sm-2 control-label">Cable?</label>
<div class="col-sm-10">
{% render_field form.is_cable|attr:'onchange=checkIfCableHidden()' %}
</div>
</div>
<div class="row">
<div class="col-md-10 pull-right">
<button type="submit" class="btn btn-success"><i class="glyphicon glyphicon-floppy-disk"></i> Audit</button>
<br>
<button type="reset" class="btn btn-link" onclick="history.back()">Cancel</button>
</div>
</div>
</form>
{% endblock %}
{% block js%}
{% if edit %}
<script>
function checkIfCableHidden() {
if (document.getElementById("id_is_cable").checked) {
document.getElementById("cable-table").hidden = false;
} else {
document.getElementById("cable-table").hidden = true;
}
}
checkIfCableHidden();
</script>
{% endif %}
{% endblock %}

View File

@@ -9,26 +9,7 @@
<h1 class="text-center">Asset List</h1> <h1 class="text-center">Asset List</h1>
</div> </div>
<form id="asset-search-form" method="get" class="form-inline pull-right"> {% include 'partials/asset_search.html' %}
<div class="input-group pull-right" style="width: auto;">
{% 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>
<div style="margin-top: 1em;" class="pull-right">
<div id="category-group" class="form-group">
<label for="category" class="sr-only">Category</label>
{% render_field form.category|attr:'multiple'|add_class:'form-control selectpicker' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %}
</div>
<div id="status-group" class="form-group">
<label for="status" class="sr-only">Status</label>
{% render_field form.status|attr:'multiple'|add_class:'form-control selectpicker' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
</div>
<!---TODO: Auto filter whenever an option is selected, instead of using a button -->
<button id="filter-submit" type="submit" class="btn btn-default">Filter</button>
</div>
</form>
<table class="table"> <table class="table">
<thead> <thead>

View File

@@ -35,6 +35,11 @@
<div class="col-md-4"> <div class="col-md-4">
{% include 'partials/parent_form.html' %} {% include 'partials/parent_form.html' %}
</div> </div>
{% if not edit %}
<div class="col-md-4">
{% include 'partials/audit_details.html' %}
</div>
{% endif %}
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">

View File

@@ -0,0 +1,28 @@
{% extends request.is_ajax|yesno:'base_ajax.html,base_assets.html' %}
{% load widget_tweaks %}
{% block title %}Asset Search{% endblock %}
{% block content %}
<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/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>
<div style="margin-top: 1em;" class="pull-right">
<div id="category-group" class="form-group">
<label for="category" class="sr-only">Category</label>
{% render_field form.category|attr:'multiple'|add_class:'form-control selectpicker' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %}
</div>
<div id="status-group" class="form-group">
<label for="status" class="sr-only">Status</label>
{% render_field form.status|attr:'multiple'|add_class:'form-control selectpicker' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %}
</div>
<!---TODO: Auto filter whenever an option is selected, instead of using a button -->
<button id="filter-submit" type="submit" class="btn btn-default">Filter</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,8 @@
<div class="panel {% if object.last_audited_at is not None %} panel-success {% else %} panel-default {% endif %}">
<div class="panel-heading">
Audit Details
</div>
<div class="panel-body">
<p>Audited at <span class="label label-default">{{ object.last_audited_at|default_if_none:'-' }}</span> by <span class="label label-info">{{ object.last_audited_by|default_if_none:'-' }}</span></p>
</div>
</div>

View File

@@ -31,6 +31,9 @@ urlpatterns = [
views.AssetOembed.as_view(), views.AssetOembed.as_view(),
name='asset_oembed'), name='asset_oembed'),
path('asset/audit/', permission_required_with_403('assets.view_asset')(views.AssetAuditList.as_view()), name='asset_audit_list'),
path('asset/id/<str:pk>/audit/', permission_required_with_403('assets.view_asset')(views.AssetAudit.as_view()), name='asset_audit'),
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.add_supplier') path('supplier/create', permission_required_with_403('assets.add_supplier')

View File

@@ -11,6 +11,7 @@ from assets import models, forms
from RIGS import versioning from RIGS import versioning
import simplejson import simplejson
import datetime
@method_decorator(csrf_exempt, name='dispatch') @method_decorator(csrf_exempt, name='dispatch')
@@ -173,6 +174,34 @@ class AssetEmbed(AssetDetail):
template_name = 'asset_embed.html' template_name = 'asset_embed.html'
class AssetAuditList(LoginRequiredMixin, generic.ListView):
model = models.Asset
template_name = 'asset_list.html'
paginate_by = 40
ordering = ['-pk']
class AssetAudit(LoginRequiredMixin, AssetIDUrlMixin, generic.UpdateView):
template_name = 'asset_audit.html'
model = models.Asset
form_class = forms.AssetForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['edit'] = True
context['connectors'] = models.Connector.objects.all()
return context
def get_success_url(self):
# TODO For some reason this doesn't stick when done in form_valid??
asset = self.get_object()
asset.last_audited_by = self.request.user
asset.last_audited_at = datetime.datetime.now()
asset.save()
return reverse("asset_audit_list")
class SupplierList(generic.ListView): class SupplierList(generic.ListView):
model = models.Supplier model = models.Supplier
template_name = 'supplier_list.html' template_name = 'supplier_list.html'

View File

@@ -35,5 +35,6 @@
{# % endif % #} {# % endif % #}
{% if perms.assets.view_asset %} {% if perms.assets.view_asset %}
<li><a href="{% url 'asset_activity_table' %}">Recent Changes</a></li> <li><a href="{% url 'asset_activity_table' %}">Recent Changes</a></li>
<li><a href="{% url 'asset_audit_list' %}">Audit</a></li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}