Browse Source

"Support UTF-8 + gestion de base des kits"

Doug Le Tough 3 years ago
parent
commit
0a63c23c49

+ 1
- 1
config.local.py View File

@@ -1,2 +1,2 @@
1 1
 SQLALCHEMY_TRACK_MODIFICATIONS = True
2
-SQLALCHEMY_DATABASE_URI = "postgresql://tetalab_user:tetalab@localhost/tetalab_stock"
2
+SQLALCHEMY_DATABASE_URI = "postgresql://tetastock:tetastock@localhost/tetastock"

BIN
static/images/login.png View File


BIN
static/images/logout.png View File


+ 191
- 2
static/scripts/tetalab.js View File

@@ -46,6 +46,36 @@ function valid_input(obj) {
46 46
   , 2000);
47 47
 }
48 48
 
49
+/* **************************************************************************************
50
+ * LOGIN
51
+ * **************************************************************************************/
52
+
53
+function login() {
54
+  err = false;
55
+  username = document.getElementById('login');
56
+  password = document.getElementById('password');
57
+  if (username.value.length < 1) {
58
+    err = true;
59
+    invalid_input(username);
60
+  }
61
+  if (password.value.length < 1){
62
+    err = true;
63
+    invalid_input(password);
64
+  }
65
+  if (err)
66
+    return;
67
+  
68
+  setcookie('login', username.value, 30);
69
+  setcookie('password', password.value, 30);
70
+  document.location='/';
71
+}
72
+
73
+function logout() {
74
+  setcookie('token', '', 30);
75
+  document.location='/';
76
+}
77
+
78
+
49 79
 /* **************************************************************************************
50 80
  * COMPONTANTS
51 81
  * **************************************************************************************/
