Merge branch 'master' into training

# Conflicts:
#	RIGS/templates/risk_assessment_form.html
#	templates/base.html
This commit is contained in:
2021-10-08 18:40:39 +01:00
36 changed files with 592 additions and 437 deletions

View File

@@ -49,7 +49,7 @@ class Supplier(models.Model, RevisionMixin):
ordering = ['name']
def get_absolute_url(self):
return reverse('supplier_list')
return reverse('supplier_detail', kwargs={'pk': self.pk})
def __str__(self):
return self.name
@@ -82,6 +82,9 @@ class CableType(models.Model):
else:
return "Unknown"
def get_absolute_url(self):
return reverse('cable_type_detail', kwargs={'pk': self.pk})
def get_available_asset_id(wanted_prefix=""):
sql = """

View File

@@ -2,6 +2,9 @@
{% load widget_tweaks %}
{% block content %}
<div class="row justify-content-end">
{% include 'partials/asset_buttons.html' %}
</div>
<div class="row">
<div class="col-md-6 mb-3">
{% include 'partials/asset_detail_form.html' %}

View File

@@ -34,7 +34,7 @@
})
.ajaxSelectPicker({
ajax: {
url: '{% url 'asset_search_json' %}',
url: "{% url 'asset_search_json' %}",
type: "GET",
data: function () {
let params = {

View File

@@ -11,7 +11,10 @@
<div class="btn-group">
{% button 'edit' url='asset_update' 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>
{% endif %}
{% if create or edit or duplicate %}

View File

@@ -17,11 +17,9 @@
{% else %}
<dl>
<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>
<dd>{{ object.length|default_if_none:'-' }}m</dd>
<dt>Cross Sectional Area</dt>
<dd>{{ object.csa|default_if_none:'-' }}mm²</dd>
</dl>

View File

@@ -28,13 +28,13 @@
<dt>Children</dt>
{% if object.asset_parent.all %}
<div style="max-height: 200px; overflow-y: auto; -webkit-overflow-scrolling: touch; ">
{% for child in object.asset_parent.all %}
<dd>
<a href="{% url 'asset_detail' child.asset_id %}">
{{ child.asset_id }} - {{ child.description }}
</a>
<a href="{% url 'asset_detail' child.asset_id %}">{{ child }}</a>
</dd>
{% endfor %}
</div>
{% else %}
<dd><span>-</span></dd>
{% endif %}

View File

@@ -1,4 +1,5 @@
{% load widget_tweaks %}
{% load linkornone from filters %}
<div class="card mb-2">
<div class="card-header">
Purchase Details
@@ -51,14 +52,11 @@
{% else %}
<dl>
<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>
<dd>£{{ object.purchase_price|default_if_none:'-' }}</dd>
<dt>Salvage Value</dt>
<dd>£{{ object.salvage_value|default_if_none:'-' }}</dd>
<dt>Date Acquired</dt>
<dd>{{ object.date_acquired|default_if_none:'-' }}</dd>
{% if object.date_sold %}

View File

@@ -16,6 +16,7 @@ urlpatterns = [
(views.AssetEdit.as_view()), name='asset_update'),
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.add_asset')
(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/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'),

View File

@@ -1,4 +1,5 @@
import simplejson
import random
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core import serializers
@@ -9,6 +10,11 @@ from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import generic
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, \
is_ajax, OEmbedView
@@ -338,3 +344,37 @@ class CableTypeUpdate(generic.UpdateView):
def get_success_url(self):
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