From 642cee2ea3081f05fceb1c722845e6b9ad252211 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Thu, 18 Jan 2018 21:29:52 +0100
Subject: [PATCH] Add quantity field to item table

Allow to keep track of batches of small parts.
---
 app/inventory/forms.py                   | 4 +++-
 app/inventory/views.py                   | 4 ++++
 app/models.py                            | 2 ++
 app/static/js/items.js                   | 4 ++--
 app/templates/inventory/create_item.html | 1 +
 app/templates/inventory/edit_item.html   | 1 +
 app/templates/inventory/items.html       | 1 +
 app/templates/inventory/view_item.html   | 4 ++++
 tests/functional/test_web.py             | 2 +-
 9 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/app/inventory/forms.py b/app/inventory/forms.py
index 530b151..1f40e0d 100644
--- a/app/inventory/forms.py
+++ b/app/inventory/forms.py
@@ -9,7 +9,7 @@ This module defines the inventory blueprint forms.
 :license: BSD 2-Clause, see LICENSE for more details.
 
 """
-from wtforms import SelectField, StringField, TextAreaField, validators
+from wtforms import SelectField, StringField, IntegerField, TextAreaField, validators
 from ..helpers import CSEntryForm
 from ..validators import Unique, RegexpList, ICS_ID_RE, MAC_ADDRESS_RE
 from .. import utils, models
@@ -27,6 +27,8 @@ class ItemForm(CSEntryForm):
                                      Unique(models.Item, 'ics_id')])
     serial_number = StringField('Serial number',
                                 validators=[validators.InputRequired()])
+    quantity = IntegerField('Quantity', default=1,
+                            validators=[validators.NumberRange(min=1)])
     manufacturer_id = SelectField('Manufacturer', coerce=utils.coerce_to_str_or_none)
     model_id = SelectField('Model', coerce=utils.coerce_to_str_or_none)
     location_id = SelectField('Location', coerce=utils.coerce_to_str_or_none)
diff --git a/app/inventory/views.py b/app/inventory/views.py
index 93327a2..5c84360 100644
--- a/app/inventory/views.py
+++ b/app/inventory/views.py
@@ -67,6 +67,7 @@ def retrieve_items():
                'created_at',
                'updated_at',
                'serial_number',
+               'quantity',
                'manufacturer',
                'model',
                'location',
@@ -84,6 +85,7 @@ def retrieve_items():
          utils.format_field(item.created_at),
          utils.format_field(item.updated_at),
          item.serial_number,
+         item.quantity,
          utils.format_field(item.manufacturer),
          utils.format_field(item.model),
          utils.format_field(item.location),
@@ -119,6 +121,7 @@ def create_item():
             session[key] = getattr(form, key).data
         item = models.Item(ics_id=form.ics_id.data,
                            serial_number=form.serial_number.data,
+                           quantity=form.quantity.data,
                            manufacturer_id=form.manufacturer_id.data,
                            model_id=form.model_id.data,
                            location_id=form.location_id.data,
@@ -171,6 +174,7 @@ def edit_item(ics_id):
         if item.ics_id.startswith(current_app.config['TEMPORARY_ICS_ID']):
             item.ics_id = form.ics_id.data
         item.serial_number = form.serial_number.data
+        item.quantity = form.quantity.data
         for key in ('manufacturer_id', 'model_id', 'location_id', 'status_id', 'parent_id'):
             setattr(item, key, getattr(form, key).data)
         new_addresses = form.mac_addresses.data.split()
diff --git a/app/models.py b/app/models.py
index ed58eed..f2b2f73 100644
--- a/app/models.py
+++ b/app/models.py
@@ -273,6 +273,7 @@ class Item(CreatedMixin, db.Model):
     ics_id = db.Column(db.Text, unique=True, nullable=False,
                        index=True, default=get_temporary_ics_id)
     serial_number = db.Column(db.Text, nullable=False)
+    quantity = db.Column(db.Integer, nullable=False, default=1)
     manufacturer_id = db.Column(db.Integer, db.ForeignKey('manufacturer.id'))
     model_id = db.Column(db.Integer, db.ForeignKey('model.id'))
     location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
@@ -340,6 +341,7 @@ class Item(CreatedMixin, db.Model):
                 parent = Item.query.get(version.parent_id)
             versions.append({
                 'updated_at': utils.format_field(version.updated_at),
+                'quantity': version.quantity,
                 'location': utils.format_field(version.location),
                 'status': utils.format_field(version.status),
                 'parent': utils.format_field(parent),
diff --git a/app/static/js/items.js b/app/static/js/items.js
index 364a509..017947a 100644
--- a/app/static/js/items.js
+++ b/app/static/js/items.js
@@ -65,11 +65,11 @@ $(document).ready(function() {
         "searchable": false
       },
       {
-        "targets": [5, 6, 7, 8],
+        "targets": [6, 7, 8, 9],
         "orderable": false
       },
       {
-        "targets": [1, 9],
+        "targets": [1, 10],
         "render": function(data, type, row) {
           // render funtion to create link to Item view page
           if ( data === null ) {
diff --git a/app/templates/inventory/create_item.html b/app/templates/inventory/create_item.html
index faf013f..5cc2e4e 100644
--- a/app/templates/inventory/create_item.html
+++ b/app/templates/inventory/create_item.html
@@ -8,6 +8,7 @@
     {{ form.hidden_tag() }}
     {{ render_field(form.ics_id) }}
     {{ render_field(form.serial_number) }}
+    {{ render_field(form.quantity) }}
     {{ render_field(form.manufacturer_id) }}
     {{ render_field(form.model_id) }}
     {{ render_field(form.location_id) }}
diff --git a/app/templates/inventory/edit_item.html b/app/templates/inventory/edit_item.html
index 1070849..9a2b187 100644
--- a/app/templates/inventory/edit_item.html
+++ b/app/templates/inventory/edit_item.html
@@ -22,6 +22,7 @@
       {{ render_field(form.ics_id, readonly=True) }}
     {% endif %}
     {{ render_field(form.serial_number) }}
+    {{ render_field(form.quantity) }}
     {{ render_field(form.manufacturer_id) }}
     {{ render_field(form.model_id) }}
     {{ render_field(form.location_id) }}
diff --git a/app/templates/inventory/items.html b/app/templates/inventory/items.html
index 9e4edba..0940e55 100644
--- a/app/templates/inventory/items.html
+++ b/app/templates/inventory/items.html
@@ -26,6 +26,7 @@
         <th>Created</th>
         <th>Updated</th>
         <th>Serial number</th>
+        <th>Quantity</th>
         <th>Manufacturer</th>
         <th>Model</th>
         <th>Location</th>
diff --git a/app/templates/inventory/view_item.html b/app/templates/inventory/view_item.html
index c695846..8def1b3 100644
--- a/app/templates/inventory/view_item.html
+++ b/app/templates/inventory/view_item.html
@@ -24,6 +24,8 @@
     <dd class="col-sm-9">{{ format_datetime(item.updated_at) }}</dd>
     <dt class="col-sm-3">Serial number</dt>
     <dd class="col-sm-9">{{ item.serial_number }}</dd>
+    <dt class="col-sm-3">Quantity</dt>
+    <dd class="col-sm-9">{{ item.quantity }}</dd>
     <dt class="col-sm-3">Manufacturer</dt>
     <dd class="col-sm-9">{{ item.manufacturer }}</dd>
     <dt class="col-sm-3">Model</dt>
@@ -71,6 +73,7 @@
     <thead>
       <tr>
         <th>Updated</th>
+        <th>Quantity</th>
         <th>Location</th>
         <th>Status</th>
         <th>Parent</th>
@@ -80,6 +83,7 @@
       {% for version in item.history() %}
       <tr>
         <td>{{ version['updated_at'] }}</td>
+        <td>{{ version['quantity'] }}</td>
         <td>{{ version['location'] }}</td>
         <td>{{ version['status'] }}</td>
         <td>{{ link_to_item(version['parent']) }}</td>
diff --git a/tests/functional/test_web.py b/tests/functional/test_web.py
index 1d8dac3..644b41d 100644
--- a/tests/functional/test_web.py
+++ b/tests/functional/test_web.py
@@ -80,4 +80,4 @@ def test_retrieve_items(logged_client, item_factory):
     response = get(logged_client, '/inventory/_retrieve_items')
     items = response.json['data']
     assert set(serial_numbers) == set(item[4] for item in items)
-    assert len(items[0]) == 10
+    assert len(items[0]) == 11
-- 
GitLab