@@ -143,7 +173,7 @@ function search_componants_by_provider(obj) {
143 173
 
144 174
 function confirm_componant_delete() {
145 175
   var msg="La suppression est définitive \net n'est pas autorisée si le \ncomposant fait partie d'un Kit.\n\nConfirmer ?";
146
-  return confirm(msg)
176
+  return confirm(msg);
147 177
 }
148 178
 
149 179
 // New componant
@@ -383,7 +413,7 @@ function create_provider() {
383 413
 
384 414
 function confirm_provider_delete() {
385 415
   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 ?";
386
-  return confirm(msg)
416
+  return confirm(msg);
387 417
 }
388 418
 
389 419
 // Update provider
@@ -410,3 +440,162 @@ function update_provider(obj, provider_id, type) {
410 440
   xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
411 441
   xhttp.send('field='+obj.id+'&value='+obj.value);
412 442
 }
443
+
444
+
445
+/* **************************************************************************************
446
+ * KITS
447
+ * **************************************************************************************/
448
+
449
+// Update result
450
+function update_kits() {
451
+  obj = document.getElementById('result_container');
452
+  var xhttp = new XMLHttpRequest();
453
+  xhttp.onerror = function(){
454
+    obj.innerHTML = "Erreur lors de la mise à jour de la liste (1)"
455
+  };
456
+
457
+  xhttp.onload = function(){
458
+    if (xhttp.status != 200) {
459
+      obj.innerHTML = "Erreur lors de la mise à jour de la liste (2)"
460
+      } 
461
+  };
462
+
463
+  xhttp.onreadystatechange = function() {
464
+    if (xhttp.readyState == 4 && xhttp.status == 200) {
465
+      var response = xhttp.responseText;
466
+      obj.innerHTML = response;
467
+      return true;
468
+    }
469
+  };
470
+  xhttp.open('POST', '/kits/update', true);
471
+  xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
472
+  xhttp.send();
473
+}
474
+
475
+// Result ordering
476
+
477
+function update_kits_by_name(order) {
478
+  setcookie('k_order', order, 30);
479
+  setcookie('k_sort', 'name', 30);
480
+  setcookie('k_order_refresh', '1', 30);
481
+  update_kits();
482
+}
483
+
484
+function update_kits_by_name(order) {
485
+  setcookie('k_order', order, 30);
486
+  setcookie('k_sort', 'name', 30);
487
+  setcookie('k_order_refresh', '1', 30);
488
+  update_kits();
489
+}
490
+
491
+function update_kits_by_designation(order) {
492
+  setcookie('k_order', order, 30);
493
+  setcookie('k_sort', 'designation', 30);
494
+  setcookie('k_order_refresh', '1', 30);
495
+  update_kits();
496
+}
497
+
498
+function k_krevious_kage(prevhop) {
499
+  setcookie('k_offset', prevhop, 30);
500
+  update_kits();
501
+}
502
+
503
+function k_next_kage(nexthop) {
504
+  setcookie('k_offset', nexthop, 30);
505
+  update_kits();
506
+}
507
+
508
+// Search kits
509
+
510
+function search_kits_by_name(obj) {
511
+  setcookie('k_name', obj.value, 30);
512
+  update_kits();
513
+}
514
+
515
+function search_kits_by_designation(obj) {
516
+  setcookie('k_designation', obj.value, 30);
517
+  update_kits();
518
+}
519
+
520
+// New kit
521
+
522
+function new_kit() {
523
+  var err = false;
524
+  var obj = {};
525
+  if (getcookie('k_count') > 0){
526
+    var err = true;
527
+    obj[0] = document.getElementById('name');
528
+  }
529
+  if (getcookie('k_name').length < 1){
530
+    var err = true;
531
+    obj[0] = document.getElementById('name');
532
+  }
533
+  if (getcookie('k_designation').length < 1){
534
+    var err = true;
535
+    obj[1] = document.getElementById('designation');
536
+  }
537
+  if (err == true) {
538
+    for (i in obj){
539
+      invalid_input(obj[i]);
540
+    }
541
+    return;
542
+  }
543
+  create_kit();
544
+  update_kits();
545
+}
546
+
547
+function create_kit() {
548
+  var MSG='Erreur lors de la creation du kit.';
549
+  var xhttp = new XMLHttpRequest();
550
+  xhttp.onerror = function(){
551
+    alert(MSG);
552
+    return false;
553
+  };
554
+
555
+  xhttp.onload = function(){
556
+    if (xhttp.readyState == 4 && xhttp.status == 200) {
557
+      var response = xhttp.responseText;
558
+      if (response == 'OK'){
559
+        return true;
560
+      }
561
+      alert(MSG);
562
+      return false;
563
+    }
564
+  };
565
+
566
+  xhttp.open('POST', '/kits/new', true);
567
+  xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
568
+  xhttp.send();
569
+}
570
+
571
+// Delete kit
572
+
573
+function confirm_kit_delete() {
574
+  var msg="La suppression d'un kit est définitive.\n\nConfirmer ?";
575
+  return confirm(msg);
576
+}
577
+
578
+// Update kit
579
+
580
+function update_kit(obj, kit_id, type) {
581
+  var xhttp = new XMLHttpRequest();
582
+  xhttp.onerror = function(){
583
+    invalid_input(obj);
584
+  };
585
+
586
+  xhttp.onload = function(){
587
+    if (xhttp.readyState == 4 && xhttp.status == 200) {
588
+      var response = xhttp.responseText;
589
+      if (response == 'OK'){
590
+        valid_input(obj);
591
+        return;
592
+      }
593
+      obj.style.borderColor = red;
594
+      invalid_input(obj);
595
+    }
596
+  };
597
+
598
+  xhttp.open('POST', '/kits/update/'+kit_id, true);
599
+  xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
600
+  xhttp.send('field='+obj.id+'&value='+obj.value);
601
+}

+ 13
- 0
static/style/style.css View File

@@ -44,6 +44,19 @@ div.top_menu {
44 44
   border-width: 1px 0 0 0;
45 45
 }
46 46
 
47
+div.top_menu input {
48
+  position: relative;
49
+  top: 4px;
50
+  width: 16px;
51
+  height: 16px;
52
+  border-radius: 2px;
53
+  margin-right: 4px;
54
+}
55
+
56
+div.top_menu input:hover {
57
+  background-color: #FF5D00;
58
+}
59
+
47 60
 span.top_menu_item {
48 61
   margin: 5px 2px 0 0;
49 62
   font-size: 12px;

+ 29
- 11
stock.sql View File

@@ -1,9 +1,13 @@
1 1
 \c postgres;
2 2
 
3
-drop database tetalab_stock;
4
-create database tetalab_stock;
3
+drop database tetastock;
4
+drop role tetastock;
5 5
 
6
-\c tetalab_stock;
6
+create role tetastock with LOGIN ENCRYPTED PASSWORD 'tetastock';
7
+
8
+create database tetastock;
9
+
10
+\c tetastock;
7 11
 
8 12
 CREATE TABLE stock_users (
9 13
   id serial primary key,
@@ -14,8 +18,8 @@ CREATE TABLE stock_users (
14 18
 
15 19
 CREATE TABLE stock_kits (
16 20
   id serial primary key,
17
-  name text not NULL,
18
-  description text not NULL
21
+  name text not NULL unique,
22
+  designation text not NULL
19 23
 );
20 24
 
21 25
 CREATE TABLE stock_providers (
@@ -46,12 +50,26 @@ CREATE TABLE stock_kit_compositions (
46 50
   quantity integer not NULL
47 51
 );
48 52
 
49
-alter table stock_users owner to tetalab_user;
50
-alter table stock_kits owner to tetalab_user;
51
-alter table stock_providers owner to tetalab_user;
52
-alter table stock_componants owner to tetalab_user;
53
-alter table stock_kit_compositions owner to tetalab_user;
54
-alter database tetalab_stock owner to tetalab_user;
53
+CREATE TABLE stock_orders (
54
+  id serial primary key,
55
+  componant_id integer REFERENCES stock_componants(id),
56
+  quantity integer not NULL,
57
+  price NUMERIC not NULL default 0,
58
+  date timestamp not NULL
59
+);
60
+
61
+alter table stock_users owner to tetastock;
62
+alter table stock_kits owner to tetastock;
63
+alter table stock_providers owner to tetastock;
64
+alter table stock_componants owner to tetastock;
65
+alter table stock_kit_compositions owner to tetastock;
66
+alter table stock_orders owner to tetastock;
67
+alter database tetastock owner to tetastock;
68
+
69
+insert into stock_users (mail, password, name) values
70
+('doug.letough@free.fr', '$2a$08$578910202124252729313uTyggq4ANEjMljcClFriOqcsttB2fnAW', 'Doug Le Tough');
71
+insert into stock_users (mail, password, name) values
72
+('doug@redatomik.org', '$2a$08$578910202124252729313uTyggq4ANEjMljcClFriOqcsttB2fnAW', 'Doug Le Tough');
55 73
 
56 74
 insert into stock_providers (name, address, mail, url, comment)
57 75
   values ('Tous', 'N/A', 'N/A', 'N/A', 'N/A');

+ 1
- 1
templates/componant.html View File

@@ -6,7 +6,7 @@
6 6
         <span class='top_menu_item' onclick='javascript:document.location="/componants/in";'>Entrée de stock</span>
7 7
         <span class='top_menu_item' onclick='javascript:document.location="/componants/out";'>Sortie de stock</span>
8 8
         {% endblock %}
9
-        
9
+
10 10
           {% block left_menu %}
11 11
           <div class='left_menu_item' onclick='javascript:document.location="/";'>
12 12
             Accueil

+ 2
- 0
templates/index.html View File

@@ -17,6 +17,7 @@
17 17
       </div>
18 18
       <div class='top_menu'>
19 19
         {% block top_menu %} <span class='top_menu_item_selected' onclick='javascript:document.location="./";'>Accueil</span> {% endblock %}
20
+        <input type='image' src='/static/images/logout.png' title='Se deconnecter' value='' onclick='javascript:logout();' />
20 21
       </div>
21 22
       <div class='content_wrapper'>
22 23
         <div class='left_menu'>
@@ -38,6 +39,7 @@
38 39
           {% block content %}
39 40
           <h1>Tetastock</h1>
40 41
           <div class='note'>
42
+            <p>Bienvenue {{ user }}</p>
41 43
             <p>Ceci est l'outil de gestion de stock du <a href='https://www.tetalab.org'>Tetalab</a>.</p>
42 44
             <p>Cet outil vous permet:
43 45
               <ul>

+ 47
- 0
templates/kit.html View File

@@ -0,0 +1,47 @@
1
+{% extends "index.html" %}
2
+{% block title %}Éditer un kit{% endblock %}
3
+        {% block top_menu %}
4
+        <span class='top_menu_item' onclick='javascript:document.location="/providers";'>Gérer les kits</span>
5
+        <span class='top_menu_item_selected' onclick='javascript:document.location="/kits/{{ kit.id }}";'>Éditer un kit</span>
6
+        {% endblock %}
7
+          {% block left_menu %}
8
+          <div class='left_menu_item' onclick='javascript:document.location="/";'>
9
+            Accueil
10
+          </div>
11
+          <div class='left_menu_item' onclick='javascript:document.location="/componants";'>
12
+            Composants
13
+          </div>
14
+          <div class='left_menu_item_selected' onclick='javascript:document.location="/kits";'>
15
+            Kits
16
+          </div>
17
+          <div class='left_menu_item' onclick='javascript:document.location="/providers";'>
18
+            Fournisseurs
19
+          </div>
20
+          {% endblock %}
21
+
22
+          {% block content %}
23
+            <div id='edit' class='main_block'>
24
+              <text>Kit:</text>
25
+              <div class='input_block'>
26
+                <label>Nom (unique)</label>
27
+                <input
28
+                      id='name'
29
+                      type='text'
30
+                      onchange='javascript:update_kit(this, {{ kit.id }}, "text");'
31
+                      maxlength='20'
32
+                      title='Nom unique (max. 20)'
33
+                      placeholder='Nom unique (max. 20)'
34
+                      value='{{ kit.name }}' />
35
+              </div>
36
+              <div class='input_block'>
37
+                <label>Designation</label>
38
+                <input
39
+                      id='designation'
40
+                      type='text'
41
+                      onchange='javascript:update_kit(this, {{ kit.id }}, "text");'
42
+                      title='Adresse'
43
+                      placeholder='Adresse'
44
+                      value='{{ kit.designation }}' />
45
+              </div>
46
+            </div>
47
+          {% endblock %}

+ 70
- 0
templates/kits.html View File

@@ -0,0 +1,70 @@
1
+{% extends "index.html" %}
2
+{% block bodyheader %}
3
+  <body onload="javascript:update_kits();">
4
+{% endblock %}
5
+{% block title %}Liste des fournisseurs{% endblock %}
6
+        {% block top_menu %}
7
+        <span class='top_menu_item_selected' onclick='javascript:document.location="/kits";'>Gérer les kits</span>
8
+        {% endblock %}
9
+        
10
+          {% block left_menu %}
11
+          <div class='left_menu_item' onclick='javascript:document.location="/";'>
12
+            Accueil
13
+          </div>
14
+          <div class='left_menu_item' onclick='javascript:document.location="/componants";'>
15
+            Composants
16
+          </div>
17
+          <div class='left_menu_item_selected' onclick='javascript:document.location="/kits";'>
18
+            Kits
19
+          </div>
20
+          <div class='left_menu_item' onclick='javascript:document.location="/providers";'>
21
+            Fournisseurs
22
+          </div>
23
+          {% endblock %}
24
+
25
+          {% block content %}
26
+          <!-- ----------------------------------------------------
27
+          Recherche
28
+          -----------------------------------------------------  -->
29
+           <div id='search' class='main_block'>
30
+            <text>Recherche:</text>
31
+            <div class='input_block'>
32
+              <label>Nom (unique)</label>
33
+              <input
34
+                    id='name'
35
+                    type='text'
36
+                    onkeyup='javascript:search_kits_by_name(this, "text");'
37
+                    title='Nom unique'
38
+                    placeholder='Nom unique'
39
+                    value='{{ name }}' />
40
+            </div>
41
+            <div class='input_block'>
42
+              <label>Désignation</label>
43
+              <input
44
+                    id='designation'
45
+                    type='text'
46
+                    onkeyup='javascript:search_kits_by_designation(this, "text");'
47
+                    title='Désignation'
48
+                    placeholder='Désignation'
49
+                    value='{{ designation }}' />
50
+            </div>
51
+            <div class='button_block'>
52
+              <input
53
+                    type='image'
54
+                    src='/static/images/search.png'
55
+                    title='Rechercher'
56
+                    onclick='javascript:update_kits("name");'/>
57
+              <input
58
+                    type='image'
59
+                    src='/static/images/save.png'
60
+                    title='Enregistrer'
61
+                    onclick='javascript:new_kit();'/>
62
+            </div>
63
+          </div>
64
+          <!-- ----------------------------------------------------
65
+          Resultat
66
+          -----------------------------------------------------  -->
67
+          <div id='result_container' class='result_container'>
68
+          
69
+          </div>
70
+          {% endblock %}

+ 50
- 0
templates/login.html View File

@@ -0,0 +1,50 @@
1
+{% extends "index.html" %}
2
+{% block title %}Éditer un fournisseur{% endblock %}
3
+        {% block top_menu %}
4
+        <span class='top_menu_item_selected'>Authentification</span>
5
+        {% endblock %}
6
+          {% block left_menu %}
7
+          <div class='left_menu_item_selected' onclick='javascript:document.location="/";'>
8
+            Accueil
9
+          </div>
10
+          <div class='left_menu_item' onclick='javascript:document.location="/componants";'>
11
+            Composants
12
+          </div>
13
+          <div class='left_menu_item' onclick='javascript:document.location="/kits";'>
14
+            Kits
15
+          </div>
16
+          <div class='left_menu_item' onclick='javascript:document.location="/providers";'>
17
+            Fournisseurs
18
+          </div>
19
+          {% endblock %}
20
+
21
+          {% block content %}
22
+            <div id='edit' class='main_block'>
23
+              <text>Authentification:<text>
24
+              <div class='input_block'>
25
+                <label>Login</label>
26
+                <input
27
+                      id='login'
28
+                      type='text'
29
+                      title='Login'
30
+                      placeholder='Login'
31
+                      value='' />
32
+              </div>
33
+              <div class='input_block'>
34
+                <label>Mot de passe</label>
35
+                <input
36
+                      id='password'
37
+                      type='password'
38
+                      title='Mot de passe'
39
+                      placeholder='Mot de passe'
40
+                      value='' />
41
+              </div>
42
+              <div class='button_block'>
43
+                <input
44
+                      type='image'
45
+                      src='/static/images/login.png'
46
+                      title='Se connecter'
47
+                      onclick='javascript:login();'/>
48
+              </div>
49
+            </div>
50
+          {% endblock %}

+ 1
- 1
templates/provider.html View File

@@ -21,7 +21,7 @@
21 21
 
22 22
           {% block content %}
23 23
             <div id='edit' class='main_block'>
24
-              <text>Composant:</text>
24
+              <text>Fournisseur:</text>
25 25
               <div class='input_block'>
26 26
                 <label>Nom (unique)</label>
27 27
                 <input

+ 40
- 0
templates/result_kits.html View File

@@ -0,0 +1,40 @@
1
+            <div class='main_block'>
2
+              <text>Résultat: 
3
+              {% set ss='' %}
4
+              {% if row_count > 1 %}
5
+              {%    set ss='s' %}
6
+              {% endif %}
7
+              {{ row_count }} objet{{ ss }} selectionné{{ ss }}
8
+              </text>
9
+              <div class='row_block border_bottom'>
10
+                <label style='width: 209px;' onclick='javascript:update_kits_by_name("{{ order }}");'>Nom</label>
11
+                <label class='border_left' style='width: 700px;' onclick='javascript:update_kits_by_designation("{{ order }}");'>Désignation</label>
12
+                <label class='border_left' style='width: 89px;' style='cursor: default;'>Action</label>
13
+              </div>
14
+              {% set row_class = cycler('odd', 'even') %}
15
+              {% for kit in kits %}
16
+              <div class='row_block {{ row_class.next() }}'>
17
+                <text style='width: 199px;'>{{ kit.name }}</text>
18
+                <text class='border_left' style='width: 690px;'>{{ kit.designation }}</text>
19
+                <div class='action_bar_block border_left' style='width: 89px;'>
20
+                  <input
21
+                    type='image'
22
+                    src='/static/images/edit.png'
23
+                    title='Éditer'
24
+                    onclick='javascript:document.location="/kits/{{ kit.id }}"'/>
25
+                  <input
26
+                    type='image'
27
+                    src='/static/images/trash.png'
28
+                    title='Supprimer'
29
+                    onclick='javascript:confirm_kit_delete()?document.location="/kits/delete/{{ kit.id }}":false;'/>
30
+                </div>
31
+              </div>
32
+              {% endfor %}
33
+              <div class='nav_page_block border_top'>
34
+                <text>
35
+                <span class='prev_page' onclick='javascript:k_previous_page({{ prevhop }});'>&lt;</span>
36
+                <span class='page_num'>{{ page }} / {{ page_count }}</span>
37
+                <span class='next_page' onclick='javascript:k_next_page({{ nexthop }})'>&gt;</span>
38
+              </text>
39
+              </div>
40
+            </div>

+ 0
- 56
templates/users.html View File

@@ -1,56 +0,0 @@
1
-<!DOCTYPE html>
2
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr" dir="ltr">
3
-<head>
4
-  <meta name="generator" content="HTML Tidy for HTML5 for Linux version 5.5.21" />
5
-  <title>Stock Tetalab - {% block title %}Accueil{% endblock %}</title>
6
-  <meta name="viewport" content="initial-scale=1.0" />
7
-  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
8
-  <link rel="stylesheet" type="text/css" href="/static/style/style.css" />
9
-  <script type="text/javascript" src="/static/scripts/tetalab.js"></script>
10
-</head>
11
-<body>
12
-  <div class='main_wrapper'>
13
-    <div class='center'>
14
-      <div class='banner' title='Stock Tetalab'>
15
-        Stock Tetalab
16
-      </div>
17
-      <div class='top_menu'>
18
-        {% block top_menu %} <span class='top_menu_item_selected' onclick='javascript:document.location="./";'>Accueil</span> {% endblock %}
19
-      </div>
20
-      <div class='content_wrapper'>
21
-        <div class='left_menu'>
22
-          {% block left_menu %}
23
-          <div class='left_menu_item_selected' onclick='javascript:document.location="/";'>
24
-            Accueil
25
-          </div>
26
-          <div class='left_menu_item' onclick='javascript:document.location="/componants";'>
27
-            Composants
28
-          </div>
29
-          <div class='left_menu_item' onclick='javascript:document.location="/kits";'>
30
-            Kits
31
-          </div>
32
-          <div class='left_menu_item' onclick='javascript:document.location="/providers";'>
33
-            Fournisseurs
34
-          </div>{% endblock %}
35
-        </div>
36
-        <div class='content'>
37
-          {% block content %}
38
-          <h1>Gestion du stock</h1>
39
-          <p>Ceci est l'outil de gestion de stock du <a href='https://www.tetalab.org'>Tetalab</a>.</p>
40
-          <p>Cet outil vous permet:
41
-            <ul>
42
-              <li>De gérer la liste des composants électroniques en possession du Tetalab</li>
43
-              <li>De gérer la liste des fournisseurs de composants</li>
44
-              <li>De gérer la liste des kits de montage</li>
45
-            </ul>
46
-          </p>
47
-          {% endblock %}
48
-        </div>
49
-      </div>
50
-      <div class='footer'>
51
-        Tetalab - Le Hacker Space Toulousaing' Putaing' Cong' -
52
-      </div>
53
-    </div>
54
-  </div>
55
-</body>
56
-</html>

+ 411
- 177
tetastock.py View File

@@ -1,6 +1,10 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8
3 3
 
4
+import os
5
+import datetime
6
+import bcrypt
7
+import binascii
4 8
 import math
5 9
 import psycopg2
6 10
 from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
@@ -49,111 +53,211 @@ class Stock_providers(db.Model):
49 53
 class Stock_kits(db.Model):
50 54
   id = db.Column(db.Integer, primary_key=True)
51 55
   name = db.Column(db.Text, nullable=False)
52
-  description = db.Column(db.Text, nullable=False)
56
+  designation = db.Column(db.Text, nullable=False)
53 57
 
54 58
 class Stock_kit_compositions(db.Model):
55 59
   id = db.Column(db.Integer, primary_key=True)
56 60
   kit_id = db.Column(db.Integer, db.ForeignKey('Stock_kits.id'), nullable=False)
57
-  component_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False)
58
-  component_quantity = db.Column(db.Integer, nullable=False)
61
+  componant_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False)
62
+  quantity = db.Column(db.Integer, nullable=False)
63
+  price = db.Column(db.Integer, nullable=False)
64
+
65
+class Stock_orders(db.Model):
66
+  id = db.Column(db.Integer, primary_key=True)
67
+  componant_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'))
68
+  componant_quantity = db.Column(db.Integer, nullable=False)
69
+  date = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
70
+  injected = db.Column(db.Boolean, nullable=False, default=False)
71
+
72
+def sync_cookies(response, session):
73
+  """ Sync cookies from session """
74
+  for key in session:
75
+    response.set_cookie(key, value=str(session[key]))
76
+    if key != u'session':
77
+      print '[c]', key, session[key]
78
+
79
+def sync_session(request, session, offset_reset):
80
+  """ Sync session with cookies"""
81
+  for key in request.cookies:
82
+    try:
83
+      old = str(session[key])
84
+      session[key] = int(str(request.cookies[key].encode('utf8')))
85
+    except ValueError:
86
+      # Value is not an int, will be treated as string
87
+      session[key] = str(request.cookies[key].encode('utf8'))
88
+    except KeyError:
89
+      # Key does not exist in session
90
+      try:
91
+        session[key] = int(str(request.cookies[key].encode('utf8')))
92
+      except ValueError:
93
+        # Value is not an int, will be treated as string
94
+        session[key] = str(request.cookies[key].encode('utf8'))
95
+    if key in offset_reset and len(str(session[key])) > 0 and old != str(session[key]):
96
+      session['c_offset'] = 0
97
+      session['p_offset'] = 0
98
+      session['k_offset'] = 0
99
+    if key != u'session':
100
+      print '[s]', key, request.cookies[key]
101
+
102
+def check_user(request, session):
103
+  """ Check user credentials """
104
+  if session['token'] and request.cookies['token']:
105
+    if len(session['token']) > 0 and len(request.cookies['token']) > 0:
106
+      if session['token'] == request.cookies['token']:
107
+        return True
108
+      return False
109
+  if 'login' not in request.cookies or 'password' not in request.cookies:
110
+    return False
111
+  if request.cookies['login'] and request.cookies['password']:
112
+    if request.cookies['login'] > 0 and request.cookies['password'] > 0:
113
+      hashed = Stock_users.query.filter_by(mail=request.cookies['login']).with_entities(Stock_users.password).first()
114
+      if hashed is None:
115
+        # User is unknown
116
+        return False
117
+      password = request.cookies['password'].encode('utf8')
118
+      hashed = hashed[0].encode('utf8')
119
+      if bcrypt.checkpw(password, hashed):
120
+        session['password'] = ''
121
+        session['login'] = ''
122
+        session['token'] = binascii.hexlify(os.urandom(42))
123
+        return True
124
+    # Password mismatch
125
+    return False
126
+  
59 127
 
60 128
 def resume_session(func):
61 129
   @wraps(func)
62 130
   def check(*args, **kwargs):
63
-    # default
131
+    # Motherfuckin' bunch of defaults values
132
+    empty=u''
64 133
     limit = 10
65 134
     offset = 0
66 135
     page = 1
67 136
     nexthop = offset + limit
68 137
     prevhop = offset
69
-    order = 'asc'
138
+    order = u'asc'
70 139
     order_refresh = 0
71
-    c_empty = ''
72
-    c_sort = 'reference'
140
+    c_sort = u'reference'
73 141
     c_provider = 0
74 142
     c_count = 0
75
-    p_empty = ''
76
-    p_sort = 'name'
77
-    offset_reset = ['c_reference', 'c_designation', 'c_place', 'c_provider']
78
-    if not 'session' in session:
79
-      session['session'] = ''
80
-    if not 'c_limit' in session:
81
-      session['c_limit'] = limit
82
-    if not 'c_offest' in session:
83
-      session['c_offset'] = offset
84
-    if not 'c_sort' in session:
143
+    p_sort = u'name'
144
+    p_count = 0
145
+    k_sort = u'name'
146
+    k_count = 0
147
+    offset_reset = [u'c_reference', u'c_designation', u'c_place',
148
+                    u'c_provider', u'p_name', u'p_address', u'p_mail', u'p_url',
149
+                    u'k_name', u'k_designation']
150
+    if not u'token' in session:
151
+      session[u'token'] = empty
152
+    if not u'password' in session:
153
+      session[u'password'] = empty
154
+    if not u'login' in session:
155
+      session[u'login'] = empty
156
+    if not u'session' in session:
157
+      session[u'session'] = empty
158
+    if not u'c_limit' in session:
159
+      session[u'c_limit'] = limit
160
+    if not u'c_offest' in session:
161
+      session[u'c_offset'] = offset
162
+    if not u'c_sort' in session:
85 163
       session['c_sort'] = c_sort
86
-    if not 'c_order' in session:
87
-      session['c_order'] = order
88
-    if not 'c_order_refresh' in session:
89
-      session['c_order_refresh'] = order_refresh
90
-    if not 'c_page' in session:
91
-      session['c_page'] = page
92
-    if not 'c_nexthop' in session:
93
-      session['c_nexthop'] = nexthop
94
-    if not 'c_prevhop' in session:
164
+    if not u'c_order' in session:
165
+      session[u'c_order'] = order
166
+    if not u'c_order_refresh' in session:
167
+      session[u'c_order_refresh'] = order_refresh
168
+    if not u'c_page' in session:
169
+      session[u'c_page'] = page
170
+    if not u'c_nexthop' in session:
171
+      session[u'c_nexthop'] = nexthop
172
+    if not u'c_prevhop' in session:
95 173
       session['c_prevhop'] = prevhop
96
-    if not 'c_reference' in session:
97
-      session['c_reference'] = c_empty
98
-    if not 'c_designation' in session:
99
-      session['c_designation'] = c_empty
100
-    if not 'c_place' in session:
101
-      session['c_place'] = c_empty
102
-    if not 'c_provider' in session:
103
-      session['c_provider'] = c_provider
104
-    if not 'c_count' in session:
105
-      session['c_count'] = c_count
106
-    if not 'p_sort' in session:
107
-      session['p_sort'] = p_sort
108
-    if not 'p_order' in session:
109
-      session['p_order'] = order
110
-    if not 'p_order_refresh' in session:
111
-      session['p_order_refresh'] = order_refresh
112
-    if not 'p_page' in session:
113
-      session['p_page'] = page
114
-    if not 'p_nexthop' in session:
115
-      session['p_nexthop'] = nexthop
116
-    if not 'p_prevhop' in session:
117
-      session['p_prevhop'] = prevhop
118
-    if not 'p_offset' in session:
119
-      session['p_offset'] = offset
120
-    if not 'p_limit' in session:
121
-      session['p_limit'] = limit
122
-    if not 'p_name' in session:
123
-      session['p_name'] = p_empty
124
-    if not 'p_address' in session:
125
-      session['p_address'] = p_empty
126
-    if not 'p_mail' in session:
127
-      session['p_mail'] = p_empty
128
-    if not 'p_url' in session:
129
-      session['p_url'] = p_empty
130
-    if not 'p_comment' in session:
131
-      session['p_comment'] = p_empty
174
+    if not u'c_reference' in session:
175
+      session[u'c_reference'] = empty
176
+    if not u'c_designation' in session:
177
+      session[u'c_designation'] = empty
178
+    if not u'c_place' in session:
179
+      session[u'c_place'] = empty
180
+    if not u'c_provider' in session:
181
+      session[u'c_provider'] = c_provider
182
+    if not u'c_count' in session:
183
+      session[u'c_count'] = c_count
184
+    if not u'p_sort' in session:
185
+      session[u'p_sort'] = p_sort
186
+    if not u'p_order' in session:
187
+      session[u'p_order'] = order
188
+    if not u'p_order_refresh' in session:
189
+      session[u'p_order_refresh'] = order_refresh
190
+    if not u'p_page' in session:
191
+      session[u'p_page'] = page
192
+    if not u'p_nexthop' in session:
193
+      session[u'p_nexthop'] = nexthop
194
+    if not u'p_prevhop' in session:
195
+      session[u'p_prevhop'] = prevhop
196
+    if not u'p_offset' in session:
197
+      session[u'p_offset'] = offset
198
+    if not u'p_limit' in session:
199
+      session[u'p_limit'] = limit
200
+    if not u'p_name' in session:
201
+      session[u'p_name'] = empty
202
+    if not u'p_address' in session:
203
+      session[u'p_address'] = empty
204
+    if not u'p_mail' in session:
205
+      session[u'p_mail'] = empty
206
+    if not u'p_url' in session:
207
+      session[u'p_url'] = empty
208
+    if not u'p_comment' in session:
209
+      session[u'p_comment'] = empty
210
+    if not u'p_count' in session:
211
+      session['p_count'] = p_count
212
+    if not u'k_sort' in session:
213
+      session[u'k_sort'] = k_sort
214
+    if not u'k_order' in session:
215
+      session[u'k_order'] = order
216
+    if not u'k_order_refresh' in session:
217
+      session[u'k_order_refresh'] = order_refresh
218
+    if not u'k_page' in session:
219
+      session[u'k_page'] = page
220
+    if not u'k_nexthop' in session:
221
+      session[u'k_nexthop'] = nexthop
222
+    if not u'k_prevhop' in session:
223
+      session[u'k_prevhop'] = prevhop
224
+    if not u'k_offset' in session:
225
+      session[u'k_offset'] = offset
226
+    if not u'k_limit' in session:
227
+      session[u'k_limit'] = limit
228
+    if not u'k_name' in session:
229
+      session[u'k_name'] = empty
230
+    if not u'k_address' in session:
231
+      session[u'k_address'] = empty
232
+    if not u'k_mail' in session:
233
+      session[u'k_mail'] = empty
234
+    if not u'k_url' in session:
235
+      session[u'k_url'] = empty
236
+    if not u'k_designation' in session:
237
+      session[u'k_designation'] = empty
238
+    if not u'k_count' in session:
239
+      session[u'k_count'] = k_count
132 240
       
133 241
     # Cookies/session sync
134
-    for key in request.cookies:
135
-      old = str(session[key])
136
-      try:
137
-        session[key] = int(str(request.cookies[key]))
138
-      except ValueError:
139
-        # Value is not an int, will be treated as string
140
-        session[key] = str(request.cookies[key])
141
-      if key in offset_reset and len(str(session[key])) > 0 and old != str(session[key]):
142
-        session['c_offset'] = 0
143
-
144
-      if key != 'session':
145
-        print '[s]', key, request.cookies[key]
146
-
242
+    sync_session(request, session, offset_reset)
147 243
 
148 244
     # Switch sort order
149
-    if session['c_order_refresh'] == 1:
150
-      refresh = {'desc': 'asc', 'asc': 'desc'}
151
-      session['c_order'] = refresh[session['c_order']]
152
-      session['c_order_refresh'] = 0
153
-    if session['p_order_refresh'] == 1:
154
-      refresh = {'desc': 'asc', 'asc': 'desc'}
155
-      session['p_order'] = refresh[session['p_order']]
156
-      session['p_order_refresh'] = 0 
245
+    refresh = {u'desc': u'asc', u'asc': u'desc'}
246
+    if session[u'c_order_refresh'] == 1:
247
+      session[u'c_order'] = refresh[session[u'c_order']]
248
+      session[u'c_order_refresh'] = 0
249
+    if session[u'p_order_refresh'] == 1:
250
+      session[u'p_order'] = refresh[session[u'p_order']]
251
+      session[u'p_order_refresh'] = 0
252
+    if session[u'k_order_refresh'] == 1:
253
+      session[u'k_order'] = refresh[session[u'k_order']]
254
+      session[u'k_order_refresh'] = 0
255
+
256
+    # Check for valid session
257
+    if not check_user(request, session):
258
+      # User is not logged in, send him back to login page
259
+      return render_template('login.html')
260
+    # Everything's fine
157 261
     return func(*args, **kwargs)
158 262
   return check
159 263
 
@@ -164,9 +268,12 @@ def resume_session(func):
164 268
 def page_not_found(e):
165 269
     return render_template('error.html'), 404
166 270
 
167
-@app.route("/")
271
+@app.route("/", methods=['GET', 'POST'])
272
+@resume_session
168 273
 def authenticate():
169
-  return render_template('index.html')
274
+  response = app.make_response(render_template('index.html'))
275
+  sync_cookies(response, session)
276
+  return response
170 277
 
171 278
 
172 279
 ########################################################################
@@ -180,10 +287,10 @@ def componants():
180 287
   providers = Stock_providers.query.order_by(Stock_providers.id).all()
181 288
   return render_template('componants.html',
182 289
                             providers=providers,
183
-                            reference=session['c_reference'],
184
-                            designation=session['c_designation'],
185
-                            place=session['c_place'],
186
-                            provider_id=session['c_provider'])
290
+                            reference=session[u'c_reference'].decode('utf8'),
291
+                            designation=session[u'c_designation'].decode('utf8'),
292
+                            place=session[u'c_place'].decode('utf8'),
293
+                            provider_id=session[u'c_provider'])
187 294
 
188 295
 @app.route('/componants/<componant_id>')
189 296
 @resume_session
@@ -229,26 +336,32 @@ def delete_componant(componant_id):
229 336
   except ValueError as e:
230 337
     return render_template('error.html'), 404
231 338
   except Exception as e:
232
-    print "[+] Error at delete_componant:\n------------------------------\n%s------------------------------" % e.message
339
+    print "[+] Error at delete_componant:"
340
+    print "------------------------------"
341
+    print "%s" % e.message
342
+    print "------------------------------"
233 343
   return componants()
234 344
 
235 345
 @app.route('/componants/new', methods=['POST'])
236 346
 @resume_session
237 347
 def new_componant():
238 348
   """ Add componant """
239
-  componant = Stock_componants(reference=session['c_reference'],
240
-                               designation=session['c_designation'],
349
+  componant = Stock_componants(reference=session[u'c_reference'].decode('utf8'),
350
+                               designation=session[u'c_designation'].decode('utf8'),
241 351
                                last_price=0,
242 352
                                mean_price=0,
243 353
                                quantity=0,
244 354
                                min_quantity=0,
245
-                               place=session['c_place'],
246
-                               provider_id=session['c_provider'])
355
+                               place=session[u'c_place'].decode('utf8'),
356
+                               provider_id=session[u'c_provider'])
247 357
   try:
248 358
     db.session.add(componant)
249 359
     commit =  db.session.commit()
250 360
   except Exception as e:
251
-    print "[+] Error at new_componant:\n------------------------------\n%s------------------------------" % e.message
361
+    print "[+] Error at new_componant:"
362
+    print "------------------------------"
363
+    print "%s" % e.message
364
+    print "------------------------------"
252 365
     return 'KO'
253 366
   if commit != None:
254 367
     return 'KO'
@@ -272,56 +385,53 @@ def out_componants():
272 385
 def update_componants():
273 386
   """ Display componants list """
274 387
   # search by reference
275
-  like = '%s%s%s' % ('%', str(session['c_reference']), '%')
388
+  like = '%s%s%s' % ('%', str(session[u'c_reference']), '%')
276 389
   componants = Stock_componants.query.filter(Stock_componants.reference.like(like))
277 390
   # search by designation
278
-  like = '%s%s%s' % ('%', str(session['c_designation']), '%')
391
+  like = '%s%s%s' % ('%', str(session[u'c_designation']), '%')
279 392
   componants = componants.filter(Stock_componants.designation.like(like))
280 393
   # search by place
281
-  like = '%s%s%s' % ('%', str(session['c_place']),'%')
394
+  like = '%s%s%s' % ('%', str(session[u'c_place']),'%')
282 395
   componants = componants.filter(Stock_componants.place.like(like))
283 396
   # search by provider
284 397
   if session['c_provider'] > 1:
285
-    componants = componants.filter_by(provider_id=session['c_provider'])
398
+    componants = componants.filter_by(provider_id=session[u'c_provider'])
286 399
   # Pages calculation
287
-  session['c_count'] = componants.count()
288
-  session['c_pagecount'] = int(math.ceil(session['c_count'] / float(session['c_limit'])))
289
-  session['c_page'] = int(math.ceil(float(float(session['c_offset']) + 1) / float(session['c_limit'])))
290
-  if session['c_page'] > session['c_pagecount']:
291
-    session['c_page'] = session['c_pagecount']
292
-    session['c_offset'] = 0
293
-  session['c_nexthop'] = session['c_offset'] + session['c_limit']
294
-  if session['c_nexthop'] > session['c_count'] - 1:
295
-    session['c_nexthop'] = int(session['c_offset'])
296
-  session['c_prevhop'] =  int(session['c_offset'])  - session['c_limit']
297
-  if session['c_prevhop'] < 0:
298
-    session['c_prevhop']  = 0
400
+  session[u'c_count'] = componants.count()
401
+  session[u'c_pagecount'] = int(math.ceil(session[u'c_count'] / float(session[u'c_limit'])))
402
+  session[u'c_page'] = int(math.ceil(float(float(session[u'c_offset']) + 1) / float(session[u'c_limit'])))
403
+  if session[u'c_page'] > session[u'c_pagecount']:
404
+    session[u'c_page'] = session[u'c_pagecount']
405
+    session[u'c_offset'] = 0
406
+  session[u'c_nexthop'] = session[u'c_offset'] + session[u'c_limit']
407
+  if session[u'c_nexthop'] > session[u'c_count'] - 1:
408
+    session[u'c_nexthop'] = int(session[u'c_offset'])
409
+  session[u'c_prevhop'] =  int(session[u'c_offset'])  - session[u'c_limit']
410
+  if session[u'c_prevhop'] < 0:
411
+    session[u'c_prevhop']  = 0
299 412
   # Sorting
300
-  sort = getattr(Stock_componants, session['c_sort'])
301
-  if session['c_order'] == 'desc':
302
-    sort = getattr(Stock_componants, session['c_sort']).desc()
413
+  sort = getattr(Stock_componants, session[u'c_sort'])
414
+  if session[u'c_order'] == u'desc':
415
+    sort = getattr(Stock_componants, session[u'c_sort']).desc()
303 416
   componants =   componants.order_by(sort)
304 417
   # Applying offset
305
-  componants = componants.offset(session['c_offset'])
418
+  componants = componants.offset(session[u'c_offset'])
306 419
   # Applying limit
307
-  componants = componants.limit(session['c_limit'])
420
+  componants = componants.limit(session[u'c_limit'])
308 421
   # Get result
309 422
   componants = componants.all()
310 423
   
311 424
   response = app.make_response(render_template('result_componants.html',
312 425
                             componants=componants,
313
-                            offset=session['c_offset'] ,
314
-                            nexthop=session['c_nexthop'],
315
-                            prevhop=session['c_prevhop'],
316
-                            page_count=session['c_pagecount'],
317
-                            page=session['c_page'],
318
-                            sort=session['c_sort'],
319
-                            order=session['c_order'],
320
-                            row_count=session['c_count']))
321
-  for key in session:
322
-    response.set_cookie(key, value=str(session[key]))
323
-    if key != 'session':
324
-      print '[c]', key, session[key]
426
+                            offset=session[u'c_offset'] ,
427
+                            nexthop=session[u'c_nexthop'],
428
+                            prevhop=session[u'c_prevhop'],
429
+                            page_count=session[u'c_pagecount'],
430
+                            page=session[u'c_page'],
431
+                            sort=session[u'c_sort'].decode('utf8'),
432
+                            order=session[u'c_order'].decode('utf8'),
433
+                            row_count=session[u'c_count']))
434
+  sync_cookies(response, session)
325 435
   return response
326 436
 
327 437
 ########################################################################
@@ -331,11 +441,11 @@ def update_componants():
331 441
 @resume_session
332 442
 def providers():
333 443
   return render_template('providers.html',
334
-                            name=session['p_name'],
335
-                            address=session['p_address'],
336
-                            mail=session['p_mail'],
337
-                            url=session['p_url'],
338
-                            comment=session['p_comment'])
444
+                            name=session[u'p_name'].decode('utf8'),
445
+                            address=session[u'p_address'].decode('utf8'),
446
+                            mail=session[u'p_mail'].decode('utf8'),
447
+                            url=session[u'p_url'].decode('utf8'),
448
+                            comment=session[u'p_comment'].decode('utf8'))
339 449
 
