Browse Source

Nouvelle feuille de style + gestion fournisseurs

master
Doug Le Tough 4 years ago
parent
commit
a0b4516f98
13 changed files with 2153 additions and 472 deletions
  1. +1121
    -0
      result.log
  2. +200
    -16
      static/scripts/tetalab.js
  3. +119
    -173
      static/style/style.css
  4. +2
    -2
      stock.sql
  5. +107
    -108
      templates/componant.html
  6. +64
    -58
      templates/componants.html
  7. +76
    -0
      templates/provider.html
  8. +90
    -0
      templates/providers.html
  9. +0
    -31
      templates/result.html
  10. +44
    -0
      templates/result_componants.html
  11. +44
    -0
      templates/result_providers.html
  12. +100
    -0
      templates/test.html
  13. +186
    -84
      tetastock.py

+ 1121
- 0
result.log
File diff suppressed because it is too large
View File


+ 200
- 16
static/scripts/tetalab.js View File

@ -5,6 +5,10 @@ var light_green = "#D5FCD8";
var base_bg = "#FEFEFE";
var base_border = "#555555";
/* **************************************************************************************
* GLOBAL
* **************************************************************************************/
///////////////////////////////////////////
// Cookies
///////////////////////////////////////////
@ -42,9 +46,11 @@ function valid_input(obj) {
, 2000);
}
///////////////////////////////////////////
/* **************************************************************************************
* COMPONTANTS
* **************************************************************************************/
// Update result
///////////////////////////////////////////
function update_componants() {
obj = document.getElementById('result_container');
var xhttp = new XMLHttpRequest();
@ -70,9 +76,8 @@ function update_componants() {
xhttp.send();
}
///////////////////////////////////////////
// Result ordering
///////////////////////////////////////////
function update_componants_by_reference(order) {
setcookie('c_order', order, 30);
setcookie('c_sort', 'reference', 30);
@ -101,19 +106,19 @@ function update_componants_by_place(order) {
update_componants();
}
function previous_page(prevhop) {
function c_previous_page(prevhop) {
setcookie('c_offset', prevhop, 30);
update_componants();
}
function next_page(nexthop) {
function c_next_page(nexthop) {
setcookie('c_offset', nexthop, 30);
update_componants();
}
///////////////////////////////////////////
// Search componants
///////////////////////////////////////////
function search_componants_by_reference(obj) {
setcookie('c_reference', obj.value, 30);
update_componants();
@ -134,22 +139,20 @@ function search_componants_by_provider(obj) {
update_componants();
}
///////////////////////////////////////////
// Delete componant
///////////////////////////////////////////
function confirm_delete() {
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)
}
///////////////////////////////////////////
// New componant
///////////////////////////////////////////
function new_componant() {
var err = false;
var obj = {};
if (getcookie('c_count') > 0){
var errr = true;
var err = true;
obj[0] = document.getElementById('reference');
}
if (getcookie('c_designation').length < 1){
@ -160,6 +163,9 @@ function new_componant() {
var err = true;
obj[2] = document.getElementById('place');
}
if (document.getElementById('provider_id').value == 1){
setcookie('c_provider', '2', 30);
}
if (err == true) {
for (i in obj){
invalid_input(obj[i]);
@ -194,9 +200,8 @@ function create_componant() {
xhttp.send();
}
///////////////////////////////////////////
// Update componant
///////////////////////////////////////////
function update_componant(obj, componant_id, type) {
if (type == 'numeric') {
if (isNaN(obj.value)) {
@ -226,3 +231,182 @@ function update_componant(obj, componant_id, type) {
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send('field='+obj.id+'&value='+obj.value);
}
/* **************************************************************************************
* PROVIDERS
* **************************************************************************************/
// Update result
function update_providers() {
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', '/providers/update', true);
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send();
}
// Result ordering
function update_providers_by_name(order) {
setcookie('p_order', order, 30);
setcookie('p_sort', 'name', 30);
setcookie('p_order_refresh', '1', 30);
update_providers();
}
function update_providers_by_address(order) {
setcookie('p_order', order, 30);
setcookie('p_sort', 'address', 30);
setcookie('p_order_refresh', '1', 30);
update_providers();
}
function update_providers_by_mail(order) {
setcookie('p_order', order, 30);
setcookie('p_sort', 'mail', 30);
setcookie('p_order_refresh', '1', 30);
update_providers();
}
function update_providers_by_url(order) {
setcookie('p_order', order, 30);
setcookie('p_sort', 'url', 30);
setcookie('p_order_refresh', '1', 30);
update_providers();
}
function update_providers_by_commentl(order) {
setcookie('p_order', order, 30);
setcookie('p_sort', 'comment', 30);
setcookie('p_order_refresh', '1', 30);
update_providers();
}
function p_previous_page(prevhop) {
setcookie('p_offset', prevhop, 30);
update_providers();
}
function p_next_page(nexthop) {
setcookie('p_offset', nexthop, 30);
update_providers();
}
// Search providers
function search_providers_by_name(obj) {
setcookie('p_name', obj.value, 30);
update_providers();
}
function search_providers_by_address(obj) {
setcookie('p_address', obj.value, 30);
update_providers();
}
function search_providers_by_mail(obj) {
setcookie('p_mail', obj.value, 30);
update_providers();
}
function search_providers_by_url(obj) {
setcookie('p_url', obj.value, 30);
update_providers();
}
function search_providers_by_comment(obj) {
setcookie('p_comment', obj.value, 30);
update_providers();
}
// New provider
function new_provider() {
var err = false;
var obj = {};
if (getcookie('p_count') > 0){
var err = true;
obj[0] = document.getElementById('name');
}
if (err == true) {
for (i in obj){
invalid_input(obj[i]);
}
return;
}
create_provider();
update_providers();
}
function create_provider() {
var MSG='Erreur lors de la creation du fournisseur.';
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', '/providers/new', true);
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send();
}
// Delete 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)
}
// Update provider
function update_provider(obj, provider_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', '/providers/update/'+provider_id, true);
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send('field='+obj.id+'&value='+obj.value);
}

+ 119
- 173
static/style/style.css View File

@ -140,8 +140,8 @@ div.content {
}
div.note {
font-size: 12px;
line-height: 12px;
font-size: 14px;
line-height: 14px;
}
div.error {
@ -178,121 +178,120 @@ div.footer {
}
/* ***********************************
* Résultats
* Classes génériques
*********************************** */
div.row_count {
padding: 5px;
h3, h4 {
text-decoration: underline;
}
div.result_container {
text-align: left;
a {
color: #FF5D00;
text-decoration: none;
padding: 2px;
}
.border_left {
border-left-width: 1px;
border-left-style: solid;
a:hover {
background-color: #FFB387;
}
.border_right {
border-right-width: 1px;
border-right-style: solid;
span.bold {
font-weight: bold;
}
div.block, div.noborder {
overflow: hidden;
border-top-style: solid;
border-top-width: 1px;
height: 20px;
/* ***********************************
* Search
*********************************** */
div.main_block {
padding: 0;
margin: 0;
width: 1000px;
float: left;
}
div.noborder {
border-style: none;
div.main_block text {
display: block;
font-weight: bold;
margin-bottom: 4px;
}
div.inner{
overflow: hidden;
float: center;
div.button_block {
margin: 0 0 4px 0;
height: 20px;
width: 525px;
}
div.pages_nav_bar {
overflow: hidden;
width: 1000px;
border-top-style: solid;
border-top-width: 1px;
div.button_block input {
position: relative;
width: 16px;
height: 16px;
border-radius: 2px;
margin-right: 32px;
left: 250px;
}
div.button_block input:hover {
cursor: pointer;
background-color: #FF5D00;
}
div.input_block {
margin: 0 0 4px 0;
height: 20px;
text-align: right;
padding-top: 10px;
width: 525px;
}
div.block text{
width: 200px;
div.input_block label {
display: block;
float: left;
width: 200px;
text-align: center;
font-weight: bold;
background-color: #FF5D00;
height: 20px;
text-align: left;
vertical-align: middle;
padding: 0 4px 0 4px;
}
div.block text.num{
width: 200px;
float: left;
div.input_block select, div.input_block input {
width: 310px;
float: right;
padding: 0 4px 0 4px;
margin-left: 4px;
text-align: right;
background-color: #FFFFFF;
border-style: solid;
border-width: 1px;
border-color: #555555;
color: #555555;
height: 20px;
}
div.inner text.edit, div.block text.edit {
background: url(../images/edit.png);
margin: 2px 0px 0px 20px;
}
div.inner text.trash {
background: url(../images/trash.png);
margin: 2px 0px 0px 20px;
}
div.block text.refresh {
background: url(../images/refresh.png);
margin: 2px 0px 0px 20px;
}
div.block text.search {
background: url(../images/search.png);
margin-left: 255px;
div.input_block input {
float: right;
height: 17px;
width: 300px;
}
div.block text.save {
background: url(../images/save.png);
margin-left: 32px;
}
/* ***********************************
* Result
*********************************** */
div.inner text.edit:hover,
div.inner text.trash:hover,
div.block text.refresh:hover,
div.block text.search:hover,
div.block text.save:hover{
background-color: #FFB387;
cursor: pointer;
.border_bottom {
border-bottom-style: solid;
border-bottom-width: 1px;
}
div.inner text.edit {
width: 16px;
float:left;
height: 16px;
margin: 2px 0px 0px 20px;
border-radius: 2px;
background-repeat: no-repeat;
.border_top {
border-top-style: solid;
border-top-width: 1px;
}
div.inner text.trash,
div.inner text.edit,
div.block text.refresh,
div.block text.search,
div.block text.save {
width: 8px;
float:left;
height: 16px;
border-radius: 2px;
background-repeat: no-repeat;
.border_left {
border-left-width: 1px;
border-left-style: solid;
}
div.even {
@ -303,32 +302,6 @@ div.odd {
background-color: #FFFFFF;
}
div.block label {
width: 200px;
display: block;
float: left;
text-align: center;
font-weight: bold;
background-color: #FF5D00;
}
div.block label:hover {
cursor: pointer;
}
div.block .input{
margin-left:4px;
float:left;
}
div.action_bar {
display: inline-block;
width: 50px;
height: 32px;
}
span.prev_page, span.next_page {
color: #FF5D00;
font-weight: bold;
@ -345,92 +318,65 @@ span.page_num {
font-size: 12px;
}
/* ***********************************
* Editables
*********************************** */
div.no_border {
border-style: none;
border-width: 0px;
}
div.margin_bottom {
margin-bottom: 4px;
}
div.block label.editable {
div.row_block {
margin: 0 0 4px 0;
height: 20px;
text-align: left;
vertical-align: middle;
padding: 0 4px 0 4px;
width: 1000px;
}
div.block text.editable {
width: 200px;
float: left;
padding: 0 4px 0 4px;
margin-left: 4px;
div.nav_page_block {
text-align: right;
background-color: #FFFFFF;
border-style: solid;
border-width: 1px;
height: 20px;
width: 1000px;
}
div.block select, div.block input {
width: 310px;
float: left;
padding: 0 4px 0 4px;
margin-left: 4px;
text-align: right;
background-color: #FFFFFF;
border-style: solid;
border-width: 1px;
border-color: #555555;
color: #555555;
div.action_bar_block {
overflow: hidden;
float: center;
height: 20px;
}
div.block input {
height: 17px;
width: 300px;
}
/* ***********************************
* Classes génériques
*********************************** */
h3, h4 {
text-decoration: underline;
div.row_block label {
display: block;
float: left;
text-align: center;
font-weight: bold;
background-color: #FF5D00;
vertical-align: middle;
}
a {
color: #FF5D00;
text-decoration: none;
padding: 2px;
div.row_block label:hover {
cursor: pointer;
}
a:hover {
background-color: #FFB387;
div.row_block label.border_left,
div.row_block text.border_left {
border-left-style: solid;
border-left-width: 1;
}
span.bold {
font-weight: bold;
div.row_block text {
display: block;
float: left;
font-weight: normal;
text-align: left;
overflow: hidden;
vertical-align: middle;
padding: 0 5px 0 5px;
white-space: nowrap;
}
table {
border-collapse: collapse;
width: 100%;
div.row_block text.num {
text-align: right;
}
th {
background-color: #FFB387;
div.nav_page_block text {
display: block;
white-space: nowrap;
}
th, td {
text-align: left;
padding: 8px;
div.action_bar_block input {
height: 17px;
width: 16px;
margin-left: 20px;
}
tr:nth-child(even){background-color: #f2f2f2}

+ 2
- 2
stock.sql View File

@ -20,7 +20,7 @@ CREATE TABLE stock_kits (
CREATE TABLE stock_providers (
id serial primary key,
name text not NULL,
name text unique not NULL,
address text not NULL,
mail text not NULL,
url text not NULL,
@ -58,7 +58,7 @@ insert into stock_providers (name, address, mail, url, comment)
insert into stock_providers (name, address, mail, url, comment)
values ('Aucun', 'N/A', 'N/A', 'N/A', 'N/A');
insert into stock_providers (name, address, mail, url, comment)
values ('China Elec Co', 'Beijing', 'sales@chinaelecco.cc', 'https://chinaelecco', 'Pas cher, mais...');
values ('China Elec Co', 'Beijing', 'sales@chinaelecco.cc', 'https://chinaelecco.cc', 'Pas cher mais délai excessif et composants pourris');
insert into stock_componants (reference, designation, last_price, mean_price, quantity, min_quantity, place, provider_id)
values ('Res-01', 'Resistance 10KΩ', 13.34, 12.42, 73, 0, 'B 43', 3);


+ 107
- 108
templates/componant.html View File

@ -3,7 +3,6 @@
{% block top_menu %}
<span class='top_menu_item' onclick='javascript:document.location="/componants";'>Rechercher un composant</span>
<span class='top_menu_item_selected' onclick='javascript:document.location="/componants/{{ componant.id }}";'>Éditer un composant</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/new";'>Nouveau composant</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/in";'>Entrée de stock</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/out";'>Sortie de stock</span>
{% endblock %}
@ -24,111 +23,111 @@
{% endblock %}
{% block content %}
<h3>Note:</h3>
<div class='note'>
<p>Cette page vous permet de modifier directement un composant.</p>
<p>À moins de vouloir corriger une erreur de saisie, ou de saisir un inventaire vous ne devez
<strong>PAS</strong> modifier directement
les quantités d'un composant.</p>
<p>Cliquez sur les liens suivants pour saisir des <a href='/componant/in/{{ componant.id }}'>entrées</a>
ou <a href='/componant/out/{{ componant.id }}'>sorties</a> de stock.</p>
</div>
<h3>Composant:</h3>
<div class='block margin_bottom no_border'>
<label class='editable'>Référence (unique)</label>
<input
id='reference'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
value='{{ componant.reference }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Désignation</label>
<input
id='designation'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
value='{{ componant.designation }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Dernier prix d'achat</label>
<input
id='last_price'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title="Dernier prix d'achat"
placeholder="Dernier prix d'achat"
value='{{ componant.last_price }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Coût d'achat moyen pondéré</label>
<input
id='mean_price'
type='text'
class='editable'
maxlength='15'
title='CMP (non éditable)'
readonly value='{{ componant.mean_price }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Quantité</label>
<input
id='quantity'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title='Quantité'
placeholder='Quantité'
value='{{ componant.quantity }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Quantité minimum</label>
<input
id='min_quantity'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title='Quantité minimum'
placeholder='Quantité minimum'
value='{{ componant.min_quantity }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Emplacement</label>
<input
id='place'
type='text'
class='editable'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
value='{{ componant.place }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Fournisseur</label>
<select
id='provider_id'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
title='Fournisseur'>
{% for prov in providers %}
{% set option_selected = '' %}
{% if prov.id == provider.id %}
{% set option_selected = 'selected="selected"' %}
{% endif %}
<option {{ option_selected }} value='{{ prov.id }}'>{{ prov.name }}</option>
{% endfor %}
</select>
</div>
<div id='note' class='main_block'>
<text>Note:</text>
<div class='note'>
<p>Cette page vous permet de modifier directement un composant.<br/>
À moins de vouloir corriger une erreur de saisie, ou de saisir un inventaire <br/>
vous ne devez <strong>PAS</strong> modifier directement les quantités d'un composant.</p>
<p>Cliquez sur les liens suivants pour saisir des
<span class='top_menu_item_selected' onclick='javascript:document.location="/componant/in/{{ componant.id }}"'>entrées</span>
ou
<span class='top_menu_item_selected' onclick='javascript:document.location="/componant/out/{{ componant.id }}"'>sorties</span> de stock.</p>
</div>
</div>
<div id='edit' class='main_block'>
<text>Composant:</text>
<div class='input_block'>
<label>Référence (unique)</label>
<input
id='reference'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
value='{{ componant.reference }}' />
</div>
<div class='input_block'>
<label>Désignation</label>
<input
id='designation'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
value='{{ componant.designation }}' />
</div>
<div class='input_block'>
<label>Dernier prix d'achat</label>
<input
id='last_price'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title="Dernier prix d'achat"
placeholder="Dernier prix d'achat"
value='{{ componant.last_price }}' />
</div>
<div class='input_block'>
<label>Coût d'achat moyen</label>
<input
id='mean_price'
type='text'
maxlength='15'
title='CMP (non éditable)'
readonly value='{{ componant.mean_price }}' />
</div>
<div class='input_block'>
<label>Quantité</label>
<input
id='quantity'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title='Quantité'
placeholder='Quantité'
value='{{ componant.quantity }}' />
</div>
<div class='input_block'>
<label>Quantité minimum</label>
<input
id='min_quantity'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
maxlength='15'
title='Quantité minimum'
placeholder='Quantité minimum'
value='{{ componant.min_quantity }}' />
</div>
<div class='input_block'>
<label>Emplacement</label>
<input
id='place'
type='text'
onchange='javascript:update_componant(this, {{ componant.id }}, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
value='{{ componant.place }}' />
</div>
<div class='input_block'>
<label>Fournisseur</label>
<select
id='provider_id'
onchange='javascript:update_componant(this, {{ componant.id }}, "numeric");'
title='Fournisseur'>
{% for prov in providers %}
{% if prov.id > 1 %}
{% set option_selected = '' %}
{% if prov.id == provider.id %}
{% set option_selected = 'selected="selected"' %}
{% endif %}
<option {{ option_selected }} value='{{ prov.id }}'>{{ prov.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
{% endblock %}

+ 64
- 58
templates/componants.html View File

@ -4,8 +4,7 @@
{% endblock %}
{% block title %}Liste des composants{% endblock %}
{% block top_menu %}
<span class='top_menu_item_selected' onclick='javascript:document.location="/componants/search";'>Rechercher un composant</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/new";'>Nouveau composant</span>
<span class='top_menu_item_selected' onclick='javascript:document.location="/componants";'>Gestion des composants</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/in";'>Entrée de stock</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/out";'>Sortie de stock</span>
{% endblock %}
@ -29,66 +28,73 @@
<!-- ----------------------------------------------------
Recherche
----------------------------------------------------- -->
<h3>Recherche:</h3>
<div class='block margin_bottom no_border'>
<label class='editable'>Référence (unique)</label>
<input
id='reference'
type='text'
class='editable'
onkeyup='javascript:search_componants_by_reference(this, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
value='{{ reference }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Désignation</label>
<input
id='designation'
type='text'
class='editable'
onkeyup='javascript:search_componants_by_designation(this, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
value='{{ designation }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Emplacement</label>
<input
id='place'
type='text'
class='editable'
onkeyup='javascript:search_componants_by_place(this, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
value='{{ place }}' />
</div>
<div class='block margin_bottom no_border'>
<label class='editable'>Fournisseur</label>
<select
id='provider_id'
onchange='javascript:search_componants_by_provider(this, "numeric");'
title='Fournisseur'>
{% for prov in providers %}
{% set selected = '' %}
{% if prov.id == provider_id %}
{% set selected = 'selected' %}
{% endif %}
<option value='{{ prov.id }}' {{ selected }}>{{ prov.name }}</option>
{% endfor %}
</select>
</div>
<div class='block margin_bottom no_border center'>
<text title='Rechercher' class='search' onclick='javascript:update_componants("reference");'></text>
<text title='Enregistrer' class='save' onclick='javascript:new_componant();'></text>
<div id='search' class='main_block'>
<text>Recherche:</text>
<div class='input_block'>
<label>Référence (unique)</label>
<input
id='reference'
type='text'
onkeyup='javascript:search_componants_by_reference(this, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
value='{{ reference }}' />
</div>
<div class='input_block'>
<label>Désignation</label>
<input
id='designation'
type='text'
onkeyup='javascript:search_componants_by_designation(this, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
value='{{ designation }}' />
</div>
<div class='input_block'>
<label>Emplacement</label>
<input
id='place'
type='text'
onkeyup='javascript:search_componants_by_place(this, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
value='{{ place }}' />
</div>
<div class='input_block'>
<label>Fournisseur</label>
<select
id='provider_id'
onchange='javascript:search_componants_by_provider(this, "numeric");'
title='Fournisseur'>
{% for prov in providers %}
{% set selected = '' %}
{% if prov.id == provider_id %}
{% set selected = 'selected' %}
{% endif %}
<option value='{{ prov.id }}' {{ selected }}>{{ prov.name }}</option>
{% endfor %}
</select>
</div>
<div class='button_block'>
<input
type='image'
src='/static/images/search.png'
title='Rechercher'
onclick='javascript:update_componants("reference");'/>
<input
type='image'
src='/static/images/save.png'
title='Enregistrer'
onclick='javascript:new_componant();'/>
</div>
</div>
<!-- ----------------------------------------------------
Resultat
----------------------------------------------------- -->
<div id='result_container' class='result_container'>
<div id='result_container' class='main_block'>
</div>
{% endblock %}

+ 76
- 0
templates/provider.html View File

@ -0,0 +1,76 @@
{% extends "index.html" %}
{% block title %}Éditer un fournisseur{% endblock %}
{% block top_menu %}
<span class='top_menu_item' onclick='javascript:document.location="/providers";'>Gérer les fournisseurs</span>
<span class='top_menu_item_selected' onclick='javascript:document.location="/providers/{{ provider.id }}";'>Éditer un fournisseur</span>
{% endblock %}
{% block left_menu %}
<div class='left_menu_item' onclick='javascript:document.location="/";'>
Accueil
</div>
<div class='left_menu_item' onclick='javascript:document.location="/componants";'>
Composants
</div>
<div class='left_menu_item' onclick='javascript:document.location="/kits";'>
Kits
</div>
<div class='left_menu_item_selected' onclick='javascript:document.location="/providers";'>
Fournisseurs
</div>
{% endblock %}
{% block content %}
<div id='edit' class='main_block'>
<text>Composant:</text>
<div class='input_block'>
<label>Nom (unique)</label>
<input
id='name'
type='text'
onchange='javascript:update_provider(this, {{ provider.id }}, "text");'
maxlength='20'
title='Nom unique (max. 20)'
placeholder='Nom unique (max. 20)'
value='{{ provider.name }}' />
</div>
<div class='input_block'>
<label>Adresse</label>
<input
id='address'
type='text'
onchange='javascript:update_provider(this, {{ provider.id }}, "text");'
title='Adresse'
placeholder='Adresse'
value='{{ provider.address }}' />
</div>
<div class='input_block'>
<label>@ mail</label>
<input
id='mail'
type='text'
onchange='javascript:update_provider(this, {{ provider.id }}, "text");'
title="Adresse e-mail"
placeholder="Adresse e-mail"
value='{{ provider.mail }}' />
</div>
<div class='input_block'>
<label>URL</label>
<input
id='url'
type='text'
onchange='javascript:update_provider(this, {{ provider.id }}, "text");'
title="URL"
placeholder="URL"
value='{{ provider.url }}' />
</div>
<div class='input_block'>
<label>Commentaires</label>
<input
id='comment'
type='text'
onchange='javascript:update_provider(this, {{ provider.id }}, "text");'
title='Commentaire'
value='{{ provider.comment }}' />
</div>
</div>
{% endblock %}

+ 90
- 0
templates/providers.html View File

@ -0,0 +1,90 @@
{% extends "index.html" %}
{% block bodyheader %}
<body onload="javascript:update_providers();">
{% endblock %}
{% block title %}Liste des fournisseurs{% endblock %}
{% block top_menu %}
<span class='top_menu_item_selected' onclick='javascript:document.location="/providers";'>Gérer les fournisseurs</span>
{% endblock %}
{% block left_menu %}
<div class='left_menu_item' onclick='javascript:document.location="/";'>
Accueil
</div>
<div class='left_menu_item' onclick='javascript:document.location="/componants";'>
Composants
</div>
<div class='left_menu_item' onclick='javascript:document.location="/kits";'>
Kits
</div>
<div class='left_menu_item_selected' onclick='javascript:document.location="/providers";'>
Fournisseurs
</div>
{% endblock %}
{% block content %}
<!-- ----------------------------------------------------
Recherche
----------------------------------------------------- -->
<div id='search' class='main_block'>
<text>Recherche:</text>
<div class='input_block'>
<label>Nom (unique)</label>
<input
id='name'
type='text'
onkeyup='javascript:search_providers_by_name(this, "text");'
title='Nom unique'
placeholder='Nom unique'
value='{{ name }}' />
</div>
<div class='input_block'>
<label>Adresse</label>
<input
id='address'
type='text'
onkeyup='javascript:search_providers_by_address(this, "text");'
title='Adresse'
placeholder='Adresse'
value='{{ address }}' />
</div>
<div class='input_block'>
<label>@ mail</label>
<input
id='mail'
type='text'
onkeyup='javascript:search_providers_by_mail(this, "text");'
title='Adresse mail'
placeholder='Adresse mail'
value='{{ mail }}' />
</div>
<div class='input_block'>
<label>URL</label>
<input
id='url'
type='text'
onkeyup='javascript:search_providers_by_url(this, "text");'
title='URL'
placeholder='URL'
value='{{ url }}' />
</div>
<div class='button_block'>
<input
type='image'
src='/static/images/search.png'
title='Rechercher'
onclick='javascript:update_providers("name");'/>
<input
type='image'
src='/static/images/save.png'
title='Enregistrer'
onclick='javascript:new_provider();'/>
</div>
</div>
<!-- ----------------------------------------------------
Resultat
----------------------------------------------------- -->
<div id='result_container' class='result_container'>
</div>
{% endblock %}

+ 0
- 31
templates/result.html View File

@ -1,31 +0,0 @@
<h3>Résultat:</h3>
{% set ss='' %}
{% if row_count > 1 %}
{% set ss='s' %}
{% endif %}
<div class='row_count'>{{ row_count }} objet{{ ss }} selectionné{{ ss }}</div>
<div class='block' style='border-top-style: none;'>
<label onclick='javascript:update_componants_by_reference("{{ order }}");'>Référence</label>
<label onclick='javascript:update_componants_by_designation("{{ order }}");' class='border_left' style='width: 440px;'>Désignation</label>
<label onclick='javascript:update_componants_by_quantity("{{ order }}");' class='border_left' style='width: 100px;'>Quantité</label>
<label onclick='javascript:update_componants_by_place("{{ order }}");' class='border_right border_left' style='width: 160px;'>Emplacement</label>
<label style='width: 106px; cursor: default;'>Action</label>
</div>
{% set row_class = cycler('odd', 'even') %}
{% for componant in componants %}
<div class='block {{ row_class.next() }}'>
<text style='width: 192px;'>{{ componant.reference }}</text>
<text class='border_left' style='width: 432px;'>{{ componant.designation }}</text>
<text class='num border_left' style='width: 92px;'>{{ componant.quantity }}</text>
<text class='num border_right border_left' style='width: 152px;'>{{ componant.place }}</text>
<div class='inner' style='width: 95px;'>
<text class='edit' title='Éditer' onclick='javascript:document.location="/componants/{{ componant.id }}"'></text>
<text class='trash' title='Supprimer' onclick='javascript:confirm_delete()?document.location="/componants/delete/{{ componant.id }}":false;'></text>
</div>
</div>
{% endfor %}
<div class='pages_nav_bar'>
<text><span class='prev_page' onclick='javascript:previous_page({{ prevhop }});'><</span></text>
<text><span class='page_num'>{{ page }} / {{ page_count }}</span></text>
<text><span class='next_page' onclick='javascript:next_page({{ nexthop }})'>></span></text>
</div>

+ 44
- 0
templates/result_componants.html View File

@ -0,0 +1,44 @@
<div class='main_block'>
<text>Résultat:
{% set ss='' %}
{% if row_count > 1 %}
{% set ss='s' %}
{% endif %}
{{ row_count }} objet{{ ss }} selectionné{{ ss }}
</text>
<div class='row_block border_bottom'>
<label style='width: 200px;' onclick='javascript:update_componants_by_reference("{{ order }}");'>Référence</label>
<label class='border_left' style='width: 449px;' onclick='javascript:update_componants_by_designation("{{ order }}");'>Désignation</label>
<label class='border_left' style='width: 99px;' onclick='javascript:update_componants_by_quantity("{{ order }}");'>Quantité</label>
<label class='border_left' style='width: 149px;' onclick='javascript:update_componants_by_place("{{ order }}");'>Emplacement</label>
<label class='border_left' style='width: 99px; cursor: default;'>Action</label>
</div>
{% set row_class = cycler('odd', 'even') %}
{% for componant in componants %}
<div class='row_block {{ row_class.next() }}'>
<text style='width: 190px;'>{{ componant.reference }}</text>
<text class='border_left' style='width: 439px;'>{{ componant.designation }}</text>
<text class='num border_left' style='width: 89px;'>{{ componant.quantity }}</text>
<text class='num border_right border_left' style='width: 139px;'>{{ componant.place }}</text>
<div class='action_bar_block border_left' style='width: 89px;'>
<input
type='image'
src='/static/images/edit.png'
title='Éditer'
onclick='javascript:document.location="/componants/{{ componant.id }}"'/>
<input
type='image'
src='/static/images/trash.png'
title='Supprimer'
onclick='javascript:confirm_componant_delete()?document.location="/componants/delete/{{ componant.id }}":false;'/>
</div>
</div>
{% endfor %}
<div class='nav_page_block border_top'>
<text>
<span class='prev_page' onclick='javascript:c_previous_page({{ prevhop }});'>&lt;</span>
<span class='page_num'>{{ page }} / {{ page_count }}</span>
<span class='next_page' onclick='javascript:c_next_page({{ nexthop }})'>&gt;</span>
</text>
</div>
</div>

+ 44
- 0
templates/result_providers.html View File

@ -0,0 +1,44 @@
<div class='main_block'>
<text>Résultat:
{% set ss='' %}
{% if row_count > 1 %}
{% set ss='s' %}
{% endif %}
{{ row_count }} objet{{ ss }} selectionné{{ ss }}
</text>
<div class='row_block border_bottom'>
<label style='width: 209px;' onclick='javascript:update_providers_by_name("{{ order }}");'>Nom</label>
<label class='border_left' style='width: 199px;' onclick='javascript:update_providers_by_address("{{ order }}");'>Addresse</label>
<label class='border_left' style='width: 199px;' onclick='javascript:update_providers_by_mail("{{ order }}");'>@ Mail</label>
<label class='border_left' style='width: 299px;' onclick='javascript:update_providers_by_url("{{ order }}");'>URL</label>
<label class='border_left' style='width: 89px;' style='cursor: default;'>Action</label>
</div>
{% set row_class = cycler('odd', 'even') %}
{% for provider in providers %}
<div class='row_block {{ row_class.next() }}'>
<text style='width: 199px;'>{{ provider.name }}</text>
<text class='border_left' style='width: 189px;'>{{ provider.address }}</text>
<text class='border_left' style='width: 189px;'>{{ provider.mail }}</text>
<text class='border_left' style='width: 289px;'>{{ provider.url }}</text>
<div class='action_bar_block border_left' style='width: 89px;'>
<input
type='image'
src='/static/images/edit.png'
title='Éditer'
onclick='javascript:document.location="/providers/{{ provider.id }}"'/>
<input
type='image'
src='/static/images/trash.png'
title='Supprimer'
onclick='javascript:confirm_provider_delete()?document.location="/providers/delete/{{ provider.id }}":false;'/>
</div>
</div>
{% endfor %}
<div class='nav_page_block border_top'>
<text>
<span class='prev_page' onclick='javascript:p_previous_page({{ prevhop }});'>&lt;</span>
<span class='page_num'>{{ page }} / {{ page_count }}</span>
<span class='next_page' onclick='javascript:p_next_page({{ nexthop }})'>&gt;</span>
</text>
</div>
</div>

+ 100
- 0
templates/test.html View File

@ -0,0 +1,100 @@
{% extends "index.html" %}
{% block bodyheader %}
<body onload="javascript:update_componants();">
{% endblock %}
{% block title %}Liste des composants{% endblock %}
{% block top_menu %}
<span class='top_menu_item_selected' onclick='javascript:document.location="/componants";'>Gestion des composants</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/in";'>Entrée de stock</span>
<span class='top_menu_item' onclick='javascript:document.location="/componants/out";'>Sortie de stock</span>
{% endblock %}
{% block left_menu %}
<div class='left_menu_item' onclick='javascript:document.location="/";'>
Accueil
</div>
<div class='left_menu_item_selected' onclick='javascript:document.location="/componants";'>
Composants
</div>
<div class='left_menu_item' onclick='javascript:document.location="/kits";'>
Kits
</div>
<div class='left_menu_item' onclick='javascript:document.location="/providers";'>
Fournisseurs
</div>
{% endblock %}
{% block content %}
<!-- ----------------------------------------------------
Recherche
----------------------------------------------------- -->
<div id='search' class='main_block'>
<text>Recherche:</text>
<div class='input_block'>
<label>Référence (unique)</label>
<input
id='reference'
type='text'
onkeyup='javascript:search_componants_by_reference(this, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
value='{{ reference }}' />
</div>
<div class='input_block'>
<label>Désignation</label>
<input
id='designation'
type='text'
onkeyup='javascript:search_componants_by_designation(this, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
value='{{ designation }}' />
</div>
<div class='input_block'>
<label>Emplacement</label>
<input
id='place'
type='text'
onkeyup='javascript:search_componants_by_place(this, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
value='{{ place }}' />
</div>
<div class='input_block'>
<label>Fournisseur</label>
<select
id='provider_id'
onchange='javascript:search_componants_by_provider(this, "numeric");'
title='Fournisseur'>
{% for prov in providers %}
{% set selected = '' %}
{% if prov.id == provider_id %}
{% set selected = 'selected' %}
{% endif %}
<option value='{{ prov.id }}' {{ selected }}>{{ prov.name }}</option>
{% endfor %}
</select>
</div>
<div class='button_block'>
<input
type='image'
src='/static/images/search.png'
title='Rechercher'
onclick='javascript:update_componants("reference");'/>
<input
type='image'
src='/static/images/save.png'
title='Enregistrer'
onclick='javascript:new_componant();'/>
</div>
</div>
<!-- ----------------------------------------------------
Resultat
----------------------------------------------------- -->
<div id='result_container' class='main_block'>
</div>
{% endblock %}

+ 186
- 84
tetastock.py View File

@ -42,6 +42,7 @@ class Stock_providers(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text, nullable=False)
address = db.Column(db.Text)
mail = db.Column(db.Text)
url = db.Column(db.Text)
comment = db.Column(db.Text)
@ -60,16 +61,19 @@ def resume_session(func):
@wraps(func)
def check(*args, **kwargs):
# default
limit = 8
limit = 10
offset = 0
page = 1
nexthop = offset + limit
prevhop = offset
sort = 'reference'
order = 'asc'
order_refresh = 0
c_empty = ''
c_sort = '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'] = ''
@ -78,11 +82,13 @@ def resume_session(func):
if not 'c_offest' in session:
session['c_offset'] = offset
if not 'c_sort' in session:
session['c_sort'] = sort
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:
@ -97,6 +103,33 @@ def resume_session(func):
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
# Cookies/session sync
for key in request.cookies:
old = str(session[key])
@ -109,14 +142,18 @@ def resume_session(func):
session['c_offset'] = 0
if key != 'session':
print '+', key, request.cookies[key]
print '[s]', key, request.cookies[key]
# 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
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
return func(*args, **kwargs)
return check
@ -149,6 +186,7 @@ def componants():
provider_id=session['c_provider'])
@app.route('/componants/<componant_id>')
@resume_session
def get_componant(componant_id):
""" Edit componant """
try:
@ -164,6 +202,7 @@ def get_componant(componant_id):
return render_template('error.html'), 404
@app.route('/componants/update/<componant_id>', methods=['POST'])
@resume_session
def update_componant(componant_id):
""" Update componant field"""
field = request.form['field']
@ -180,14 +219,17 @@ def update_componant(componant_id):
return 'KO'