diff --git a/config.local.py b/config.local.py index 8c13253..1003e8a 100644 --- a/config.local.py +++ b/config.local.py @@ -1,2 +1,2 @@ SQLALCHEMY_TRACK_MODIFICATIONS = True -SQLALCHEMY_DATABASE_URI = "postgresql://tetalab_user:tetalab@localhost/tetalab_stock" +SQLALCHEMY_DATABASE_URI = "postgresql://tetastock:tetastock@localhost/tetastock" diff --git a/static/images/login.png b/static/images/login.png new file mode 100644 index 0000000..b0b3ae7 Binary files /dev/null and b/static/images/login.png differ diff --git a/static/images/logout.png b/static/images/logout.png new file mode 100644 index 0000000..b3806f4 Binary files /dev/null and b/static/images/logout.png differ diff --git a/static/scripts/tetalab.js b/static/scripts/tetalab.js index bb69729..2f1a42d 100644 --- a/static/scripts/tetalab.js +++ b/static/scripts/tetalab.js @@ -46,6 +46,36 @@ function valid_input(obj) { , 2000); } +/* ************************************************************************************** + * LOGIN + * **************************************************************************************/ + +function login() { + err = false; + username = document.getElementById('login'); + password = document.getElementById('password'); + if (username.value.length < 1) { + err = true; + invalid_input(username); + } + if (password.value.length < 1){ + err = true; + invalid_input(password); + } + if (err) + return; + + setcookie('login', username.value, 30); + setcookie('password', password.value, 30); + document.location='/'; +} + +function logout() { + setcookie('token', '', 30); + document.location='/'; +} + + /* ************************************************************************************** * COMPONTANTS * **************************************************************************************/ @@ -143,7 +173,7 @@ function search_componants_by_provider(obj) { function confirm_componant_delete() { var msg="La suppression est définitive \net n'est pas autorisée si le \ncomposant fait partie d'un Kit.\n\nConfirmer ?"; - return confirm(msg) + return confirm(msg); } // New componant @@ -383,7 +413,7 @@ function create_provider() { function confirm_provider_delete() { var msg="La suppression est définitive \net n'est pas autorisée si le \nfournisseur est référencé \npar un composant.\n\nConfirmer ?"; - return confirm(msg) + return confirm(msg); } // Update provider @@ -410,3 +440,162 @@ function update_provider(obj, provider_id, type) { xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhttp.send('field='+obj.id+'&value='+obj.value); } + + +/* ************************************************************************************** + * KITS + * **************************************************************************************/ + +// Update result +function update_kits() { + obj = document.getElementById('result_container'); + var xhttp = new XMLHttpRequest(); + xhttp.onerror = function(){ + obj.innerHTML = "Erreur lors de la mise à jour de la liste (1)" + }; + + xhttp.onload = function(){ + if (xhttp.status != 200) { + obj.innerHTML = "Erreur lors de la mise à jour de la liste (2)" + } + }; + + xhttp.onreadystatechange = function() { + if (xhttp.readyState == 4 && xhttp.status == 200) { + var response = xhttp.responseText; + obj.innerHTML = response; + return true; + } + }; + xhttp.open('POST', '/kits/update', true); + xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhttp.send(); +} + +// Result ordering + +function update_kits_by_name(order) { + setcookie('k_order', order, 30); + setcookie('k_sort', 'name', 30); + setcookie('k_order_refresh', '1', 30); + update_kits(); +} + +function update_kits_by_name(order) { + setcookie('k_order', order, 30); + setcookie('k_sort', 'name', 30); + setcookie('k_order_refresh', '1', 30); + update_kits(); +} + +function update_kits_by_designation(order) { + setcookie('k_order', order, 30); + setcookie('k_sort', 'designation', 30); + setcookie('k_order_refresh', '1', 30); + update_kits(); +} + +function k_krevious_kage(prevhop) { + setcookie('k_offset', prevhop, 30); + update_kits(); +} + +function k_next_kage(nexthop) { + setcookie('k_offset', nexthop, 30); + update_kits(); +} + +// Search kits + +function search_kits_by_name(obj) { + setcookie('k_name', obj.value, 30); + update_kits(); +} + +function search_kits_by_designation(obj) { + setcookie('k_designation', obj.value, 30); + update_kits(); +} + +// New kit + +function new_kit() { + var err = false; + var obj = {}; + if (getcookie('k_count') > 0){ + var err = true; + obj[0] = document.getElementById('name'); + } + if (getcookie('k_name').length < 1){ + var err = true; + obj[0] = document.getElementById('name'); + } + if (getcookie('k_designation').length < 1){ + var err = true; + obj[1] = document.getElementById('designation'); + } + if (err == true) { + for (i in obj){ + invalid_input(obj[i]); + } + return; + } + create_kit(); + update_kits(); +} + +function create_kit() { + var MSG='Erreur lors de la creation du kit.'; + var xhttp = new XMLHttpRequest(); + xhttp.onerror = function(){ + alert(MSG); + return false; + }; + + xhttp.onload = function(){ + if (xhttp.readyState == 4 && xhttp.status == 200) { + var response = xhttp.responseText; + if (response == 'OK'){ + return true; + } + alert(MSG); + return false; + } + }; + + xhttp.open('POST', '/kits/new', true); + xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhttp.send(); +} + +// Delete kit + +function confirm_kit_delete() { + var msg="La suppression d'un kit est définitive.\n\nConfirmer ?"; + return confirm(msg); +} + +// Update kit + +function update_kit(obj, kit_id, type) { + var xhttp = new XMLHttpRequest(); + xhttp.onerror = function(){ + invalid_input(obj); + }; + + xhttp.onload = function(){ + if (xhttp.readyState == 4 && xhttp.status == 200) { + var response = xhttp.responseText; + if (response == 'OK'){ + valid_input(obj); + return; + } + obj.style.borderColor = red; + invalid_input(obj); + } + }; + + xhttp.open('POST', '/kits/update/'+kit_id, true); + xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xhttp.send('field='+obj.id+'&value='+obj.value); +} diff --git a/static/style/style.css b/static/style/style.css index d21e2cb..f82c79f 100644 --- a/static/style/style.css +++ b/static/style/style.css @@ -44,6 +44,19 @@ div.top_menu { border-width: 1px 0 0 0; } +div.top_menu input { + position: relative; + top: 4px; + width: 16px; + height: 16px; + border-radius: 2px; + margin-right: 4px; +} + +div.top_menu input:hover { + background-color: #FF5D00; +} + span.top_menu_item { margin: 5px 2px 0 0; font-size: 12px; diff --git a/stock.sql b/stock.sql index 3c642f3..133acf0 100644 --- a/stock.sql +++ b/stock.sql @@ -1,9 +1,13 @@ \c postgres; -drop database tetalab_stock; -create database tetalab_stock; +drop database tetastock; +drop role tetastock; -\c tetalab_stock; +create role tetastock with LOGIN ENCRYPTED PASSWORD 'tetastock'; + +create database tetastock; + +\c tetastock; CREATE TABLE stock_users ( id serial primary key, @@ -14,8 +18,8 @@ CREATE TABLE stock_users ( CREATE TABLE stock_kits ( id serial primary key, - name text not NULL, - description text not NULL + name text not NULL unique, + designation text not NULL ); CREATE TABLE stock_providers ( @@ -46,12 +50,26 @@ CREATE TABLE stock_kit_compositions ( quantity integer not NULL ); -alter table stock_users owner to tetalab_user; -alter table stock_kits owner to tetalab_user; -alter table stock_providers owner to tetalab_user; -alter table stock_componants owner to tetalab_user; -alter table stock_kit_compositions owner to tetalab_user; -alter database tetalab_stock owner to tetalab_user; +CREATE TABLE stock_orders ( + id serial primary key, + componant_id integer REFERENCES stock_componants(id), + quantity integer not NULL, + price NUMERIC not NULL default 0, + date timestamp not NULL +); + +alter table stock_users owner to tetastock; +alter table stock_kits owner to tetastock; +alter table stock_providers owner to tetastock; +alter table stock_componants owner to tetastock; +alter table stock_kit_compositions owner to tetastock; +alter table stock_orders owner to tetastock; +alter database tetastock owner to tetastock; + +insert into stock_users (mail, password, name) values +('doug.letough@free.fr', '$2a$08$578910202124252729313uTyggq4ANEjMljcClFriOqcsttB2fnAW', 'Doug Le Tough'); +insert into stock_users (mail, password, name) values +('doug@redatomik.org', '$2a$08$578910202124252729313uTyggq4ANEjMljcClFriOqcsttB2fnAW', 'Doug Le Tough'); insert into stock_providers (name, address, mail, url, comment) values ('Tous', 'N/A', 'N/A', 'N/A', 'N/A'); diff --git a/templates/componant.html b/templates/componant.html index 8a40813..3dc5da9 100644 --- a/templates/componant.html +++ b/templates/componant.html @@ -6,7 +6,7 @@ Entrée de stock Sortie de stock {% endblock %} - + {% block left_menu %}
Accueil diff --git a/templates/index.html b/templates/index.html index 0a0a2ee..1652b54 100644 --- a/templates/index.html +++ b/templates/index.html @@ -17,6 +17,7 @@
{% block top_menu %} Accueil {% endblock %} +
@@ -38,6 +39,7 @@ {% block content %}

Tetastock

+

Bienvenue {{ user }}

Ceci est l'outil de gestion de stock du Tetalab.

Cet outil vous permet:

    diff --git a/templates/kit.html b/templates/kit.html new file mode 100644 index 0000000..65dff08 --- /dev/null +++ b/templates/kit.html @@ -0,0 +1,47 @@ +{% extends "index.html" %} +{% block title %}Éditer un kit{% endblock %} + {% block top_menu %} + Gérer les kits + Éditer un kit + {% endblock %} + {% block left_menu %} +
    + Accueil +
    +
    + Composants +
    +
    + Kits +
    +
    + Fournisseurs +
    + {% endblock %} + + {% block content %} +
    + Kit: +
    + + +
    +
    + + +
    +
    + {% endblock %} diff --git a/templates/kits.html b/templates/kits.html new file mode 100644 index 0000000..e02145a --- /dev/null +++ b/templates/kits.html @@ -0,0 +1,70 @@ +{% extends "index.html" %} +{% block bodyheader %} + +{% endblock %} +{% block title %}Liste des fournisseurs{% endblock %} + {% block top_menu %} + Gérer les kits + {% endblock %} + + {% block left_menu %} +
    + Accueil +
    +
    + Composants +
    +
    + Kits +
    +
    + Fournisseurs +
    + {% endblock %} + + {% block content %} + + + +
    + +
    + {% endblock %} diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..73e57bd --- /dev/null +++ b/templates/login.html @@ -0,0 +1,50 @@ +{% extends "index.html" %} +{% block title %}Éditer un fournisseur{% endblock %} + {% block top_menu %} + Authentification + {% endblock %} + {% block left_menu %} +
    + Accueil +
    +
    + Composants +
    +
    + Kits +
    +
    + Fournisseurs +
    + {% endblock %} + + {% block content %} +
    + Authentification: +
    + + +
    +
    + + +
    +
    + +
    +
    + {% endblock %} diff --git a/templates/provider.html b/templates/provider.html index 8c0aeb0..dd9635f 100644 --- a/templates/provider.html +++ b/templates/provider.html @@ -21,7 +21,7 @@ {% block content %}
    - Composant: + Fournisseur:
    + Résultat: + {% set ss='' %} + {% if row_count > 1 %} + {% set ss='s' %} + {% endif %} + {{ row_count }} objet{{ ss }} selectionné{{ ss }} + +
    + + + +
    + {% set row_class = cycler('odd', 'even') %} + {% for kit in kits %} +
    + {{ kit.name }} + {{ kit.designation }} +
    + + +
    +
    + {% endfor %} + +
    diff --git a/templates/users.html b/templates/users.html deleted file mode 100644 index f0a0f24..0000000 --- a/templates/users.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Stock Tetalab - {% block title %}Accueil{% endblock %} - - - - - - -
    -
    - -
    - {% block top_menu %} Accueil {% endblock %} -
    -
    -
    - {% block left_menu %} -
    - Accueil -
    -
    - Composants -
    -
    - Kits -
    -
    - Fournisseurs -
    {% endblock %} -
    -
    - {% block content %} -

    Gestion du stock

    -

    Ceci est l'outil de gestion de stock du Tetalab.

    -

    Cet outil vous permet: -

      -
    • De gérer la liste des composants électroniques en possession du Tetalab
    • -
    • De gérer la liste des fournisseurs de composants
    • -
    • De gérer la liste des kits de montage
    • -
    -

    - {% endblock %} -
    -
    - -
    -
    - - diff --git a/tetastock.py b/tetastock.py index 7be8849..06a72d7 100755 --- a/tetastock.py +++ b/tetastock.py @@ -1,6 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 +import os +import datetime +import bcrypt +import binascii import math import psycopg2 from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash @@ -49,111 +53,211 @@ class Stock_providers(db.Model): class Stock_kits(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text, nullable=False) - description = db.Column(db.Text, nullable=False) + designation = db.Column(db.Text, nullable=False) class Stock_kit_compositions(db.Model): id = db.Column(db.Integer, primary_key=True) kit_id = db.Column(db.Integer, db.ForeignKey('Stock_kits.id'), nullable=False) - component_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False) - component_quantity = db.Column(db.Integer, nullable=False) + componant_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False) + quantity = db.Column(db.Integer, nullable=False) + price = db.Column(db.Integer, nullable=False) + +class Stock_orders(db.Model): + id = db.Column(db.Integer, primary_key=True) + componant_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id')) + componant_quantity = db.Column(db.Integer, nullable=False) + date = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) + injected = db.Column(db.Boolean, nullable=False, default=False) + +def sync_cookies(response, session): + """ Sync cookies from session """ + for key in session: + response.set_cookie(key, value=str(session[key])) + if key != u'session': + print '[c]', key, session[key] + +def sync_session(request, session, offset_reset): + """ Sync session with cookies""" + for key in request.cookies: + try: + old = str(session[key]) + session[key] = int(str(request.cookies[key].encode('utf8'))) + except ValueError: + # Value is not an int, will be treated as string + session[key] = str(request.cookies[key].encode('utf8')) + except KeyError: + # Key does not exist in session + try: + session[key] = int(str(request.cookies[key].encode('utf8'))) + except ValueError: + # Value is not an int, will be treated as string + session[key] = str(request.cookies[key].encode('utf8')) + if key in offset_reset and len(str(session[key])) > 0 and old != str(session[key]): + session['c_offset'] = 0 + session['p_offset'] = 0 + session['k_offset'] = 0 + if key != u'session': + print '[s]', key, request.cookies[key] + +def check_user(request, session): + """ Check user credentials """ + if session['token'] and request.cookies['token']: + if len(session['token']) > 0 and len(request.cookies['token']) > 0: + if session['token'] == request.cookies['token']: + return True + return False + if 'login' not in request.cookies or 'password' not in request.cookies: + return False + if request.cookies['login'] and request.cookies['password']: + if request.cookies['login'] > 0 and request.cookies['password'] > 0: + hashed = Stock_users.query.filter_by(mail=request.cookies['login']).with_entities(Stock_users.password).first() + if hashed is None: + # User is unknown + return False + password = request.cookies['password'].encode('utf8') + hashed = hashed[0].encode('utf8') + if bcrypt.checkpw(password, hashed): + session['password'] = '' + session['login'] = '' + session['token'] = binascii.hexlify(os.urandom(42)) + return True + # Password mismatch + return False + def resume_session(func): @wraps(func) def check(*args, **kwargs): - # default + # Motherfuckin' bunch of defaults values + empty=u'' limit = 10 offset = 0 page = 1 nexthop = offset + limit prevhop = offset - order = 'asc' + order = u'asc' order_refresh = 0 - c_empty = '' - c_sort = 'reference' + c_sort = u'reference' c_provider = 0 c_count = 0 - p_empty = '' - p_sort = 'name' - offset_reset = ['c_reference', 'c_designation', 'c_place', 'c_provider'] - if not 'session' in session: - session['session'] = '' - if not 'c_limit' in session: - session['c_limit'] = limit - if not 'c_offest' in session: - session['c_offset'] = offset - if not 'c_sort' in session: + p_sort = u'name' + p_count = 0 + k_sort = u'name' + k_count = 0 + offset_reset = [u'c_reference', u'c_designation', u'c_place', + u'c_provider', u'p_name', u'p_address', u'p_mail', u'p_url', + u'k_name', u'k_designation'] + if not u'token' in session: + session[u'token'] = empty + if not u'password' in session: + session[u'password'] = empty + if not u'login' in session: + session[u'login'] = empty + if not u'session' in session: + session[u'session'] = empty + if not u'c_limit' in session: + session[u'c_limit'] = limit + if not u'c_offest' in session: + session[u'c_offset'] = offset + if not u'c_sort' in session: session['c_sort'] = c_sort - if not 'c_order' in session: - session['c_order'] = order - if not 'c_order_refresh' in session: - session['c_order_refresh'] = order_refresh - if not 'c_page' in session: - session['c_page'] = page - if not 'c_nexthop' in session: - session['c_nexthop'] = nexthop - if not 'c_prevhop' in session: + if not u'c_order' in session: + session[u'c_order'] = order + if not u'c_order_refresh' in session: + session[u'c_order_refresh'] = order_refresh + if not u'c_page' in session: + session[u'c_page'] = page + if not u'c_nexthop' in session: + session[u'c_nexthop'] = nexthop + if not u'c_prevhop' in session: session['c_prevhop'] = prevhop - if not 'c_reference' in session: - session['c_reference'] = c_empty - if not 'c_designation' in session: - session['c_designation'] = c_empty - if not 'c_place' in session: - session['c_place'] = c_empty - if not 'c_provider' in session: - session['c_provider'] = c_provider - if not 'c_count' in session: - session['c_count'] = c_count - if not 'p_sort' in session: - session['p_sort'] = p_sort - if not 'p_order' in session: - session['p_order'] = order - if not 'p_order_refresh' in session: - session['p_order_refresh'] = order_refresh - if not 'p_page' in session: - session['p_page'] = page - if not 'p_nexthop' in session: - session['p_nexthop'] = nexthop - if not 'p_prevhop' in session: - session['p_prevhop'] = prevhop - if not 'p_offset' in session: - session['p_offset'] = offset - if not 'p_limit' in session: - session['p_limit'] = limit - if not 'p_name' in session: - session['p_name'] = p_empty - if not 'p_address' in session: - session['p_address'] = p_empty - if not 'p_mail' in session: - session['p_mail'] = p_empty - if not 'p_url' in session: - session['p_url'] = p_empty - if not 'p_comment' in session: - session['p_comment'] = p_empty + if not u'c_reference' in session: + session[u'c_reference'] = empty + if not u'c_designation' in session: + session[u'c_designation'] = empty + if not u'c_place' in session: + session[u'c_place'] = empty + if not u'c_provider' in session: + session[u'c_provider'] = c_provider + if not u'c_count' in session: + session[u'c_count'] = c_count + if not u'p_sort' in session: + session[u'p_sort'] = p_sort + if not u'p_order' in session: + session[u'p_order'] = order + if not u'p_order_refresh' in session: + session[u'p_order_refresh'] = order_refresh + if not u'p_page' in session: + session[u'p_page'] = page + if not u'p_nexthop' in session: + session[u'p_nexthop'] = nexthop + if not u'p_prevhop' in session: + session[u'p_prevhop'] = prevhop + if not u'p_offset' in session: + session[u'p_offset'] = offset + if not u'p_limit' in session: + session[u'p_limit'] = limit + if not u'p_name' in session: + session[u'p_name'] = empty + if not u'p_address' in session: + session[u'p_address'] = empty + if not u'p_mail' in session: + session[u'p_mail'] = empty + if not u'p_url' in session: + session[u'p_url'] = empty + if not u'p_comment' in session: + session[u'p_comment'] = empty + if not u'p_count' in session: + session['p_count'] = p_count + if not u'k_sort' in session: + session[u'k_sort'] = k_sort + if not u'k_order' in session: + session[u'k_order'] = order + if not u'k_order_refresh' in session: + session[u'k_order_refresh'] = order_refresh + if not u'k_page' in session: + session[u'k_page'] = page + if not u'k_nexthop' in session: + session[u'k_nexthop'] = nexthop + if not u'k_prevhop' in session: + session[u'k_prevhop'] = prevhop + if not u'k_offset' in session: + session[u'k_offset'] = offset + if not u'k_limit' in session: + session[u'k_limit'] = limit + if not u'k_name' in session: + session[u'k_name'] = empty + if not u'k_address' in session: + session[u'k_address'] = empty + if not u'k_mail' in session: + session[u'k_mail'] = empty + if not u'k_url' in session: + session[u'k_url'] = empty + if not u'k_designation' in session: + session[u'k_designation'] = empty + if not u'k_count' in session: + session[u'k_count'] = k_count # Cookies/session sync - for key in request.cookies: - old = str(session[key]) - try: - session[key] = int(str(request.cookies[key])) - except ValueError: - # Value is not an int, will be treated as string - session[key] = str(request.cookies[key]) - if key in offset_reset and len(str(session[key])) > 0 and old != str(session[key]): - session['c_offset'] = 0 - - if key != 'session': - print '[s]', key, request.cookies[key] - + sync_session(request, session, offset_reset) # Switch sort order - if session['c_order_refresh'] == 1: - refresh = {'desc': 'asc', 'asc': 'desc'} - session['c_order'] = refresh[session['c_order']] - session['c_order_refresh'] = 0 - if session['p_order_refresh'] == 1: - refresh = {'desc': 'asc', 'asc': 'desc'} - session['p_order'] = refresh[session['p_order']] - session['p_order_refresh'] = 0 + refresh = {u'desc': u'asc', u'asc': u'desc'} + if session[u'c_order_refresh'] == 1: + session[u'c_order'] = refresh[session[u'c_order']] + session[u'c_order_refresh'] = 0 + if session[u'p_order_refresh'] == 1: + session[u'p_order'] = refresh[session[u'p_order']] + session[u'p_order_refresh'] = 0 + if session[u'k_order_refresh'] == 1: + session[u'k_order'] = refresh[session[u'k_order']] + session[u'k_order_refresh'] = 0 + + # Check for valid session + if not check_user(request, session): + # User is not logged in, send him back to login page + return render_template('login.html') + # Everything's fine return func(*args, **kwargs) return check @@ -164,9 +268,12 @@ def resume_session(func): def page_not_found(e): return render_template('error.html'), 404 -@app.route("/") +@app.route("/", methods=['GET', 'POST']) +@resume_session def authenticate(): - return render_template('index.html') + response = app.make_response(render_template('index.html')) + sync_cookies(response, session) + return response ######################################################################## @@ -180,10 +287,10 @@ def componants(): providers = Stock_providers.query.order_by(Stock_providers.id).all() return render_template('componants.html', providers=providers, - reference=session['c_reference'], - designation=session['c_designation'], - place=session['c_place'], - provider_id=session['c_provider']) + reference=session[u'c_reference'].decode('utf8'), + designation=session[u'c_designation'].decode('utf8'), + place=session[u'c_place'].decode('utf8'), + provider_id=session[u'c_provider']) @app.route('/componants/') @resume_session @@ -229,26 +336,32 @@ def delete_componant(componant_id): except ValueError as e: return render_template('error.html'), 404 except Exception as e: - print "[+] Error at delete_componant:\n------------------------------\n%s------------------------------" % e.message + print "[+] Error at delete_componant:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" return componants() @app.route('/componants/new', methods=['POST']) @resume_session def new_componant(): """ Add componant """ - componant = Stock_componants(reference=session['c_reference'], - designation=session['c_designation'], + componant = Stock_componants(reference=session[u'c_reference'].decode('utf8'), + designation=session[u'c_designation'].decode('utf8'), last_price=0, mean_price=0, quantity=0, min_quantity=0, - place=session['c_place'], - provider_id=session['c_provider']) + place=session[u'c_place'].decode('utf8'), + provider_id=session[u'c_provider']) try: db.session.add(componant) commit = db.session.commit() except Exception as e: - print "[+] Error at new_componant:\n------------------------------\n%s------------------------------" % e.message + print "[+] Error at new_componant:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" return 'KO' if commit != None: return 'KO' @@ -272,56 +385,53 @@ def out_componants(): def update_componants(): """ Display componants list """ # search by reference - like = '%s%s%s' % ('%', str(session['c_reference']), '%') + like = '%s%s%s' % ('%', str(session[u'c_reference']), '%') componants = Stock_componants.query.filter(Stock_componants.reference.like(like)) # search by designation - like = '%s%s%s' % ('%', str(session['c_designation']), '%') + like = '%s%s%s' % ('%', str(session[u'c_designation']), '%') componants = componants.filter(Stock_componants.designation.like(like)) # search by place - like = '%s%s%s' % ('%', str(session['c_place']),'%') + like = '%s%s%s' % ('%', str(session[u'c_place']),'%') componants = componants.filter(Stock_componants.place.like(like)) # search by provider if session['c_provider'] > 1: - componants = componants.filter_by(provider_id=session['c_provider']) + componants = componants.filter_by(provider_id=session[u'c_provider']) # Pages calculation - session['c_count'] = componants.count() - session['c_pagecount'] = int(math.ceil(session['c_count'] / float(session['c_limit']))) - session['c_page'] = int(math.ceil(float(float(session['c_offset']) + 1) / float(session['c_limit']))) - if session['c_page'] > session['c_pagecount']: - session['c_page'] = session['c_pagecount'] - session['c_offset'] = 0 - session['c_nexthop'] = session['c_offset'] + session['c_limit'] - if session['c_nexthop'] > session['c_count'] - 1: - session['c_nexthop'] = int(session['c_offset']) - session['c_prevhop'] = int(session['c_offset']) - session['c_limit'] - if session['c_prevhop'] < 0: - session['c_prevhop'] = 0 + session[u'c_count'] = componants.count() + session[u'c_pagecount'] = int(math.ceil(session[u'c_count'] / float(session[u'c_limit']))) + session[u'c_page'] = int(math.ceil(float(float(session[u'c_offset']) + 1) / float(session[u'c_limit']))) + if session[u'c_page'] > session[u'c_pagecount']: + session[u'c_page'] = session[u'c_pagecount'] + session[u'c_offset'] = 0 + session[u'c_nexthop'] = session[u'c_offset'] + session[u'c_limit'] + if session[u'c_nexthop'] > session[u'c_count'] - 1: + session[u'c_nexthop'] = int(session[u'c_offset']) + session[u'c_prevhop'] = int(session[u'c_offset']) - session[u'c_limit'] + if session[u'c_prevhop'] < 0: + session[u'c_prevhop'] = 0 # Sorting - sort = getattr(Stock_componants, session['c_sort']) - if session['c_order'] == 'desc': - sort = getattr(Stock_componants, session['c_sort']).desc() + sort = getattr(Stock_componants, session[u'c_sort']) + if session[u'c_order'] == u'desc': + sort = getattr(Stock_componants, session[u'c_sort']).desc() componants = componants.order_by(sort) # Applying offset - componants = componants.offset(session['c_offset']) + componants = componants.offset(session[u'c_offset']) # Applying limit - componants = componants.limit(session['c_limit']) + componants = componants.limit(session[u'c_limit']) # Get result componants = componants.all() response = app.make_response(render_template('result_componants.html', componants=componants, - offset=session['c_offset'] , - nexthop=session['c_nexthop'], - prevhop=session['c_prevhop'], - page_count=session['c_pagecount'], - page=session['c_page'], - sort=session['c_sort'], - order=session['c_order'], - row_count=session['c_count'])) - for key in session: - response.set_cookie(key, value=str(session[key])) - if key != 'session': - print '[c]', key, session[key] + offset=session[u'c_offset'] , + nexthop=session[u'c_nexthop'], + prevhop=session[u'c_prevhop'], + page_count=session[u'c_pagecount'], + page=session[u'c_page'], + sort=session[u'c_sort'].decode('utf8'), + order=session[u'c_order'].decode('utf8'), + row_count=session[u'c_count'])) + sync_cookies(response, session) return response ######################################################################## @@ -331,11 +441,11 @@ def update_componants(): @resume_session def providers(): return render_template('providers.html', - name=session['p_name'], - address=session['p_address'], - mail=session['p_mail'], - url=session['p_url'], - comment=session['p_comment']) + name=session[u'p_name'].decode('utf8'), + address=session[u'p_address'].decode('utf8'), + mail=session[u'p_mail'].decode('utf8'), + url=session[u'p_url'].decode('utf8'), + comment=session[u'p_comment'].decode('utf8')) @app.route('/providers/') @resume_session @@ -372,17 +482,19 @@ def update_provider(provider_id): @resume_session def new_provider(): """ Add provider """ - provider = Stock_providers(name=session['p_name'], - address=session['p_address'], - mail=session['p_mail'], - url=session['p_url'], - comment=session['p_comment']) + provider = Stock_providers(name=session[u'p_name'].decode('utf8'), + address=session[u'p_address'].decode('utf8'), + mail=session[u'p_mail'].decode('utf8'), + url=session[u'p_url'].decode('utf8'), + comment=session[u'p_comment'].decode('utf8')) try: db.session.add(provider) commit = db.session.commit() except Exception as e: - print 'Error at new_provider():', e - print 'Commit = ', commit + print "[+] Error at new_provider:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" return 'KO' if commit != None: return 'KO' @@ -399,7 +511,10 @@ def delete_provider(provider_id): except ValueError as e: return render_template('error.html'), 404 except Exception as e: - print "[+] Error at delete_provider:\n-----------------------------\n%s-----------------------------" % e.message + print "[+] Error at delete_provider:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" return providers() @app.route('/providers/update', methods=['POST']) @@ -407,69 +522,188 @@ def delete_provider(provider_id): def search_providers(): """ Display componants list """ # search by reference - like = '%s%s%s' % ('%', str(session['p_name']), '%') + like = '%s%s%s' % ('%', str(session[u'p_name']), '%') providers = Stock_providers.query.filter(Stock_providers.name.like(like)) - # search by designation - like = '%s%s%s' % ('%', str(session['p_address']), '%') + # search by address + like = '%s%s%s' % ('%', str(session[u'p_address']), '%') providers = providers.filter(Stock_providers.address.like(like)) # search by place - like = '%s%s%s' % ('%', str(session['p_mail']),'%') + like = '%s%s%s' % ('%', str(session[u'p_mail']),'%') providers = providers.filter(Stock_providers.mail.like(like)) # search by place - like = '%s%s%s' % ('%', str(session['p_url']),'%') + like = '%s%s%s' % ('%', str(session[u'p_url']),'%') providers = providers.filter(Stock_providers.url.like(like)) # search by place - like = '%s%s%s' % ('%', str(session['p_comment']),'%') + like = '%s%s%s' % ('%', str(session[u'p_comment']),'%') providers = providers.filter(Stock_providers.comment.like(like)) # Don't take 'all' and 'none' entry providers = providers.filter(Stock_providers.id > 2) # Pages calculation - session['p_count'] = providers.count() - session['p_pagecount'] = int(math.ceil(session['p_count'] / float(session['p_limit']))) - session['p_page'] = int(math.ceil(float(float(session['p_offset']) + 1) / float(session['p_limit']))) - if session['p_page'] > session['p_pagecount']: - session['p_page'] = session['p_pagecount'] - session['p_offset'] = 0 - session['p_nexthop'] = session['p_offset'] + session['p_limit'] - if session['p_nexthop'] > session['p_count'] - 1: - session['p_nexthop'] = int(session['p_offset']) - session['p_prevhop'] = int(session['p_offset']) - session['p_limit'] - if session['p_prevhop'] < 0: - session['p_prevhop'] = 0 + session[u'p_count'] = providers.count() + session[u'p_pagecount'] = int(math.ceil(session[u'p_count'] / float(session[u'p_limit']))) + session[u'p_page'] = int(math.ceil(float(float(session[u'p_offset']) + 1) / float(session[u'p_limit']))) + if session[u'p_page'] > session[u'p_pagecount']: + session[u'p_page'] = session[u'p_pagecount'] + session[u'p_offset'] = 0 + session[u'p_nexthop'] = session[u'p_offset'] + session[u'p_limit'] + if session[u'p_nexthop'] > session[u'p_count'] - 1: + session[u'p_nexthop'] = int(session[u'p_offset']) + session[u'p_prevhop'] = int(session[u'p_offset']) - session[u'p_limit'] + if session[u'p_prevhop'] < 0: + session[u'p_prevhop'] = 0 # Sorting - sort = getattr(Stock_providers, session['p_sort']) - if session['p_order'] == 'desc': - sort = getattr(Stock_providers, session['p_sort']).desc() + sort = getattr(Stock_providers, session[u'p_sort']) + if session[u'p_order'] == u'desc': + sort = getattr(Stock_providers, session[u'p_sort']).desc() providers = providers.order_by(sort) # Applying offset - providers = providers.offset(session['p_offset']) + providers = providers.offset(session[u'p_offset']) # Applying limit - providers = providers.limit(session['p_limit']) + providers = providers.limit(session[u'p_limit']) # Get result providers = providers.all() response = app.make_response(render_template('result_providers.html', providers=providers, - offset=session['p_offset'] , - nexthop=session['p_nexthop'], - prevhop=session['p_prevhop'], - page_count=session['p_pagecount'], - page=session['p_page'], - sort=session['p_sort'], - order=session['p_order'], - row_count=session['p_count'])) - for key in session: - response.set_cookie(key, value=str(session[key])) - if key != 'session': - print '[c]', key, session[key] + offset=session[u'p_offset'] , + nexthop=session[u'p_nexthop'], + prevhop=session[u'p_prevhop'], + page_count=session[u'p_pagecount'], + page=session[u'p_page'], + sort=session[u'p_sort'].decode('utf8'), + order=session[u'p_order'].decode('utf8'), + row_count=session[u'p_count'])) + sync_cookies(response, session) return response ######################################################################## # Kits ######################################################################## +@app.route('/kits', methods=['GET', 'POST']) +@resume_session +def kits(): + return render_template('kits.html', + name=session[u'k_name'].decode('utf8'), + designation=session[u'k_designation'].decode('utf8')) - +@app.route('/kits/') +@resume_session +def get_kit(kit_id): + """ Edit kit """ + try: + kit_id = int(kit_id) + except ValueError as e: + return render_template('error.html'), 404 + kit = Stock_kits.query.filter_by(id=kit_id).first() + if kit: + return render_template('kit.html', kit=kit) + return render_template('error.html'), 404 + +@app.route('/kits/update/', methods=['POST']) +@resume_session +def update_kit(kit_id): + """ Update kit field""" + field = request.form['field'] + value = request.form['value'] + if field and value: + try: + kit = Stock_kits.query.filter_by(id=kit_id).first() + setattr(kit, field, value) + commit = db.session.commit() + if commit == None: + return 'OK' + except Exception as e: + pass + return 'KO' + +@app.route('/kits/new', methods=['POST']) +@resume_session +def new_kit(): + """ Add kit """ + kit = Stock_kits(name=session[u'k_name'].decode('utf8'), + designation=session[u'k_designation'].decode('utf8')) + try: + db.session.add(kit) + commit = db.session.commit() + except Exception as e: + print "[+] Error at new_kit:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" + return 'KO' + if commit != None: + return 'KO' + return 'OK' + +@app.route('/kits/delete/') +@resume_session +def delete_kit(kit_id): + """ Delete kit """ + try: + kit_id = int(kit_id) + Stock_kit_compositions.query.filter_by(kit_id=kit_id).delete() + Stock_kits.query.filter_by(id=kit_id).delete() + db.session.commit() + except ValueError as e: + return render_template('error.html'), 404 + except Exception as e: + print "[+] Error at delete_kit:" + print "------------------------------" + print "%s" % e.message + print "------------------------------" + return kits() + +@app.route('/kits/update', methods=['POST']) +@resume_session +def search_kits(): + """ Display componants list """ + # search by name + like = '%s%s%s' % ('%', str(session[u'k_name']), '%') + kits = Stock_kits.query.filter(Stock_kits.name.like(like)) + # search by designation + like = '%s%s%s' % ('%', str(session[u'k_designation']), '%') + kits = kits.filter(Stock_kits.designation.like(like)) + + # Pages calculation + session[u'k_count'] = kits.count() + session[u'k_pagecount'] = int(math.ceil(session[u'k_count'] / float(session[u'k_limit']))) + session[u'k_page'] = int(math.ceil(float(float(session[u'k_offset']) + 1) / float(session[u'k_limit']))) + if session[u'k_page'] > session[u'k_pagecount']: + session[u'k_page'] = session[u'k_pagecount'] + session[u'k_offset'] = 0 + session[u'k_nexthop'] = session[u'k_offset'] + session[u'k_limit'] + if session[u'k_nexthop'] > session[u'k_count'] - 1: + session[u'k_nexthop'] = int(session[u'k_offset']) + session[u'k_prevhop'] = int(session[u'k_offset']) - session[u'k_limit'] + if session[u'k_prevhop'] < 0: + session[u'k_prevhop'] = 0 + # Sorting + sort = getattr(Stock_kits, session[u'k_sort'].decode('utf8')) + if session[u'k_order'] == 'desc': + sort = getattr(Stock_kits, session[u'k_sort'].decode('utf8')).desc() + kits = kits.order_by(sort) + # Applying offset + kits = kits.offset(session[u'k_offset']) + # Applying limit + kits = kits.limit(session[u'k_limit']) + # Get result + kits = kits.all() + response = app.make_response(render_template('result_kits.html', + kits=kits, + offset=session[u'k_offset'] , + nexthop=session[u'k_nexthop'], + prevhop=session[u'k_prevhop'], + page_count=session[u'k_pagecount'], + page=session[u'k_page'], + sort=session[u'k_sort'].decode('utf8'), + order=session[u'k_order'].decode('utf8'), + row_count=session[u'k_count'])) + for key in session: + response.set_cookie(key, value=str(session[key])) + if key != 'session': + print '[c]', key, session[key] + return response ######################################################################## # Users