340 450
 @app.route('/providers/<provider_id>')
341 451
 @resume_session
@@ -372,17 +482,19 @@ def update_provider(provider_id):
372 482
 @resume_session
373 483
 def new_provider():
374 484
   """ Add provider """
375
-  provider = Stock_providers(name=session['p_name'],
376
-                            address=session['p_address'],
377
-                            mail=session['p_mail'],
378
-                            url=session['p_url'],
379
-                            comment=session['p_comment'])
485
+  provider = Stock_providers(name=session[u'p_name'].decode('utf8'),
486
+                            address=session[u'p_address'].decode('utf8'),
487
+                            mail=session[u'p_mail'].decode('utf8'),
488
+                            url=session[u'p_url'].decode('utf8'),
489
+                            comment=session[u'p_comment'].decode('utf8'))
380 490
   try:
381 491
     db.session.add(provider)
382 492
     commit =  db.session.commit()
383 493
   except Exception as e:
384
-    print 'Error at new_provider():', e
385
-    print 'Commit = ', commit
494
+    print "[+] Error at new_provider:"
495
+    print "------------------------------"
496
+    print "%s" % e.message
497
+    print "------------------------------"
386 498
     return 'KO'
387 499
   if commit != None:
388 500
     return 'KO'
@@ -399,7 +511,10 @@ def delete_provider(provider_id):
399 511
   except ValueError as e:
400 512
     return render_template('error.html'), 404
401 513
   except Exception as e:
402
-    print "[+] Error at delete_provider:\n-----------------------------\n%s-----------------------------" % e.message
514
+    print "[+] Error at delete_provider:"
515
+    print "------------------------------"
516
+    print "%s" % e.message
517
+    print "------------------------------"
403 518
   return providers()
404 519
 
405 520
 @app.route('/providers/update', methods=['POST'])
@@ -407,69 +522,188 @@ def delete_provider(provider_id):
407 522
 def search_providers():
408 523
   """ Display componants list """
409 524
   # search by reference
410
-  like = '%s%s%s' % ('%', str(session['p_name']), '%')
525
+  like = '%s%s%s' % ('%', str(session[u'p_name']), '%')
411 526
   providers = Stock_providers.query.filter(Stock_providers.name.like(like))
412
-  # search by designation
413
-  like = '%s%s%s' % ('%', str(session['p_address']), '%')
527
+  # search by address
528
+  like = '%s%s%s' % ('%', str(session[u'p_address']), '%')
414 529
   providers = providers.filter(Stock_providers.address.like(like))
415 530
   # search by place
416
-  like = '%s%s%s' % ('%', str(session['p_mail']),'%')
531
+  like = '%s%s%s' % ('%', str(session[u'p_mail']),'%')
417 532
   providers = providers.filter(Stock_providers.mail.like(like))
418 533
   # search by place
419
-  like = '%s%s%s' % ('%', str(session['p_url']),'%')
534
+  like = '%s%s%s' % ('%', str(session[u'p_url']),'%')
420 535
   providers = providers.filter(Stock_providers.url.like(like))
421 536
   # search by place
422
-  like = '%s%s%s' % ('%', str(session['p_comment']),'%')
537
+  like = '%s%s%s' % ('%', str(session[u'p_comment']),'%')
423 538
   providers = providers.filter(Stock_providers.comment.like(like))
424 539
   # Don't take 'all' and 'none' entry
425 540
   providers = providers.filter(Stock_providers.id > 2)
426 541
 
427 542
   # Pages calculation
428
-  session['p_count'] = providers.count()
429
-  session['p_pagecount'] = int(math.ceil(session['p_count'] / float(session['p_limit'])))
430
-  session['p_page'] = int(math.ceil(float(float(session['p_offset']) + 1) / float(session['p_limit'])))
431
-  if session['p_page'] > session['p_pagecount']:
432
-    session['p_page'] = session['p_pagecount']
433
-    session['p_offset'] = 0
434
-  session['p_nexthop'] = session['p_offset'] + session['p_limit']
435
-  if session['p_nexthop'] > session['p_count'] - 1:
436
-    session['p_nexthop'] = int(session['p_offset'])
437
-  session['p_prevhop'] =  int(session['p_offset']) - session['p_limit']
438
-  if session['p_prevhop'] < 0:
439
-    session['p_prevhop']  = 0
543
+  session[u'p_count'] = providers.count()
544
+  session[u'p_pagecount'] = int(math.ceil(session[u'p_count'] / float(session[u'p_limit'])))
545
+  session[u'p_page'] = int(math.ceil(float(float(session[u'p_offset']) + 1) / float(session[u'p_limit'])))
546
+  if session[u'p_page'] > session[u'p_pagecount']:
547
+    session[u'p_page'] = session[u'p_pagecount']
548
+    session[u'p_offset'] = 0
549
+  session[u'p_nexthop'] = session[u'p_offset'] + session[u'p_limit']
550
+  if session[u'p_nexthop'] > session[u'p_count'] - 1:
551
+    session[u'p_nexthop'] = int(session[u'p_offset'])
552
+  session[u'p_prevhop'] =  int(session[u'p_offset']) - session[u'p_limit']
553
+  if session[u'p_prevhop'] < 0:
554
+    session[u'p_prevhop']  = 0
440 555
   # Sorting
441
-  sort = getattr(Stock_providers, session['p_sort'])
442
-  if session['p_order'] == 'desc':
443
-    sort = getattr(Stock_providers, session['p_sort']).desc()
556
+  sort = getattr(Stock_providers, session[u'p_sort'])
557
+  if session[u'p_order'] == u'desc':
558
+    sort = getattr(Stock_providers, session[u'p_sort']).desc()
444 559
   providers =   providers.order_by(sort)
445 560
   # Applying offset
446
-  providers = providers.offset(session['p_offset'])
561
+  providers = providers.offset(session[u'p_offset'])
447 562
   # Applying limit
448
-  providers = providers.limit(session['p_limit'])
563
+  providers = providers.limit(session[u'p_limit'])
449 564
   # Get result
450 565
   providers = providers.all()
451 566
   response = app.make_response(render_template('result_providers.html',
452 567
                             providers=providers,
453
-                            offset=session['p_offset'] ,
454
-                            nexthop=session['p_nexthop'],
455
-                            prevhop=session['p_prevhop'],
456
-                            page_count=session['p_pagecount'],
457
-                            page=session['p_page'],
458
-                            sort=session['p_sort'],
459
-                            order=session['p_order'],
460
-                            row_count=session['p_count']))
461
-  for key in session:
462
-    response.set_cookie(key, value=str(session[key]))
463
-    if key != 'session':
464
-      print '[c]', key, session[key]
568
+                            offset=session[u'p_offset'] ,
569
+                            nexthop=session[u'p_nexthop'],
570
+                            prevhop=session[u'p_prevhop'],
571
+                            page_count=session[u'p_pagecount'],
572
+                            page=session[u'p_page'],
573
+                            sort=session[u'p_sort'].decode('utf8'),
574
+                            order=session[u'p_order'].decode('utf8'),
575
+                            row_count=session[u'p_count']))
576
+  sync_cookies(response, session)
465 577
   return response
466 578
 
467 579
 
468 580
 ########################################################################
469 581
 # Kits
470 582
 ########################################################################
583
+@app.route('/kits', methods=['GET', 'POST'])
584
+@resume_session
585
+def kits():
586
+  return render_template('kits.html',
587
+                            name=session[u'k_name'].decode('utf8'),
588
+                            designation=session[u'k_designation'].decode('utf8'))
471 589
 
472
-  
590
+@app.route('/kits/<kit_id>')
591
+@resume_session
592
+def get_kit(kit_id):
593
+  """ Edit kit """
594
+  try:
595
+    kit_id = int(kit_id)
596
+  except ValueError as e:
597
+    return render_template('error.html'), 404
598
+  kit = Stock_kits.query.filter_by(id=kit_id).first()
599
+  if kit:
600
+    return render_template('kit.html', kit=kit)
601
+  return render_template('error.html'), 404
602
+
603
+@app.route('/kits/update/<kit_id>', methods=['POST'])
604
+@resume_session
605
+def update_kit(kit_id):
606
+  """ Update kit field"""
607
+  field = request.form['field']
608
+  value = request.form['value']
609
+  if field and value:
610
+    try:
611
+      kit = Stock_kits.query.filter_by(id=kit_id).first()
612
+      setattr(kit, field, value)
613
+      commit =  db.session.commit()
614
+      if commit == None:
615
+        return 'OK'
616
+    except Exception as e:
617
+      pass
618
+  return 'KO'
619
+
620
+@app.route('/kits/new', methods=['POST'])
621
+@resume_session
622
+def new_kit():
623
+  """ Add kit """
624
+  kit = Stock_kits(name=session[u'k_name'].decode('utf8'),
625
+                    designation=session[u'k_designation'].decode('utf8'))
626
+  try:
627
+    db.session.add(kit)
628
+    commit =  db.session.commit()
629
+  except Exception as e:
630
+    print "[+] Error at new_kit:"
631
+    print "------------------------------"
632
+    print "%s" % e.message
633
+    print "------------------------------"
634
+    return 'KO'
635
+  if commit != None:
636
+    return 'KO'
637
+  return 'OK'
638
+
639
+@app.route('/kits/delete/<kit_id>')
640
+@resume_session
641
+def delete_kit(kit_id):
642
+  """ Delete kit """
643
+  try:
644
+    kit_id = int(kit_id)
645
+    Stock_kit_compositions.query.filter_by(kit_id=kit_id).delete()
646
+    Stock_kits.query.filter_by(id=kit_id).delete()
647
+    db.session.commit()
648
+  except ValueError as e:
649
+    return render_template('error.html'), 404
650
+  except Exception as e:
651
+    print "[+] Error at delete_kit:"
652
+    print "------------------------------"
653
+    print "%s" % e.message
654
+    print "------------------------------"
655
+  return kits()
656
+
657
+@app.route('/kits/update', methods=['POST'])
658
+@resume_session
659
+def search_kits():
660
+  """ Display componants list """
661
+  # search by name
662
+  like = '%s%s%s' % ('%', str(session[u'k_name']), '%')
663
+  kits = Stock_kits.query.filter(Stock_kits.name.like(like))
664
+  # search by designation
665
+  like = '%s%s%s' % ('%', str(session[u'k_designation']), '%')
666
+  kits = kits.filter(Stock_kits.designation.like(like))
667
+
668
+  # Pages calculation
669
+  session[u'k_count'] = kits.count()
670
+  session[u'k_pagecount'] = int(math.ceil(session[u'k_count'] / float(session[u'k_limit'])))
671
+  session[u'k_page'] = int(math.ceil(float(float(session[u'k_offset']) + 1) / float(session[u'k_limit'])))
672
+  if session[u'k_page'] > session[u'k_pagecount']:
673
+    session[u'k_page'] = session[u'k_pagecount']
674
+    session[u'k_offset'] = 0
675
+  session[u'k_nexthop'] = session[u'k_offset'] + session[u'k_limit']
676
+  if session[u'k_nexthop'] > session[u'k_count'] - 1:
677
+    session[u'k_nexthop'] = int(session[u'k_offset'])
678
+  session[u'k_prevhop'] =  int(session[u'k_offset']) - session[u'k_limit']
679
+  if session[u'k_prevhop'] < 0:
680
+    session[u'k_prevhop']  = 0
681
+  # Sorting
682
+  sort = getattr(Stock_kits, session[u'k_sort'].decode('utf8'))
683
+  if session[u'k_order'] == 'desc':
684
+    sort = getattr(Stock_kits, session[u'k_sort'].decode('utf8')).desc()
685
+  kits =   kits.order_by(sort)
686
+  # Applying offset
687
+  kits = kits.offset(session[u'k_offset'])
688
+  # Applying limit
689
+  kits = kits.limit(session[u'k_limit'])
690
+  # Get result
691
+  kits = kits.all()
692
+  response = app.make_response(render_template('result_kits.html',
693
+                            kits=kits,
694
+                            offset=session[u'k_offset'] ,
695
+                            nexthop=session[u'k_nexthop'],
696
+                            prevhop=session[u'k_prevhop'],
697
+                            page_count=session[u'k_pagecount'],
698
+                            page=session[u'k_page'],
699
+                            sort=session[u'k_sort'].decode('utf8'),
700
+                            order=session[u'k_order'].decode('utf8'),
701
+                            row_count=session[u'k_count']))
702
+  for key in session:
703
+    response.set_cookie(key, value=str(session[key]))
704
+    if key != 'session':
705
+      print '[c]', key, session[key]
706
+  return response
473 707
 
474 708
 ########################################################################
475 709
 # Users

Loading…
Cancel
Save