This commit is contained in:
2019-01-19 16:37:16 +01:00
42 changed files with 1514 additions and 372 deletions

View File

@@ -22,6 +22,7 @@ sqlalchemy.url = mysql://phuoc:phuoc!@localhost/bddevfac?charset=utf8
# sqlalchemy.url = mysql://root:cni/@srvbd/bddevfac?charset=utf8 # sqlalchemy.url = mysql://root:cni/@srvbd/bddevfac?charset=utf8
mondumas.admin_email = ctphuoc@bbox.fr mondumas.admin_email = ctphuoc@bbox.fr
mondumas.DEVFAC14 = mondumas:static/img/DEVFAC14/
# Mailer configuration # Mailer configuration
mail.host = smtp.free.fr mail.host = smtp.free.fr

View File

@@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: mondumas Name: mondumas
Version: 0.1 Version: 1.0
Summary: mondumas Summary: mondumas
Home-page: UNKNOWN Home-page: UNKNOWN
Author: Author:
@@ -9,16 +9,16 @@ License: UNKNOWN
Description: # README # Description: # README #
Application web permettant aux personnels de l'entreprise Dumas d'accéder aux dossiers des clients Application web permettant aux personnels de l'entreprise Dumas d'accéder aux dossiers des clients
Développé avec : Développé avec :
- Pyramid Framework - Pyramid Framework
- MySQL - MySQL
- Chameleon - Chameleon
* [Exemple d'une comptabilité simple] (http://perso.numericable.fr/assoc1901/droit/comptabilite1.htm) * [Exemple d'une comptabilité simple] (http://perso.numericable.fr/assoc1901/droit/comptabilite1.htm)
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo) * [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)

View File

@@ -21,10 +21,12 @@ mondumas.egg-info/top_level.txt
mondumas/models/__init__.py mondumas/models/__init__.py
mondumas/models/agenda.py mondumas/models/agenda.py
mondumas/models/default.py mondumas/models/default.py
mondumas/models/dossier.py
mondumas/models/parametres.py mondumas/models/parametres.py
mondumas/scripts/__init__.py mondumas/scripts/__init__.py
mondumas/views/__init__.py mondumas/views/__init__.py
mondumas/views/agenda.py mondumas/views/agenda.py
mondumas/views/default.py mondumas/views/default.py
mondumas/views/dossier.py
mondumas/views/notfound.py mondumas/views/notfound.py
mondumas/views/parametres.py mondumas/views/parametres.py

View File

@@ -1,16 +1,17 @@
SQLAlchemy
docutils
mysqlclient
pyramid pyramid
pyramid_chameleon pyramid_chameleon
pyramid_debugtoolbar pyramid_debugtoolbar
pyramid_layout pyramid_layout
pyramid_mailer pyramid_mailer
pyramid_tm pyramid_tm
python-dateutil SQLAlchemy
transaction transaction
waitress
zope.sqlalchemy zope.sqlalchemy
waitress
mysqlclient
python-dateutil
docutils
user-agents
[testing] [testing]
WebTest>=1.3.1 WebTest>=1.3.1

View File

@@ -3,8 +3,10 @@ from pyramid_layout.layout import layout_config
from .security import groupfinder from .security import groupfinder
from .views.default import ( from .views.default import (
to_euro, to_euro,
to_euroz,
to_percent, to_percent,
to_decimal, to_decimal,
to_decz,
) )
@layout_config(template='templates/layouts/global_layout.pt') @layout_config(template='templates/layouts/global_layout.pt')
@@ -22,6 +24,12 @@ class GlobalLayout(object):
def to_euro(self, x): def to_euro(self, x):
return to_euro(x) return to_euro(x)
def to_euroz(self, x):
return to_euroz(x)
def to_decz(self, x):
return to_euroz(x)
def to_percent(self, x): def to_percent(self, x):
return to_percent(x) return to_percent(x)

View File

@@ -20,42 +20,20 @@ def execute_query(request, query, params):
mark_changed(request.dbsession) mark_changed(request.dbsession)
transaction.commit() transaction.commit()
def get_users_agenda(request): def get_users_agenda(request, user):
if user == '':
""" lire la liste des users ayant un agenda""" """ lire la liste des users ayant un agenda"""
query = "SELECT * FROM p_users WHERE cd_uti != 'N' and agenda != 0 AND actif != 0 ORDER BY nom;" query = "SELECT * FROM p_users WHERE cd_uti != 'N' and agenda != 0 AND actif != 0 ORDER BY nom;"
results = request.dbsession.execute(query).fetchall() results = request.dbsession.execute(query).fetchall()
return results
def get_dossier_by_no(request,nodossier):
societe = nodossier[0:2]
no_id = nodossier[3:]
query = """
SELECT d.*, c.*, a.NOM as nom_cabinet, e.NOM as nom_expert FROM dem_devis d
INNER JOIN clients c ON d.societe = c.societe and d.cd_cli = c.cd_cli
INNER JOIN p_cabinet a ON d.cabinet = a.code
INNER JOIN p_experts e ON d.cabinet = e.code_cab and d.expert = e.code_exp
where d.societe = '%s' and d.no_id=%s;""" % (societe, no_id);
results = request.dbsession.execute(query).first()
return results
def get_dossier_rdv_by_no(request,nodossier, nolig):
societe = nodossier[0:2]
no_id = nodossier[3:]
if nolig == '0':
query = "SELECT * FROM dem_lig where societe = '%s' and no_id=%s;" % (societe, no_id)
results = request.dbsession.execute(query).fetchall()
else: else:
query = "SELECT * FROM dem_lig where societe = '%s' and no_id=%s and nolig=%s;" % (societe, no_id, nolig) """ lire le user ayant un agenda"""
results = request.dbsession.execute(query).first() query = "SELECT * FROM p_users WHERE cd_uti = :user and agenda != 0 AND actif != 0 ORDER BY nom;"
results = request.dbsession.execute(query, {'user': user}).first()
return results return results
def get_documents_byChantier(request,nodossier): def get_types_rdv(request):
societe = nodossier[0:2] """ lire la liste des types de rendez-vous"""
no_id = nodossier[3:] query = "SELECT * FROM p_types_rdv ORDER BY LIB;"
query = "CALL spGET_DOSSIERS_byNumeo('%s',%s);" % (societe, no_id)
results = request.dbsession.execute(query).fetchall() results = request.dbsession.execute(query).fetchall()
return results return results
@@ -66,7 +44,7 @@ def get_rendez_vous(request, itc):
datedeb = d.strftime('%Y-%m-01') datedeb = d.strftime('%Y-%m-01')
# lire les rdv de l'ITC # lire les rdv de l'ITC
query = """SELECT CONCAT(l.societe,"-",l.no_id) as nodossier, l.rdv_debut, l.rdv_fin, e.c_nom, e.c_ville FROM dem_lig l query = """SELECT CONCAT(l.societe,"-",l.no_id) as nodossier, l.nolig, l.rdv_debut, l.rdv_fin, e.c_qualite, e.c_nom, e.c_ville, e.c_cp FROM dem_lig l
INNER JOIN dem_devis e ON l.societe=e.societe AND l.no_id=e.no_id INNER JOIN dem_devis e ON l.societe=e.societe AND l.no_id=e.no_id
WHERE l.datevi >= :datedeb AND l.liste=:itc ORDER BY l.datevi, l.heurevi WHERE l.datevi >= :datedeb AND l.liste=:itc ORDER BY l.datevi, l.heurevi
""" """
@@ -80,20 +58,36 @@ def delete_rdv(request, nodossier, nolig):
query = "DELETE FROM dem_lig where societe = '%s' and no_id=%s and nolig=%s;" % (societe, no_id, nolig) query = "DELETE FROM dem_lig where societe = '%s' and no_id=%s and nolig=%s;" % (societe, no_id, nolig)
execute_query(request, query, {}) execute_query(request, query, {})
def update_rdv(request, nodossier, nolig, comment, commentvi, date_rdv): def update_rdv(request, nodossier, nolig, new_values):
societe = nodossier[0:2] societe = nodossier[0:2]
no_id = nodossier[3:] no_id = nodossier[3:]
# formater les champs # formater date et heure de visite
ddate = datetime.strptime(date_rdv, '%d-%m-%Y %H:%M') if new_values['rdv_debut']:
datevi = ddate.strftime("%Y-%m-%d") ddate = datetime.strptime(new_values['rdv_debut'], '%d-%m-%Y %H:%M')
heurevi = date_rdv[-5:] new_values['DATEVI'] = ddate.strftime("%Y-%m-%d")
auj = date.today().strftime("%Y-%m-%d") new_values['HEUREVI'] = ddate.strftime("%H:%M")
if nolig == '0': del new_values['rdv_debut']
query = "INSERT INTO dem_devis SET societe='%s',no_id=%s,date='%s',datevi='%s',heurevi='%s',comment='%s',commentvi='%s'" % (societe, no_id,auj,datevi, heurevi, comment, commentvi) s = ''
for param in new_values.keys():
if s:
s += ",%s=:%s" % (param, param)
else: else:
query = "UPDATE dem_ligs SET datevi='%s', heurevi='%s', comment='%s', commentvi='%s' where societe = '%s' and no_id=%s and nolig=%s;" % (datevi, heurevi, comment, commentvi, societe, no_id, nolig) s = "%s=:%s" % (param, param)
execute_query(request, query, {}) new_values['societe'] = societe
new_values['no_id'] = no_id
new_values['nolig'] = nolig
query = "UPDATE dem_lig SET %s WHERE societe = :societe AND NO_ID = :no_id AND NOLIG = :nolig ;" % s
execute_query(request, query, new_values)
def create_rdv(request, nodossier, dateRDV, heureRDV, type_rdv, agenda, logged_in):
societe = nodossier[0:2]
no_id = nodossier[3:]
query = """
INSERT INTO dem_lig (societe, NO_ID, DATE, COMMENT, DATEVI, HEUREVI, LISTE, USERMAJ) VALUES
(:societe, :no_id, CURRENT_DATE, :type_rdv, :dateRDV, :heureRDV, :agenda, :logged_in) ;"""
execute_query(request, query, {'societe': societe, 'no_id' :no_id, 'dateRDV': dateRDV, 'heureRDV': heureRDV, 'type_rdv': type_rdv, 'agenda': agenda, 'logged_in':logged_in})

View File

@@ -35,25 +35,24 @@ def get_member_by_id(request, mbr_id):
return results return results
def update_membre_mdp_oublie(request, login): def update_membre_mdp_oublie(request, login):
import base64
import uuid
# get a UUID - URL safe, Base64 # get a UUID - URL safe, Base64
r_uuid = base64.urlsafe_b64encode(uuid.uuid4().bytes)
r_uuid = r_uuid.replace('=', '') uid = uuid.uuid1()
query = "UPDATE p_users SET mdp_oublie=:r_uuid, mdp_oublie_date=now() WHERE CD_UTI=:login;" urlslug = base64.urlsafe_b64encode(uid.bytes).decode("utf-8").rstrip('=\n').replace('/', '_')
execute_query(request, query, {'r_uuid':r_uuid, 'login':login}) query = "UPDATE p_users SET mdp_oublie=:urlslug, mdp_oublie_date=now() WHERE CD_UTI=:login;"
return r_uuid execute_query(request, query, {'urlslug':urlslug, 'login':login})
return urlslug
def update_membre_mdp(request, login, password): def update_membre_mdp(request, login, password):
"""Update password for member login""" """Update password for member login"""
query = "UPDATE p_users SET mdp = SHA1(:password), mdp_oublie=NULL, mdp_oublie_date=NULL WHERE cd_uti=:login;" query = "UPDATE p_users SET mdp = SHA1(:password), mdp_oublie=NULL, mdp_oublie_date=NULL WHERE cd_uti=:login;"
execute_query(request, query, {'login': login, 'password': password}) execute_query(request, query, {'login': login, 'password': password})
def update_last_connection(request, login): def update_last_connection(request, login, ua_string):
"""Update last connection for login """ """Update last connection for login """
query = "UPDATE p_users SET dern_cnx_le=NOW() WHERE cd_uti=:login;" query = "UPDATE p_users SET dern_cnx_le=NOW(), ua_string=:ua_string WHERE cd_uti=:login;"
execute_query(request, query, {'login': login}) execute_query(request, query, {'login': login, 'ua_string': ua_string})
def update_membre(request, cd_uti, new_values): def update_membre(request, cd_uti, new_values):
# formater les champs # formater les champs
@@ -81,9 +80,3 @@ def delete_membre(request, cd_uti):
query = "DELETE FROM p_users WHERE cd_uti = :cd_uti ;" query = "DELETE FROM p_users WHERE cd_uti = :cd_uti ;"
execute_query(request, query, {'cd_uti': cd_uti}) execute_query(request, query, {'cd_uti': cd_uti})
def get_chantiers_byName(request, societe, name, tous):
query = "CALL spGET_CHANTIERS_byName('%s','%s');" % (societe, name)
results = request.dbsession.execute(query).fetchall()
return results

161
mondumas/models/dossier.py Normal file
View File

@@ -0,0 +1,161 @@
# -*- coding: utf8 -*-
from sqlalchemy import text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
scoped_session,
sessionmaker,
)
from zope.sqlalchemy import (
ZopeTransactionExtension,
mark_changed
)
from datetime import *
import transaction
def execute_query(request, query, params):
"""Execute query and mark session as changed"""
request.dbsession.execute(query, params)
mark_changed(request.dbsession)
transaction.commit()
def get_chantiers_byName(request, societe, name, tous):
query = "CALL spGET_CHANTIERS_byName('%s','%s');" % (societe, name)
results = request.dbsession.execute(query).fetchall()
return results
def get_dossier_by_no(request,nodossier):
societe = nodossier[0:2]
no_id = nodossier[3:]
query = """
SELECT d.*, c.*, a.NOM as nom_cabinet, e.NOM as nom_expert FROM dem_devis d
INNER JOIN clients c ON d.societe = c.societe and d.cd_cli = c.cd_cli
INNER JOIN p_cabinet a ON d.cabinet = a.code
INNER JOIN p_experts e ON d.cabinet = e.code_cab and d.expert = e.code_exp
where d.societe = '%s' and d.no_id=%s;""" % (societe, no_id);
results = request.dbsession.execute(query).first()
return results
def get_devis_by_no(request,nodossier):
societe = nodossier[0:2]
type_doc = nodossier[3:5]
no_id = nodossier[5:]
if type_doc == 'DE':
query = """
SELECT d.*, c.*, a.NOM as nom_cabinet, e.NOM as nom_expert FROM devis d
INNER JOIN clients c ON d.societe = c.societe and d.cd_cli = c.cd_cli
INNER JOIN p_cabinet a ON d.cabinet = a.code
INNER JOIN p_experts e ON d.cabinet = e.code_cab and d.expert = e.code_exp
WHERE d.societe = :societe and d.no_id=:no_id;"""
elif type_doc == 'FA':
query = """
SELECT d.*, c.*, a.NOM as nom_cabinet, e.NOM as nom_expert FROM facture d
INNER JOIN clients c ON d.societe = c.societe and d.cd_cli = c.cd_cli
INNER JOIN p_cabinet a ON d.cabinet = a.code
INNER JOIN p_experts e ON d.cabinet = e.code_cab and d.expert = e.code_exp
WHERE d.societe = :societe and d.no_id=:no_id;"""
else:
query = """
SELECT d.*, c.*, a.NOM as nom_cabinet, e.NOM as nom_expert FROM proforma d
INNER JOIN clients c ON d.societe = c.societe and d.cd_cli = c.cd_cli
INNER JOIN p_cabinet a ON d.cabinet = a.code
INNER JOIN p_experts e ON d.cabinet = e.code_cab and d.expert = e.code_exp
WHERE d.societe = :societe and d.no_id=:no_id;"""
results = request.dbsession.execute(query, {'societe': societe, 'no_id': no_id}).first()
return results
def get_dossier_rdv_by_no(request,nodossier, nolig):
societe = nodossier[0:2]
no_id = nodossier[3:]
if nolig == '0':
query = "SELECT * FROM dem_lig WHERE societe = :societe AND no_id = :no_id;"
results = request.dbsession.execute(query, {'societe': societe, 'no_id': no_id}).fetchall()
else:
query = """
SELECT l.*, d.C_QUALITE, d.C_NOM FROM dem_lig l INNER JOIN dem_devis d ON l.societe = d.societe and l.no_id = d.no_id
where l.societe = '%s' and l.no_id=%s and l.nolig=%s;""" % (societe, no_id, nolig)
results = request.dbsession.execute(query).first()
return results
def get_documents_byChantier(request,nodossier):
societe = nodossier[0:2]
no_id = nodossier[3:]
query = "CALL spGET_DOSSIERS_byNumeo('%s',%s);" % (societe, no_id)
results = request.dbsession.execute(query).fetchall()
return results
def update_suivi(request, nodossier, nolig, new_values):
societe = nodossier[0:2]
no_id = nodossier[3:]
new_values['societe'] = societe
new_values['NO_ID'] = no_id
s = ''
for param in new_values.keys():
if s:
s += ",%s=:%s" % (param, param)
else:
s = "%s=:%s" % (param, param)
if nolig == '0':
query = "INSERT INTO dem_lig SET %s" % s
else:
new_values['nolig'] = nolig
query = "UPDATE dem_lig SET %s WHERE societe = :societe AND NO_ID = :no_id AND NOLIG = :nolig ;" % s
execute_query(request, query, new_values)
def get_similaires_byChantier(request, societe, C_NOM, C_ADR, C_CP, C_VILLE):
query = """
SELECT CONCAT(societe,'-',NO_ID) AS nodossier, dem_devis.* FROM dem_devis
WHERE societe<>:societe AND C_NOM=:C_NOM AND C_ADR=:C_ADR AND C_CP=:C_CP AND C_VILLE=:C_VILLE;"""
results = request.dbsession.execute(query, {'societe': societe, 'C_NOM': C_NOM, 'C_ADR': C_ADR, 'C_CP': C_CP, 'C_VILLE': C_VILLE}).fetchall()
return results
def get_devis_lig_by_no(request,nodossier):
societe = nodossier[0:2]
type_doc = nodossier[3:5]
no_id = nodossier[5:]
if type_doc == 'DE':
query = "SELECT * FROM devis_lig WHERE societe = :societe and no_id=:no_id;"
elif type_doc == 'FA':
query = "SELECT * FROM facture_lig WHERE societe = :societe and no_id=:no_id;"
else:
query = "SELECT * FROM proforma_lig WHERE societe = :societe and no_id=:no_id;"
results = request.dbsession.execute(query, {'societe': societe, 'no_id': no_id}).fetchall()
return results
def get_docs_attaches(request, nomrep, nodossier):
societe = nodossier[0:2]
nochantier = int(nodossier[3:])
query = "SELECT * FROM dossier_attaches WHERE nomrep = :nomrep AND societe = :societe AND nochantier = :nochantier ORDER BY cree_le;"
results = request.dbsession.execute(query, {'nomrep': nomrep, 'societe': societe, 'nochantier': nochantier}).fetchall()
return results
def update_dossier(request, nodossier, new_values):
societe = nodossier[0:2]
nochantier = int(nodossier[3:])
s = ''
for param in new_values.keys():
if s:
s += ",%s=:%s" % (param, param)
else:
s = "%s=:%s" % (param, param)
new_values['societe'] = societe
new_values['nochantier'] = nochantier
query = u"UPDATE dem_devis SET %s WHERE societe=:societe AND no_id=:nochantier" % s
execute_query(request, query, new_values)

View File

@@ -32,3 +32,25 @@ def get_last_emailing(request):
results = request.dbsession.execute(query, {}) results = request.dbsession.execute(query, {})
return results.fetchall() return results.fetchall()
def get_orphans_DE(request, societe):
query = "SELECT * FROM devis WHERE societe = '%s' AND nochantier = 0 ORDER BY date desc LIMIT 50 ;" % (societe)
results = request.dbsession.execute(query).first()
return results
def get_dossiers_byChantier(request, societe, name):
query = "CALL spGET_DOSSIERS_byChantier('%s','%s','%s');" % (societe, 'DE', name.replace("'","''"))
results = request.dbsession.execute(query).fetchall()
return results
def update_nochantier(request, societe, nodossier, nochantier):
x = nodossier.split('-')
type = x[0]
no_id = int(x[1])
if type == 'DE':
query = "UPDATE devis SET nochantier = :nochantier WHERE societe = :societe and no_id = :no_id;"
else:
query = "UPDATE facture SET nochantier = :nochantier WHERE societe = :societe and no_id = :no_id;"
execute_query(request, query, {'societe': societe, 'no_id': no_id, 'nochantier': nochantier})

View File

@@ -1,19 +1,29 @@
def includeme(config): def includeme(config):
config.add_static_view('static', 'static', cache_max_age=3600) config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/') # agenda
config.add_route('agenda', '/agenda') config.add_route('agenda', '/agenda/{date}')
config.add_route('planning', '/planning') config.add_route('planning', '/planning/{date}')
config.add_route('chantier_lookup', '/chantier_lookup')
config.add_route('changer_mdp', '/changer_mdp')
config.add_route('dossier_view', '/dossier_view/{nodossier}')
config.add_route('rdv_edit','/rdv_edit/{nodossier}/{nolig}') config.add_route('rdv_edit','/rdv_edit/{nodossier}/{nolig}')
# default
config.add_route('home', '/')
config.add_route('changer_mdp', '/changer_mdp')
config.add_route('envoyer_mdp', '/envoyer_mdp') config.add_route('envoyer_mdp', '/envoyer_mdp')
config.add_route('login', '/login') config.add_route('login', '/login')
config.add_route('logout', '/logout') config.add_route('logout', '/logout')
config.add_route('redefinir_mdp', '/redefinir_mdp/{lien}') config.add_route('redefinir_mdp', '/redefinir_mdp/{lien}')
config.add_route('suivi_edit','/suivi_edit/{nodossier}/{nolig}')
# dossier
config.add_route('dossier_edit', '/dossier_edit/{nodossier}')
config.add_route('dossier_lookup', '/chantier_lookup')
config.add_route('dossier_select', '/dossier_select/{date}')
config.add_route('dossier_selected', '/dossier_selected/{goto}/{date}/{nodossier}')
config.add_route('dossier_view', '/dossier_view/{nodossier}')
config.add_route('devis_view', '/devis_view/{nodossier}')
# parametres # parametres
config.add_route('parametres', '/parametres') config.add_route('parametres', '/parametres')
config.add_route('dashboard', '/dashboard') config.add_route('dashboard', '/dashboard')
config.add_route('last_emailing', '/last_emailing') config.add_route('last_emailing', '/last_emailing')
config.add_route('orphans_de', '/orphans_de/{societe}')
config.add_route('user_edit', '/user_edit/{cd_uti}') config.add_route('user_edit', '/user_edit/{cd_uti}')
config.add_route('users_list', '/users_list') config.add_route('users_list', '/users_list')
config.add_route('users_ua', '/users_ua')

View File

@@ -46,6 +46,14 @@
color: #000000 !important; color: #000000 !important;
} }
.modal-dialog {
position: absolute;
margin-left: 200px;
height: 500px;
top: 80px;
}
#footer { #footer {
text-align: center; text-align: center;
color: #428BCA; color: #428BCA;
@@ -97,3 +105,23 @@
.logo-small { .logo-small {
font-size: 50px; font-size: 50px;
} }
.bg-PE {
background-color: #ffffb3 !important;
color: black;
}
.bg-ME {
background-color: #ffe44d !important;
color: black;
}
.bg-PL {
background-color: #b3ff66 !important;
color: black;
}
.bg-PO {
background-color: #b1dae7 !important;
color: black;
}
.bg-CD {
background-color: #ffb3cc !important;
color: black;
}

View File

@@ -0,0 +1,5 @@
-- Windows 10, lecteur local
mklink /J DEVFAC14 C:\DEVFAC14
-- Windows server, lecteur r<>seau
mklink /D DEVFAC14 \\SRVTSE\DEVFAC14

View File

@@ -1,14 +1,12 @@
<metal:block use-macro="main_template"> <metal:block use-macro="main_template">
<div metal:fill-slot="content"> <div metal:fill-slot="content">
<div class="container"> <div class="container">
<div class="alert alert-warning" tal:condition="message" tal:content="message" />
<div class="form-group">
<div class="row"> <div class="row">
<form method="POST" id="frm"> <form method="POST" id="frm" class="form-horizontal">
<div class="col-md-2"> <div class="form-group">
<a class="btn btn-default" role="button" href="/">
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
</div>
<div class="col-md-4"> <div class="col-md-4">
<select class="form-control" id="agenda" name="agenda" onChange="$('#frm').submit()"> <select class="form-control" id="agenda" name="agenda" onChange="$('#frm').submit()">
<div tal:repeat="item agendas"> <div tal:repeat="item agendas">
@@ -16,40 +14,122 @@
</div> </div>
</select> </select>
</div> </div>
<label class="control-label col-md-2">Dossier en cours :</label>
<div class="col-md-6"> <div class="col-md-6">
<p> <div class="input-group">
<span class="label" style="background-color:LightYellow; color:black;">RDV Peinture</span>&nbsp; <input class="form-control" type="text" name="dossier" value="${mem_nodossier}&nbsp;&nbsp;|&nbsp;&nbsp;${mem_nomdossier}" readonly />
<span class="label" style="background-color:Gold; color:black;">RDV Menuiserie</span>&nbsp; <div class="input-group-btn">
<span class="label" style="background-color:LightGreen; color:black;">RDV Plomberie</span>&nbsp; <a href="${url_select}" class="btn btn-primary">
<span class="label" style="background-color:LightBlue; color:black;">RDV Plomberie</span>&nbsp; <span class="glyphicon glyphicon-search"></span></a>
</p> </div>
</div>
</div>
</div> </div>
</form> </form>
</div> </div>
</div>
</div>
<br /> <br />
<div class="container"> <div class="container">
<div id="calendar"></div> <div id="calendar"></div>
</div> </div>
<br /> <br />
<p align="center">
<span class="label bg-PE">RDV Peinture</span>&nbsp;
<span class="label bg-ME">RDV Menuiserie</span>&nbsp;
<span class="label bg-PL">RDV Plomberie</span>&nbsp;
<span class="label bg-PO">RDV Polynet</span>&nbsp;
<span class="label bg-CD">RDV Couleurs & Déco</span>&nbsp;
</p>
<br /> <br />
<!-- Modal : Confirmation CREATION -->
<div class="modal fade" id="confirmCreate" role="dialog" aria-labelledby="confirmCreateLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Créer un rendez-vous pour ${agenda}</h4>
</div>
<div class="modal-body">
<!-- The form is placed inside the body of modal -->
<form id="create_rdv-form" class="form-horizontal" action="${url}" method="post"
data-fv-framework="bootstrap"
data-fv-icon-valid="glyphicon glyphicon-ok"
data-fv-icon-invalid="glyphicon glyphicon-remove"
data-fv-icon-validating="glyphicon glyphicon-refresh">
<p>
Voulez-vous créer un rendez-vous avec : <br />
</p>
<div class="form-group">
<div class="col-xs-offset-2 col-xs-8">
<p class="text-danger"><b>${mem_nodossier} - ${mem_nomdossier}</p>
<p>le <span id=dateheureRDV>date</p>
</div>
</div>
<input type="hidden" name="dateRDV" id=dateRDV value="date">
<input type="hidden" name="heureRDV" id=heureRDV value="heure">
<div class="form-group">
<div class="col-xs-offset-2 col-xs-8">
<label>Motif :</label>
<select class="form-control" id="type_rdv" name="type_rdv">
<div tal:repeat="item types_rdv">
<option value="${item.LIB}" tal:attributes="selected type_rdv==item.LIB and 'selected' or None">${item.LIB}</option>
</div>
</select>
</div>
</div>
<div class="form-group">
<div class="col-xs-5 col-xs-offset-4">
<button type="submit" class="btn btn-danger" name="form.submitted"
tal:condition="mem_nodossier != 'Aucun'">Créer</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
var datePlan = '${datePlan}';
$('#calendar').fullCalendar({ $('#calendar').fullCalendar({
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
locale: 'fr', locale: 'fr',
header: { header: {
left: 'agendaDay agendaWeek month listMonth', left: 'agendaDay agendaWeek month listMonth',
center: 'prev title next', center: 'prev title next',
right: 'today' right: 'today'
}, },
allDaySlot: false,
defaultView: 'agendaWeek', defaultView: 'agendaWeek',
defaultDate: moment(datePlan),
weekends: false, weekends: false,
height: 'auto', height: 'auto',
minTime: "07:00:00", minTime: "07:00:00",
maxTime: "21:00:00", maxTime: "20:00:00",
events:${fullcalendar_events}, events:${fullcalendar_events},
eventRender: function(event, element){
element.find('.fc-title').append("<br/>" + event.description);
},
dayClick: function(date, jsEvent, view) {
$('#dateheureRDV').html(moment(date).format('dddd DD MMMM à HH:mm'));
$('#dateRDV').attr('value', moment(date).format('YYYY-MM-DD'));
$('#heureRDV').attr('value', moment(date).format('HH:mm'));
$("#confirmCreate").modal("show");
}
});
$('#create_rdv-form').formValidation({
framework: 'bootstrap',
excluded: ':disabled',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
}); });
}); });
</script> </script>

View File

@@ -1,30 +1,22 @@
<metal:block use-macro="main_template"> <metal:block use-macro="main_template">
<div metal:fill-slot="content"> <div metal:fill-slot="content">
<div class="container"> <div class="container">
<div class="form-group">
<div class="row">
<div class="col-md-2">
<a class="btn btn-primary" role="button" href="/">
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
</div>
<div class="col-md-5">
<p>
<span class="label" style="background-color:LightYellow; color:black;">RDV Peinture</span>&nbsp;
<span class="label" style="background-color:Gold; color:black;">RDV Menuiserie</span>&nbsp;
<span class="label" style="background-color:LightGreen; color:black;">RDV Plomberie</span>&nbsp;
<span class="label" style="background-color:LightBlue; color:black;">RDV Plomberie</span>&nbsp;
</p>
</div>
</div>
</div>
</div>
<br /> <br />
<div class="container"> <div class="container">
<div id="calendar"></div> <div id="calendar"></div>
</div> </div>
<br /> <br />
<p align="center">
<span class="label bg-PE">RDV Peinture</span>&nbsp;
<span class="label bg-ME">RDV Menuiserie</span>&nbsp;
<span class="label bg-PL">RDV Plomberie</span>&nbsp;
<span class="label bg-PO">RDV Polynet</span>&nbsp;
<span class="label bg-CD">RDV Couleurs & Déco</span>&nbsp;
</p>
<br /> <br />
<br />
</div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
@@ -32,7 +24,7 @@ $(document).ready(function() {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
defaultView: 'timelineDay', defaultView: 'timelineDay',
minTime: "07:00:00", minTime: "07:00:00",
maxTime: "21:00:00", maxTime: "20:00:00",
height: 'auto', height: 'auto',
locale: 'fr', locale: 'fr',
header: { header: {

View File

@@ -11,9 +11,15 @@
data-fv-icon-validating="glyphicon glyphicon-refresh"> data-fv-icon-validating="glyphicon glyphicon-refresh">
<div class="form-group"> <div class="form-group">
<label class="col-xs-2 control-label" for="date_rdv">Date et heure</label> <label class="control-label col-xs-2">No dossier</label>
<div class="col-xs-9">
<span class="form-control-static text-danger">${nodossier}&nbsp;&nbsp;|&nbsp;&nbsp;${rdv.C_QUALITE} ${rdv.C_NOM}</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2" for="date_rdv_picker">Date et heure</label>
<div class="col-xs-3 input-group date" id="date_rdv_picker"> <div class="col-xs-3 input-group date" id="date_rdv_picker">
<input class="form-control" type="text" name="date_rdv" value="${date_rdv.strftime('%d-%m-%Y %H:%M')}" <input class="form-control" type="text" name="rdv_debut" value="${rdv.rdv_debut.strftime('%d-%m-%Y %H:%M')}"
data-fv-notempty="true" data-fv-notempty="true"
data-fv-notempty-message="La date et l'heure sont obligatoires" data-fv-notempty-message="La date et l'heure sont obligatoires"
data-fv-date="true" data-fv-date="true"
@@ -26,38 +32,36 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-xs-2" for="comment">Commentaire 1</label> <label class="control-label col-xs-2" for="COMMENT">Commentaire</label>
<div class="col-xs-5"> <div class="col-xs-10">
<input class="form-control" type="text" id="comment" name="comment" value="${comment}" <input class="form-control" type="text" id=".COMMENT" name="COMMENT" value="${rdv.COMMENT}"
placeholder="30 caractères maximum" placeholder="65 caractères maximum"
data-fv-notempty="true" data-fv-notempty="true"
data-fv-notempty-message="Un commentaire est obligatoire" data-fv-notempty-message="Un commentaire est obligatoire"
data-fv-stringlength="true" data-fv-stringlength="true"
data-fv-stringlength-max="30" data-fv-stringlength-max="65"
data-fv-stringlength-message="30 caractères maximum" /> data-fv-stringlength-message="65 caractères maximum" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2" for="commentvi">Commentaire 2</label>
<div class="col-xs-5">
<input class="form-control" type="text" id="commentvi" name="commentvi" value="${commentvi}"
placeholder="30 caractères maximum"
data-fv-stringlength="true"
data-fv-stringlength-max="30"
data-fv-stringlength-message="30 caractères maximum" />
</div> </div>
</div> </div>
<div class="form-group">
<label class="control-label col-xs-2">Dern. modif le</label>
<div class="col-xs-9">
<p class="form-control-static">${rdv.DATEMAJ.strftime('%d-%m-%Y %H:%M')} par ${rdv.USERMAJ}</p>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="col-xs-offset-2 col-xs-10"> <div class="col-xs-offset-2 col-xs-10">
<div class="form-group"> <div class="form-group">
<a class="btn btn-default" href="${request.route_url('dossier_view', nodossier=nodossier)}"> <a class="btn btn-default" href="/agenda/${rdv.rdv_debut.strftime('%Y-%m-%d')}">
<span class="glyphicon glyphicon-arrow-left"></span> Annuler</a> <span class="glyphicon glyphicon-arrow-left"></span> Annuler</a>
<button class="btn btn-primary" type="submit" name="form.submitted"> <button class="btn btn-primary" type="submit" name="form.submitted">
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button> <span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
<button class="btn btn-warning" type="submit" name="form.deleted" <button class="btn btn-danger" type="submit" name="form.deleted"
tal:condition="python: nolig != '0'"> tal:condition="nolig != '0' and logged_in.upper()==rdv.USERMAJ.upper()">
<span class="glyphicon glyphicon-remove"></span> Supprimer</button> <span class="glyphicon glyphicon-remove"></span> Supprimer</button>
<a class="btn btn-warning" href="${request.route_url('dossier_view', nodossier=nodossier)}">
<span class="glyphicon glyphicon-folder-open"></span> Dossier</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -8,7 +8,7 @@
<p> <p>
Pour des raisons de sécurité, nous gardons votre mot de passe chiffré, et nous ne pouvons pas vous l'envoyer. Pour des raisons de sécurité, nous gardons votre mot de passe chiffré, et nous ne pouvons pas vous l'envoyer.
Si vous souhaitez ré-initialiser votre mot de passe, remplissez le formulaire ci-dessous et nous vous enverrons un email pour démarrer la phase de ré-initialisation de votre mot de passe. </p> Si vous souhaitez ré-initialiser votre mot de passe, remplissez le formulaire ci-dessous et nous vous enverrons un email pour démarrer la phase de ré-initialisation de votre mot de passe. </p>
<br /> OK <br />
<form id="email_login-form" role="form" action="${url}" method="post"> <form id="email_login-form" role="form" action="${url}" method="post">
<div class="form-group"> <div class="form-group">
<label class="control-label" for="login">Mon identifiant</label> <label class="control-label" for="login">Mon identifiant</label>

View File

@@ -5,19 +5,19 @@
<br /> <br />
<div class="row"> <div class="row">
<div class="col-sm-3"> <div class="col-sm-3">
<a href="${request.application_url}/agenda"> <a href="${request.application_url}/agenda/today">
<span class="glyphicon glyphicon-calendar logo-small"></span><br /> <span class="glyphicon glyphicon-calendar logo-small"></span><br />
<h4>MON AGENDA</h4></a> <h4>MON AGENDA</h4></a>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<a href="${request.application_url}/planning"> <a href="${request.application_url}/planning/today">
<span class="glyphicon glyphicon-calendar logo-small"></span><br /> <span class="glyphicon glyphicon-calendar logo-small"></span><br />
<h4>PLANNING</h4></a> <h4>PLANNING</h4></a>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<a href="${request.application_url}/chantier_lookup"> <a href="${request.application_url}/chantier_lookup">
<span class="glyphicon glyphicon-search logo-small"></span> <span class="glyphicon glyphicon-search logo-small"></span>
<h4>RECH. CHANTIER</h4></a> <h4>RECH. DOSSIER</h4></a>
</div> </div>
</div> <!-- row 1 --> </div> <!-- row 1 -->
<br /> <br />

View File

@@ -0,0 +1,120 @@
<metal:block use-macro="main_template">
<div metal:fill-slot="content">
<br />
<!-- ENTETE -->
<div class="row">
<!-- CHANTIER -->
<div class="col-md-6">
<table class="table table-condensed">
<tr>
<td><h4>CHANTIER</h4></td>
<td>
<h4>${dossier.C_QUALITE} ${dossier.C_NOM}</h4>
${dossier.C_ADR}<br />
<span tal:condition="dossier.C_ADR2">${dossier.C_ADR2}<br /></span>
${dossier.C_CP} ${dossier.C_VILLE}<br />
</td>
</tr>
<tr>
<td>
Etage - Code<br />
Tél. domicile - prof.<br />
Tél. mobile - fax
</td>
<td>
${dossier.C_ETAGE} - ${dossier.C_CODE}<br />
${dossier.C_TEL1} - ${dossier.C_TEL2}<br />
${dossier.C_TELP} - ${dossier.C_FAX}
</td>
</tr>
<tr>
<td>
Cabinet<br />
Expert<br />
Référence expert
</td>
<td>
${dossier.nom_cabinet}<br />
${dossier.nom_expert}<br />
${dossier.REF_EXPERT}<br />
</td>
</tr>
<tr>
<td>
Police<br />
Sinistre<br />
Votre référence<br />
</td>
<td>
${dossier.NOPOL}<br />
${dossier.NOSIN}<br />
${dossier.VREF}<br />
</td>
</tr>
</table>
</div>
<!-- Mon compte -->
<div class="col-md-6 ${bg_color}">
<table class="table table-condensed ">
<tr>
<td><h4>CLIENT</h4></td>
<td>
<h4>${dossier.QUALITE} ${dossier.NOM}</h4>
${dossier.ADRESSE}<br />
<span tal:condition="dossier.ADRESSE2">${dossier.ADRESSE2}<br /></span>
${dossier.CP} ${dossier.VILLE}<br />
</td>
</tr>
<tr>
<td>
Responsable<br />
Tél. 1 - 2<br />
Tél. mobile - fax
</td>
<td>
${dossier.NOMRESP}<br />
${dossier.TEL1} - ${dossier.TEL2}<br />
${dossier.TELP} - ${dossier.FAX}
</td>
</tr>
</table>
</div>
<h4>Statut : ${dossier.STATUS}</h4>
</div> <!-- row -->
<!-- ENTETE DEVIS -->
<table class="table table-bordered table-condensed">
<tr>
<th class="text-right">Total HT</th>
<th class="text-right">Total TVA</th>
<th class="text-right">Total TTC</th>
<th class="text-right">TVA</th>
</tr>
<tr>
<td class="text-right">${layout.to_decz(dossier.TOTALHT)}</td>
<td class="text-right">${layout.to_euroz(dossier.TOTALTVA)}</td>
<td class="text-right">${layout.to_euroz(dossier.TOTALTTC)}</td>
<td class="text-right">${dossier.TAUXTVA} %</td>
</tr>
</table>
<table class="table table-bordered table-condensed">
<tr>
<th>Réf</th>
<th>Désignation</th>
<th class="text-right">Qté</th>
<th class="text-right">PU HT</th>
<th class="text-right">Montant HT</th>
</tr>
<tr tal:repeat="detail details">
<td>${detail.REF}</td>
<td>${detail.LIB}</td>
<td class="text-right">${layout.to_decz(detail.QTE)}</td>
<td class="text-right">${layout.to_euroz(detail.PRIXHT)}</td>
<td class="text-right">${layout.to_euroz(detail.MTHT)}</td>
<td class="text-center">${detail.USERMAJ}</td>
</tr>
</table>
</div>
</metal:block>

View File

@@ -0,0 +1,103 @@
<metal:block use-macro="main_template">
<div metal:fill-slot="content">
<div class="row">
<form id="change-dossier-details-form" class="form-horizontal" action="${url}" method="post" tal:condition="dossier"
data-fv-framework="bootstrap"
data-fv-icon-valid="glyphicon glyphicon-ok"
data-fv-icon-invalid="glyphicon glyphicon-remove"
data-fv-icon-validating="glyphicon glyphicon-refresh">
<div class="form-group">
<label class="col-xs-4 control-label">Adresse email élève</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_EMAIL"
value="${dossier.C_EMAIL}" placeholder="50 caractères maximum"
data-fv-emailaddress="true"
data-fv-emailaddress-message="L'adresse email n'est pas valide" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Etage</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_ETAGE"
value="${dossier.C_ETAGE}" placeholder="10 caractères maximum"
data-fv-stringlength="true"
data-fv-stringlength-max="10"
data-fv-stringlength-message="10 caractères maximum" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Code d'accès</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_CODE"
value="${dossier.C_CODE}" placeholder="20 caractères maximum"
data-fv-stringlength="true"
data-fv-stringlength-max="20"
data-fv-stringlength-message="20 caractères maximum" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Téléphone fixe</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_TEL1"
value="${dossier.C_TEL1}" placeholder="20 caractères maximum"
data-fv-phone="true"
data-fv-phone-country="FR"
data-fv-phone-message="Ce numéro de téléphone n'est pas vailde" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Téléphone prof.</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_TEL2"
value="${dossier.C_TEL2}" placeholder="20 caractères maximum"
data-fv-phone="true"
data-fv-phone-country="FR"
data-fv-phone-message="Ce numéro de téléphone n'est pas vailde" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Téléphone mobile</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_TELP"
value="${dossier.C_TELP}" placeholder="20 caractères maximum"
data-fv-phone="true"
data-fv-phone-country="FR"
data-fv-phone-message="Ce numéro de téléphone n'est pas vailde" />
</div>
</div>
<div class="form-group">
<label class="col-xs-4 control-label">Téléphone fax</label>
<div class="col-xs-8">
<input class="form-control" type="text" name="C_FAX"
value="${dossier.C_FAX}" placeholder="20 caractères maximum"
data-fv-phone="true"
data-fv-phone-country="FR"
data-fv-phone-message="Ce numéro de téléphone n'est pas vailde" />
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-4 col-xs-8">
<a class="btn btn-default" href="${request.application_url}/dossier_view/${nodossier}">
<span class="glyphicon glyphicon-chevron-left"></span> Annuler</a>
<button class="btn btn-primary" type="submit" name="form.submitted">
<span class="glyphicon glyphicon-ok"></span>&nbsp;Enregistrer</button>
</div>
</div>
</form>
</div> <!-- row -->
<br />
<br />
<script>
$(document).ready(function() {
$('#change-dossier-details-form').formValidation();
$('form input').on('keypress', function(e) {
return e.which !== 13;
});
});
</script>
</div>
</metal:block>

View File

@@ -73,6 +73,7 @@
<script type="text/javascript"> <script type="text/javascript">
var dataSet = ${dt_data}; var dataSet = ${dt_data};
var goto_url = '${goto_url}';
$(document).ready(function() { $(document).ready(function() {
$.fn.dataTable.moment('DD-MM-YYYY'); $.fn.dataTable.moment('DD-MM-YYYY');
@@ -87,7 +88,7 @@
{ "targets": 0, { "targets": 0,
"render": function (data, type, full, meta) { "render": function (data, type, full, meta) {
// ajouter un link vers le formulaire // ajouter un link vers le formulaire
return '<a href="/dossier_view/' + data + '">' + data + '</a>'; return '<a href="' + goto_url + data + '">' + data + '</a>';
}, },
}, },
] ]

View File

@@ -7,12 +7,18 @@
<div class="col-md-6"> <div class="col-md-6">
<table class="table table-condensed "> <table class="table table-condensed ">
<tr> <tr>
<td><h4>CHANTIER</h4></td> <td>
<h4>CHANTIER</h4>
<a href="${request.application_url}/dossier_edit/${nodossier}" class="btn btn-primary" role="button">
<span class="glyphicon glyphicon-pencil"></span>&nbsp;Modifier</a>
</td>
<td> <td>
<h4>${dossier.C_QUALITE} ${dossier.C_NOM}</h4> <h4>${dossier.C_QUALITE} ${dossier.C_NOM}</h4>
${dossier.C_ADR}<br /> ${dossier.C_ADR}<br />
<span tal:condition="dossier.C_ADR2">${dossier.C_ADR2}<br /></span> <span tal:condition="dossier.C_ADR2">${dossier.C_ADR2}<br /></span>
${dossier.C_CP} ${dossier.C_VILLE}<br /> ${dossier.C_CP} ${dossier.C_VILLE}<br />
<span tal:condition="len(dossier.C_EMAIL)">${dossier.C_EMAIL}</span>
<span tal:condition="len(dossier.C_EMAIL)==0" class="text-danger"><b>!!! Email vide !!!</b></span>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -54,8 +60,8 @@
</table> </table>
</div> </div>
<!-- Mon compte --> <!-- CLIENT -->
<div class="col-md-6 well"> <div class="col-md-6 ${bg_color}">
<table class="table table-condensed "> <table class="table table-condensed ">
<tr> <tr>
<td><h4>CLIENT</h4></td> <td><h4>CLIENT</h4></td>
@@ -83,59 +89,92 @@
<h4>Statut : ${dossier.STATUS}</h4> <h4>Statut : ${dossier.STATUS}</h4>
</div> <!-- row --> </div> <!-- row -->
<!-- PANEL DOSSIERS SIMILAIRES -->
<table class="table table-bordered table-condensed" tal:condition="similaires">
<tr>
<th>Dossier similaire</th>
<th>Date</th>
<th>Client</th>
<th class="text-right">Montant</th>
<th class="text-center">Statut</th>
</tr>
<tr tal:repeat="detail similaires">
<td>
<a href="/dossier_view/${detail.nodossier}">${detail.nodossier}</a>
</td>
<td>${detail.DATE.strftime('%d-%m-%Y')}</td>
<td class="bg-${detail.nodossier[0:2]}">${detail.NOMCLI}</td>
<td class="text-right">${layout.to_euro(detail.MTTRAV)}</td>
<td class="text-center">${detail.STATUS}</td>
</tr>
</table>
<div class="panel-group" id="accordion"> <div class="panel-group" id="accordion">
<!-- PANEL SUIVI --> <!-- PANEL SUIVI -->
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title"> <h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#panel-suivi"> <a data-toggle="collapse" data-parent="#accordion" href="#panel-suivi">
<span class="glyphicon glyphicon-arrow-down"></span>&nbsp;SUIVI</a> <span class="glyphicon glyphicon-plus"></span>&nbsp;SUIVI du DOSSIER</a>
</h4> </h4>
</div> </div>
<div id="panel-suivi" class="panel-collapse collapse"> <div id="panel-suivi" class="panel-collapse collapse">
<div class="panel-body"> <div class="panel-body">
<p><a class="btn btn-success" role="button" href="${request.route_url('rdv_edit', nodossier=nodossier, nolig='0')}"> <p>
<span class="glyphicon glyphicon-plus"></span> Nouvelle ligne</a></p> <a class="btn btn-success" role="button" href="${request.route_url('suivi_edit', nodossier=nodossier, nolig='0')}">
<table class="table table-bordered"> <span class="glyphicon glyphicon-plus"></span> Nouvelle ligne</a>
<a class="btn btn-warning" role="button" href="${request.route_url('rdv_edit', nodossier=nodossier, nolig='0')}">
<span class="glyphicon glyphicon-calendar"></span> Nouveau rendez-vous</a>
</p>
<table class="table table-bordered table-condensed">
<tr> <tr>
<th>Date</th> <th>Date</th>
<th>Action</th> <th>Action - commentaire</th>
<th class="text-right">Montant</th>
<th>Rendez-vous</th> <th>Rendez-vous</th>
<th>Réf. lettre</th>
<th class="text-center">Par</th> <th class="text-center">Par</th>
</tr> </tr>
<tr tal:repeat="detail details"> <tr tal:repeat="detail details">
<td>${detail.DATE.strftime('%d/%m/%Y')}</td> <td tal:condition="detail.DATEVI==None">
<a href="${request.route_url('suivi_edit', nodossier=nodossier, nolig=detail.NOLIG)}">
${detail.DATE.strftime('%d-%m-%Y')}</a>
</td>
<td tal:condition="detail.DATEVI!=None">
<a href="${request.route_url('rdv_edit', nodossier=nodossier, nolig=detail.NOLIG)}">
${detail.DATE.strftime('%d-%m-%Y')}</a>
</td>
<td tal:condition="detail.COMMENT.startswith('!!')" class="text-danger"> <td tal:condition="detail.COMMENT.startswith('!!')" class="text-danger">
<b>${detail.COMMENT} ${detail.COMMENTVI}</b> <b>${detail.COMMENT}</b>
</td> </td>
<td tal:condition="not detail.COMMENT.startswith('!!')"> <td tal:condition="not detail.COMMENT.startswith('!!')">
${detail.COMMENT} ${detail.COMMENTVI} ${detail.COMMENT}
</td> </td>
<td class="text-right">${layout.to_euroz(detail.montant)}</td>
<td> <td>
<span tal:condition="detail.rdv_debut==None"></span> <span tal:condition="detail.rdv_debut==None"></span>
<span tal:condition="detail.rdv_debut!=None"> <span tal:condition="detail.rdv_debut!=None">
<a href="${request.route_url('rdv_edit', nodossier=nodossier, nolig=detail.NOLIG)}"> ${detail.rdv_debut.strftime('%d-%m-%Y %H:%M')} avec ${detail.LISTE}
${detail.rdv_debut.strftime('%d/%m/%Y %H:%M')}</a>
avec ${detail.LISTE}
</span> </span>
</td> </td>
<td class="text-center">${detail.REF_LET}</td>
<td class="text-center">${detail.USERMAJ}</td> <td class="text-center">${detail.USERMAJ}</td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
<!-- PANEL SUIVI --> <!-- PANEL DOCUMENTS -->
<div class="panel panel-default"> <div class="panel panel-default" tal:condition="documents">
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title"> <h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#panel-documents"> <a data-toggle="collapse" data-parent="#accordion" href="#panel-documents">
<span class="glyphicon glyphicon-arrow-down"></span>&nbsp;DEVIS - FACTURES</a> <span class="glyphicon glyphicon-plus"></span>&nbsp;DEVIS - FACTURES</a>
</h4> </h4>
</div> </div>
<div id="panel-documents" class="panel-collapse collapse"> <div id="panel-documents" class="panel-collapse collapse">
<div class="panel-body"> <div class="panel-body">
<table class="table table-bordered"> <table class="table table-bordered table-condensed">
<tr> <tr>
<th>Numéro</th> <th>Numéro</th>
<th>Date</th> <th>Date</th>
@@ -144,8 +183,10 @@
<th class="text-center">Statut</th> <th class="text-center">Statut</th>
</tr> </tr>
<tr tal:repeat="detail documents"> <tr tal:repeat="detail documents">
<td>${detail.TYPE}-${detail.numero}</td> <td>
<td>${detail.date.strftime('%d-%m/-%Y')}</td> <a href="/devis_view/${detail.nodossier}">${detail.nodossier}</a>
</td>
<td>${detail.date.strftime('%d-%m-%Y')}</td>
<td>${detail.nomcli}</td> <td>${detail.nomcli}</td>
<td class="text-right">${layout.to_euro(detail.montant)}</td> <td class="text-right">${layout.to_euro(detail.montant)}</td>
<td class="text-center">${detail.status}</td> <td class="text-center">${detail.status}</td>
@@ -154,6 +195,34 @@
</div> </div>
</div> </div>
</div> </div>
<!-- PANEL DOCS ATTACHES -->
<div class="panel panel-default" tal:condition="docs_attaches">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#panel-attaches">
<span class="glyphicon glyphicon-plus"></span>&nbsp;DOCUMENTS ATTACHES</a>
</h4>
</div>
<div id="panel-attaches" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<div tal:repeat="detail docs_attaches">
<li>
<span class="glyphicon glyphicon-file" tal:condition="detail.nomfichier[-3:]=='pdf'"></span>
<span class="glyphicon glyphicon-picture" tal:condition="detail.nomfichier[-3:]=='jpg'"></span>
<a href="${docs_url}${detail.nomrep}/${detail.societe}/${detail.nomfichier}"
target="popup"
onclick="window.open('${docs_url}${detail.nomrep}/${detail.societe}/${detail.nomfichier},'popup','width=900,height=768'); return false;">
${detail.nomfichier}
</a>
&nbsp;-&nbsp;${detail.cree_le.strftime('%d-%m-%Y')}&nbsp;-&nbsp;${detail.taillefichier}
</li>
</div>
</ul>
</div>
</div>
</div>
</div> </div>

View File

@@ -0,0 +1,72 @@
<metal:block use-macro="main_template">
<div metal:fill-slot="content">
<div tal:condition="message" tal:content="message" class="alert alert-danger" />
<br />
<div class="row">
<form id="rdv_edit-form" class="form-horizontal" action="${url}" method="post"
data-fv-framework="bootstrap"
data-fv-icon-valid="glyphicon glyphicon-ok"
data-fv-icon-invalid="glyphicon glyphicon-remove"
data-fv-icon-validating="glyphicon glyphicon-refresh">
<div class="form-group">
<label class="control-label col-xs-2" for="comment">Commentaire</label>
<div class="col-xs-10">
<input class="form-control" type="text" id="COMMENT" name="COMMENT" value="${suivi.COMMENT}"
placeholder="65 caractères maximum"
data-fv-notempty="true"
data-fv-notempty-message="Un commentaire est obligatoire"
data-fv-stringlength="true"
data-fv-stringlength-max="65"
data-fv-stringlength-message="65 caractères maximum" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2">Dern. modif le</label>
<div class="col-xs-9">
<p class="form-control-static">${suivi.DATEMAJ.strftime('%d-%m-%Y %H:%M')} par ${suivi.USERMAJ}</p>
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-2 col-xs-10">
<div class="form-group">
<a class="btn btn-default" href="${request.route_url('dossier_view', nodossier=nodossier)}">
<span class="glyphicon glyphicon-arrow-left"></span> Annuler</a>
<button class="btn btn-primary" type="submit" name="form.submitted">
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
<button class="btn btn-danger" type="submit" name="form.deleted"
tal:condition="nolig != '0' and logged_in.upper()==suivi.USERMAJ">
<span class="glyphicon glyphicon-remove"></span> Supprimer</button>
</div>
</div>
</div>
</form>
<br />
<br />
<br />
</div> <!-- row -->
<script>
$(document).ready(function() {
$('#rdv_edit-form').formValidation();
$('#date_rdv_picker').datetimepicker({
format: 'DD-MM-YYYY HH:mm',
showClear: true,
allowInputToggle: true,
stepping: 15,
})
.on('changeDate', function(e) {
// Revalidate the date field
$('#rdv_edit-form').formValidation('revalidateField', 'date_rdv');
});
$('form input').on('keypress', function(e) {
return e.which !== 13;
});
});
</script>
</div>
</metal:block>

View File

@@ -14,6 +14,7 @@
<link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.min.css" rel="stylesheet"> <link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.min.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" rel="stylesheet"> <link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.18/css/dataTables.bootstrap.min.css" rel="stylesheet" media="all"> <link href="//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.18/css/dataTables.bootstrap.min.css" rel="stylesheet" media="all">
<link href="//gyrocode.github.io/jquery-datatables-checkboxes/1.2.11/css/dataTables.checkboxes.css" rel="stylesheet" />
<link href="${request.static_url('mondumas:static/dist/formvalidation/css/formValidation.min.css')}" rel="stylesheet"> <link href="${request.static_url('mondumas:static/dist/formvalidation/css/formValidation.min.css')}" rel="stylesheet">
<!-- Custom CSS --> <!-- Custom CSS -->
<link href="${request.static_url('mondumas:static/css/style.less')}" type="text/css" rel="stylesheet/less"> <link href="${request.static_url('mondumas:static/css/style.less')}" type="text/css" rel="stylesheet/less">
@@ -33,6 +34,7 @@
<!-- Datatable --> <!-- Datatable -->
<script src="//cdn.datatables.net/1.10.18/js/jquery.dataTables.min.js"></script> <script src="//cdn.datatables.net/1.10.18/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/1.10.18/js/dataTables.bootstrap.min.js"></script> <script src="//cdn.datatables.net/1.10.18/js/dataTables.bootstrap.min.js"></script>
<script src="//gyrocode.github.io/jquery-datatables-checkboxes/1.2.11/js/dataTables.checkboxes.min.js"></script>
<script src="//cdn.datatables.net/plug-ins/1.10.19/sorting/datetime-moment.js"></script> <script src="//cdn.datatables.net/plug-ins/1.10.19/sorting/datetime-moment.js"></script>
<!-- FormValidation plugin --> <!-- FormValidation plugin -->
<script src="${request.static_url('mondumas:static/dist/formvalidation/js/formValidation.min.js')}"></script> <script src="${request.static_url('mondumas:static/dist/formvalidation/js/formValidation.min.js')}"></script>
@@ -95,7 +97,8 @@
<div id="footer"> <div id="footer">
<div class="well"> <div class="well">
<p>© 2017&nbsp;-&nbsp;<a href="http://www.entreprise-dumas.com/" target="_blank">Entreprise Dumas</a></p> <p>© 2017&nbsp;-&nbsp;<a href="http://www.entreprise-dumas.com/" target="_blank">Entreprise Dumas, 49 Chemin du Bois 69140 RILLIEUX LA PAPE</a></p>
ggggggg
</div> </div>
</div> </div>

View File

@@ -0,0 +1,156 @@
<metal:block use-macro="main_template">
<div metal:fill-slot="content">
<div class="alert alert-danger" tal:condition="message" tal:content="message" />
<form method="POST" id="frm" class="form-horizontal">
<div class="form-group">
<label class="control-label col-xs-2" for="societe">Societe</label>
<div class="col-xs-6">
<select class="form-control" id="societe" name="societe" onChange="$('#frm').submit()">
<div tal:repeat="item societes">
<option value="${item}" tal:attributes="selected societe==item and 'selected' or None">${item}</option>
</div>
</select>
</div>
</div>
</form>
<!-- ENTETE -->
<div class="row">
<!-- CHANTIER -->
<div class="col-md-6">
<table class="table table-condensed ">
<tr>
<td><h4>CHANTIER</h4></td>
<td>
<h4>${devis.C_QUALITE} ${devis.C_NOM}</h4>
${devis.C_ADR}<br />
<span tal:condition="devis.C_ADR2">${devis.C_ADR2}<br /></span>
${devis.C_CP} ${devis.C_VILLE}<br />
</td>
</tr>
<tr>
<td>
Police<br />
Sinistre<br />
</td>
<td>
${devis.NOPOL}<br />
${devis.NOSIN}<br />
</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-condensed ">
<tr>
<td>
<h4>CLIENT</h4>
NO DEVIS<br />
DATE<br />
</td>
<td>
<h4>${devis.NOMCLI}</h4>
${devis.NO_ID}<br />
${devis.DATE.strftime('%d-%m-%Y')}
</td>
</tr>
</table>
</div>
</div> <!-- row -->
<form id="frm-nochantier" action="${url}" method="POST" class="form-horizontal">
<div class="form-group">
<label class="control-label col-xs-2" for="societe">No chantier</label>
<div class="col-xs-2">
<select class="form-control" id="nochantier" name="nochantier">
<div tal:repeat="item nochantiers">
<option value="${item}" tal:attributes="selected nochantier == item and 'selected' or None">${item}</option>
</div>
</select>
</div>
<div class="col-xs-8">
<button class="btn btn-primary" type="submit" name="form.nochantier">
<span class="glyphicon glyphicon-pencil"></span>&nbsp;MAJ No chantier</button>
&nbsp;&nbsp;(Veuillez cocher un ou plusieurs dossiers pour mettre à jour leur no de chantier)
</div>
</div>
</form>
<div class="row">
<table id="dossiers_list" class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Numéro</th>
<th>Date</th>
<th>Client</th>
<th>Chantier</th>
<th class="text-right">Montant</th>
<th>Sinistre</th>
<th class="text-center">Ch.</th>
</tr>
</thead>
</table>
<br />
<br />
</div>
<script type="text/javascript">
var dataSet = ${dt_data};
$(document).ready(function() {
$.fn.dataTable.moment('DD-MM-YYYY');
var table = $('#dossiers_list').DataTable({
data: dataSet,
pageLength: 20,
bLengthChange: false,
searching: false,
language: {
url: 'https://cdn.datatables.net/plug-ins/1.10.16/i18n/French.json'
},
columnDefs: [
{ className: "text-center", "targets": [0] },
{ className: "text-right", "targets": [5] },
{ 'targets': 0,
'checkboxes': {
'selectRow': true
}
},
],
select: {
'style': 'multi'
},
order: [[2, 'asc']],
createdRow: function( row, data, dataIndex ) {
if ( data[0].slice(0,2) == "DD" ) {
$('td', row).eq(7).css('background-color', 'Orange');
}
},
});
// Handle form submission event
$('#frm-nochantier').on('submit', function(e){
var form = this;
var rows_selected = table.column(0).checkboxes.selected();
// Iterate over all selected checkboxes
$.each(rows_selected, function(index, rowId){
// alert("row selected :"+ index + "rowId "+ rowId);
// Create a hidden element
$(form).append(
$('<input>')
.attr('type', 'hidden')
.attr('name', 'id' + index)
.val(rowId)
);
});
});
});
</script>
</div>
</metal:block>

View File

@@ -7,10 +7,18 @@
<a href="${request.application_url}/users_list"><span class="glyphicon glyphicon-user logo-primary"></span></a> <a href="${request.application_url}/users_list"><span class="glyphicon glyphicon-user logo-primary"></span></a>
<h4>UTILISATEURS</h4> <h4>UTILISATEURS</h4>
</div> </div>
<div class="col-sm-3">
<a href="${request.application_url}/users_ua"><span class="glyphicon glyphicon-log-in logo-primary"></span></a>
<h4>CONNEXIONS</h4>
</div>
<div class="col-sm-3"> <div class="col-sm-3">
<a href="${request.application_url}/dashboard"><span class="glyphicon glyphicon-dashboard logo-primary"></span></a> <a href="${request.application_url}/dashboard"><span class="glyphicon glyphicon-dashboard logo-primary"></span></a>
<h4>TABLEAU de BORD</h4> <h4>TABLEAU de BORD</h4>
</div> </div>
<div class="col-sm-3">
<a href="${request.application_url}/orphans_de/PE"><span class="glyphicon glyphicon-wrench logo-primary"></span></a>
<h4>DEVIS ORPHELINS</h4>
</div>
</div> </div>
<br /> <br />
<br /> <br />

View File

@@ -11,9 +11,9 @@
data-fv-icon-validating="glyphicon glyphicon-refresh"> data-fv-icon-validating="glyphicon glyphicon-refresh">
<div class="form-group"> <div class="form-group">
<label class="control-label col-xs-2" for="cd_uti">Identifiant</label> <label class="control-label col-xs-2" for="CD_UTI">Identifiant</label>
<div class="col-xs-2"> <div class="col-xs-2">
<input class="form-control" type="text" id="cd_uti" name="cd_uti" value="${individu.CD_UTI}" <input class="form-control" type="text" id="CD_UTI" name="CD_UTI" value="${individu.CD_UTI}"
placeholder="10 caractères maximum" placeholder="10 caractères maximum"
data-fv-notempty="true" data-fv-notempty="true"
data-fv-notempty-message="L'identifiant est obligatoire" data-fv-notempty-message="L'identifiant est obligatoire"
@@ -23,9 +23,9 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-xs-2" for="intitule">Nom et prénom</label> <label class="control-label col-xs-2" for="NOM">Nom et prénom</label>
<div class="col-xs-5"> <div class="col-xs-5">
<input class="form-control" type="text" id="intitule" name="nom" value="${individu.NOM}" <input class="form-control" type="text" id="NOM" name="NOM" value="${individu.NOM}"
placeholder="30 caractères maximum" placeholder="30 caractères maximum"
data-fv-notempty="true" data-fv-notempty="true"
data-fv-notempty-message="Le nom est obligatoire" data-fv-notempty-message="Le nom est obligatoire"
@@ -37,8 +37,8 @@
<div class="form-group"> <div class="form-group">
<label class="col-xs-2 control-label">Email</label> <label class="col-xs-2 control-label">Email</label>
<div class="col-xs-5"> <div class="col-xs-5">
<input class="form-control" type="text" name="email" <input class="form-control" type="text" name="email" value="${individu.email}"
value="${individu.email}" placeholder="55 caractères maximum" placeholder="55 caractères maximum"
data-fv-emailaddress="true" data-fv-emailaddress="true"
data-fv-emailaddress-message="L'adresse email n'est pas valide" /> data-fv-emailaddress-message="L'adresse email n'est pas valide" />
</div> </div>

View File

@@ -16,7 +16,6 @@
<th>Email</th> <th>Email</th>
<th>Agenda</th> <th>Agenda</th>
<th>Rôle</th> <th>Rôle</th>
<th>Dern cnx</th>
<th>Etat</th> <th>Etat</th>
</tr> </tr>
</thead> </thead>

View File

@@ -0,0 +1,46 @@
<metal:block use-macro="main_template">
<div metal:fill-slot="content">
<p>
<a href="${request.application_url}/" class="btn btn-default" role="button">
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
<a href="${request.application_url}/user_edit/0" class="btn btn-success" role="button">
<span class="glyphicon glyphicon-plus"></span> Nouveau utilisateur</a>
</p>
<table id="users_list_ua" class="table table-striped table-bordered">
<thead>
<tr>
<th>Dern cnx</th>
<th>Login</th>
<th>Nom, Prénom</th>
<th>Appareil utilisé</th>
</tr>
</thead>
</table>
<br />
<br />
<script type="text/javascript">
var dataSet = ${dt_data};
$(document).ready(function() {
$.fn.dataTable.moment('DD/MM/YYYY - HH:mm');
$('#users_list_ua').DataTable({
data: dataSet,
pageLength: 50,
bLengthChange: false,
language: {
url: 'https://cdn.datatables.net/plug-ins/1.10.16/i18n/French.json'
},
"order": [[ 0, "desc" ]]
});
});
</script>
</div><!-- content -->
</metal:block>

View File

@@ -1,11 +0,0 @@
from .models.default import get_member_by_id
def groupfinder(userid, request):
member = get_member_by_id(request, userid)
if member:
# Roles administrateur ?
if member.access == 9:
return ['group:administrators']
else:
return [] # it means that userid is logged in (it returns None if userid isn't logged in)

View File

@@ -21,87 +21,98 @@ from ..security import groupfinder
import json import json
from ..models.agenda import * from ..models.agenda import *
from ..models.default import * from ..models.dossier import *
@view_config(route_name='rdv_edit', renderer='../templates/agenda/rdv_edit.pt', permission='view') @view_config(route_name='rdv_edit', renderer='../templates/agenda/rdv_edit.pt', permission='view')
def rdv_edit(request): def rdv_edit(request):
logged_in = request.authenticated_userid.upper()
nodossier = request.matchdict['nodossier'] nodossier = request.matchdict['nodossier']
nolig = request.matchdict['nolig'] nolig = request.matchdict['nolig']
# creation d'un rdv ?
if nolig == '0':
# lire le user avec agenda
agenda = get_users_agenda(request, logged_in)
if agenda:
aujourdhui = datetime.now()
create_rdv(request, nodossier, aujourdhui.strftime("%Y-%m-%d"), aujourdhui.strftime("%H:00"), 'RDV DEVIS', logged_in, logged_in)
request.session.flash(u"Le rendez-vous a été CREE avec succès.", 'success')
else:
request.session.flash(u"Vous ne pouvez pas créer de rendez-vous.", 'danger')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
url = request.route_url("rdv_edit", nodossier=nodossier, nolig=nolig) url = request.route_url("rdv_edit", nodossier=nodossier, nolig=nolig)
message = '' message = ''
if nolig == '0':
# nouveau
comment = ''
commentvi = ''
date_rdv = datetime.now()
page_title= 'Nouveau rendez-vous'
else:
# lire le rendez-vous # lire le rendez-vous
rdv = get_dossier_rdv_by_no(request, nodossier, nolig) rdv = get_dossier_rdv_by_no(request, nodossier, nolig)
if not rdv: if not rdv:
request.session.flash(u"Rendez-vous non trouvé : %s" % nodossier, 'warning') request.session.flash(u"Rendez-vous non trouvé : %s" % nodossier, 'warning')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return HTTPFound(location=request.route_url('agenda', date='today'))
comment = rdv.COMMENT # memorize nodossier et nom dossier
commentvi = rdv.COMMENTVI request.session['mem_nodossier'] = nodossier
date_rdv = rdv.rdv_debut request.session['mem_nomdossier'] = '%s %s' % (rdv.C_QUALITE, rdv.C_NOM)
page_title= u"Modification du rdv du %s" % (rdv.rdv_debut.strftime('%d-%m-%Y %H:%M')) page_title= u"Modification du rdv du %s" % (rdv.rdv_debut.strftime('%d-%m-%Y %H:%M'))
if 'form.submitted' in request.params: if 'form.submitted' in request.params:
comment = request.params['comment'] new_values = {}
commentvi = request.params['commentvi'] for param, db_value in rdv.items():
date_rdv = request.params['date_rdv'] if param in request.params and request.params[param] != db_value:
new_values[param] = request.params[param]
update_rdv(request, nodossier, nolig, comment, commentvi, date_rdv) if new_values:
new_values['USERMAJ'] = logged_in.upper()
update_rdv(request, nodossier, nolig, new_values)
request.session.flash(u"Le rendez-vous a été mis à jour avec succès.", 'success') request.session.flash(u"Le rendez-vous a été mis à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
return HTTPFound(location=request.route_url('agenda', date=rdv.rdv_debut.strftime('%Y-%m-%d')))
if 'form.deleted' in request.params: if 'form.deleted' in request.params:
delete_rdv(request, nodossier, nolig) delete_rdv(request, nodossier, nolig)
request.session.flash(u"Le rendez-vous a été supprimé avec succès.", 'success') request.session.flash(u"Le rendez-vous a été supprimé avec succès.", 'success')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return HTTPFound(location=request.route_url('agenda', date=rdv.rdv_debut.strftime('%Y-%m-%d')))
return { return {
'page_title': page_title, 'page_title': page_title,
'url': url, 'url': url,
'logged_in': logged_in,
'nodossier': nodossier, 'nodossier': nodossier,
'nolig': nolig, 'nolig': nolig,
'comment': comment, 'rdv': rdv,
'commentvi': commentvi,
'date_rdv': date_rdv,
'message': message, 'message': message,
} }
@view_config(route_name='dossier_view', renderer='../templates/agenda/dossier_view.pt', permission='view')
def dossier_view(request):
nodossier = request.matchdict['nodossier']
url = request.route_url("dossier_view", nodossier=nodossier)
dossier = get_dossier_by_no(request, nodossier)
if dossier is None:
request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger')
return HTTPFound(location=request.route_url("chantier_lookup"))
# lire tous le suivi du dossier
details = get_dossier_rdv_by_no(request, nodossier, '0')
# lire toutes les dossiers du chantiers
documents = get_documents_byChantier(request, nodossier)
return {
'page_title': u"Dossier : %s" % (nodossier),
'nodossier': nodossier,
'dossier': dossier,
'details': details,
'documents': documents,
}
@view_config(route_name='agenda', renderer='../templates/agenda/agenda.pt', permission='view') @view_config(route_name='agenda', renderer='../templates/agenda/agenda.pt', permission='view')
def agenda(request): def agenda(request):
message = ''
# récupérer les paramètres de l'appel de la view
datePlan = request.matchdict['date']
logged_in = request.authenticated_userid logged_in = request.authenticated_userid
if datePlan == 'today':
datePlan = date.today().strftime('%Y-%m-%d')
url = request.route_url('agenda', date=datePlan)
url_select = request.route_url('dossier_select', date=datePlan)
# recall code et nom élève
if 'mem_nodossier' in request.session:
mem_nodossier = request.session['mem_nodossier']
mem_nomdossier = request.session['mem_nomdossier']
else:
mem_nodossier = 'Aucun'
mem_nomdossier = u'dossier sélectionné'
# liste des types de rdv
types_rdv = get_types_rdv(request)
type_rdv = u'RDV DEVIS'
# liste des users avec agenda # liste des users avec agenda
agendas = get_users_agenda(request) agendas = get_users_agenda(request, '')
# le user a-t-il un agenda ? # le user a-t-il un agenda ?
agenda = 'JMD' agenda = 'JMD'
@@ -114,6 +125,15 @@ def agenda(request):
if 'agenda' in request.params: if 'agenda' in request.params:
agenda = request.params["agenda"] agenda = request.params["agenda"]
# -- CREER un rendez-vous
if 'form.submitted' in request.params and mem_nodossier != 'Aucun':
dateRDV = request.params['dateRDV']
heureRDV = request.params['heureRDV']
type_rdv = request.params['type_rdv']
create_rdv(request, mem_nodossier, dateRDV, heureRDV, type_rdv, agenda, logged_in.upper())
request.session.flash(u"Le rendez-vous a été CREE avec succès.", 'success')
rows = get_rendez_vous(request, agenda) rows = get_rendez_vous(request, agenda)
# construire la liste des events # construire la liste des events
@@ -122,22 +142,25 @@ def agenda(request):
# déterminer la couleur de l'event selon la societe # déterminer la couleur de l'event selon la societe
societe = row.nodossier[0:2] societe = row.nodossier[0:2]
if societe == "PE": if societe == "PE":
color = "LightYellow" color = "#ffffb3"
elif societe == "ME":
color = "#ffe44d"
elif societe == "PL": elif societe == "PL":
color = "LightGreen" color = "#b3ff66"
elif societe == "PO": elif societe == "PO":
color = "LightBlue" color = "#b1dae7"
else: else:
color = "Gold" color = "#ffb3cc"
json_event = { json_event = {
'title': row.c_nom, 'title': '%s %s' % (row.c_qualite, row.c_nom),
'description': '%s %s' % (row.c_cp, row.c_ville.capitalize()),
'start': row.rdv_debut.strftime('%Y-%m-%d %H:%M:%S'), 'start': row.rdv_debut.strftime('%Y-%m-%d %H:%M:%S'),
'end': row.rdv_fin.strftime('%Y-%m-%d %H:%M:%S'), 'end': row.rdv_fin.strftime('%Y-%m-%d %H:%M:%S'),
'allDay': False, 'allDay': False,
'color': color, 'color': color,
'textColor': 'Black', 'textColor': 'Black',
'url': 'dossier_view/%s' % (row.nodossier), 'url': '/rdv_edit/%s/%s' % (row.nodossier, row.nolig),
} }
events.append(json_event) events.append(json_event)
@@ -147,17 +170,24 @@ def agenda(request):
'fullcalendar_events': json.dumps(events), 'fullcalendar_events': json.dumps(events),
'agendas': agendas, 'agendas': agendas,
'agenda': agenda, 'agenda': agenda,
'types_rdv': types_rdv,
'type_rdv': type_rdv,
'message': message,
'mem_nodossier': mem_nodossier,
'mem_nomdossier': mem_nomdossier,
'url': url,
'url_select': url_select,
'datePlan': datePlan,
} }
@view_config(route_name='planning', renderer='../templates/agenda/planning.pt', permission='view') @view_config(route_name='planning', renderer='../templates/agenda/planning.pt', permission='view')
def planning(request): def planning(request):
logged_in = request.authenticated_userid
# construire la liste des ressources # construire la liste des ressources
# {"id":"a","title":"Auditorium A"} # {"id":"a","title":"Auditorium A"}
ressources = [] ressources = []
# liste des users avec agenda # liste des users avec agenda
users = get_users_agenda(request) users = get_users_agenda(request, '')
for row in users: for row in users:
json_ressources = { json_ressources = {
'id': row.CD_UTI, 'id': row.CD_UTI,
@@ -170,30 +200,29 @@ def planning(request):
for user in users: for user in users:
rows = get_rendez_vous(request, user.CD_UTI) rows = get_rendez_vous(request, user.CD_UTI)
for row in rows: for row in rows:
event_url = 'dossier_view/%s' % (row.nodossier)
event_title = row.c_nom
# déterminer la couleur de l'event selon la societe # déterminer la couleur de l'event selon la societe
societe = row.nodossier[0:2] societe = row.nodossier[0:2]
if societe == "PE": if societe == "PE":
color = "LightYellow" color = "#ffffb3"
elif societe == "ME":
color = "#ffe44d"
elif societe == "PL": elif societe == "PL":
color = "LightGreen" color = "#b3ff66"
elif societe == "PO": elif societe == "PO":
color = "LightBlue" color = "#b1dae7"
else: else:
color = "Gold" color = "#ffb3cc"
json_event = { json_event = {
'resourceId': user.CD_UTI, 'resourceId': user.CD_UTI,
'title': event_title, 'title': row.c_nom,
'description': row.c_ville.capitalize(), 'description': '%s %s' % (row.c_cp, row.c_ville.capitalize()),
'start': row.rdv_debut.strftime('%Y-%m-%d %H:%M:%S'), 'start': row.rdv_debut.strftime('%Y-%m-%d %H:%M:%S'),
'end': row.rdv_fin.strftime('%Y-%m-%d %H:%M:%S'), 'end': row.rdv_fin.strftime('%Y-%m-%d %H:%M:%S'),
'allDay': False, 'allDay': False,
'color': color, 'color': color,
'textColor': 'Black', 'textColor': 'Black',
'url': event_url, 'url': '/dossier_view/%s' % (row.nodossier),
} }
events.append(json_event) events.append(json_event)

View File

@@ -18,13 +18,14 @@ from pyramid_mailer import get_mailer
from pyramid_mailer.message import Message, Attachment from pyramid_mailer.message import Message, Attachment
from datetime import * from datetime import *
import hashlib import hashlib
from sqlalchemy.exc import DBAPIError from sqlalchemy.exc import DBAPIError
from ..security import groupfinder from ..security import groupfinder
from user_agents import parse
import json import json
from ..models.default import * from ..models.default import *
from ..models.agenda import *
def to_decimal(x): def to_decimal(x):
import decimal import decimal
@@ -37,6 +38,21 @@ def to_euro(x):
#else: #else:
return (u"%.2f" % x).replace('.', ',') return (u"%.2f" % x).replace('.', ',')
def to_euroz(x):
"""Takes a float and returns a string"""
if x == 0:
return ""
else:
return (u"%.2f" % x).replace('.', ',')
def to_decz(x):
"""Takes a decimal and returns a string"""
if x == 0:
return ""
else:
return (u"%.2f" % x).replace('.', ',')
def to_sha1(message): def to_sha1(message):
return hashlib.sha1(message.encode('utf-8')).hexdigest() return hashlib.sha1(message.encode('utf-8')).hexdigest()
@@ -52,14 +68,14 @@ def to_percent(x):
return (u"%.2f " % x).replace('.', ',') + "%" return (u"%.2f " % x).replace('.', ',') + "%"
@view_config(route_name='home', renderer='../templates/home.pt', permission='view') @view_config(route_name='home', renderer='../templates/default/home.pt', permission='view')
def home(request): def home(request):
return { return {
'page_title': 'Bienvenue', 'page_title': 'Bienvenue',
'project': 'mondumas', 'project': 'mondumas',
} }
@view_config(route_name='envoyer_mdp', renderer='../templates/envoyer_mdp.pt') @view_config(route_name='envoyer_mdp', renderer='../templates/default/envoyer_mdp.pt')
def envoyer_mdp(request): def envoyer_mdp(request):
url = request.route_url('envoyer_mdp') url = request.route_url('envoyer_mdp')
message = u'' message = u''
@@ -92,7 +108,7 @@ Le lien suivant vous dirigera vers une page où vous pourrez ré-initialiser vot
'message': message, 'message': message,
} }
@view_config(route_name='changer_mdp', renderer='../templates/changer_mdp.pt', permission='view') @view_config(route_name='changer_mdp', renderer='../templates/default/changer_mdp.pt', permission='view')
def changer_mdp(request): def changer_mdp(request):
url = request.route_url('changer_mdp') url = request.route_url('changer_mdp')
logged_in = request.authenticated_userid logged_in = request.authenticated_userid
@@ -117,7 +133,7 @@ def changer_mdp(request):
'message': message, 'message': message,
} }
@view_config(route_name='redefinir_mdp', renderer='../templates/redefinir_mdp.pt') @view_config(route_name='redefinir_mdp', renderer='../templates/default/redefinir_mdp.pt')
def redefinir_mdp(request): def redefinir_mdp(request):
lien = request.matchdict["lien"] lien = request.matchdict["lien"]
url = request.route_url('redefinir_mdp', lien=lien) url = request.route_url('redefinir_mdp', lien=lien)
@@ -144,8 +160,8 @@ def redefinir_mdp(request):
} }
@view_config(route_name='login', renderer='../templates/login.pt', permission='view') @view_config(route_name='login', renderer='../templates/default/login.pt', permission='view')
@forbidden_view_config(renderer='../templates/login.pt') @forbidden_view_config(renderer='../templates/default/login.pt')
def login(request): def login(request):
current_route_path = request.current_route_path() current_route_path = request.current_route_path()
@@ -166,7 +182,11 @@ def login(request):
if record : if record :
# mot de passe hash valide ? # mot de passe hash valide ?
if record.mdp == to_sha1(password): if record.mdp == to_sha1(password):
update_last_connection(request, login) # get user agent string from request
ua_string = request.user_agent
user_agent = parse(ua_string)
update_last_connection(request, login, str(user_agent))
# force le commit car il ne se fait pas automatiquement après l'update # force le commit car il ne se fait pas automatiquement après l'update
transaction.commit() transaction.commit()
@@ -213,43 +233,3 @@ gestion.entreprise-dumas.com
mailer.send_immediately(message) mailer.send_immediately(message)
@view_config(route_name='chantier_lookup', renderer='../templates/chantier_lookup.pt', permission='view')
def chantier_lookup(request):
# recherche chantier
url = request.route_url('chantier_lookup')
message = u''
societes = ['PE','ME','PL','PO','CD']
societe = 'PE'
liste=[]
name = u''
cb_tous = "non"
if 'form.submitted' in request.params:
name = request.params['name']
societe = request.params['societe']
# si afficher tous les fiches ?
if 'cb_tous' in request.params:
cb_tous = "oui"
chantiers = get_chantiers_byName(request, societe, name, True)
else:
cb_tous = "non"
chantiers = get_chantiers_byName(request, societe, name, False)
if len(chantiers) == 0:
message = u"Chantier non trouvé : %s" % name
# construire la liste
for item in chantiers:
d = ('%s-%s' % (societe, item.numero),item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant),
item.nosin, item.status)
liste.append(d)
return {
'page_title': u"Rechercher un chantier",
'url': url,
'message': message,
'dt_data': json.dumps(liste),
'societes': societes,
'societe': societe,
'name': name,
'cb_tous': cb_tous,
}

249
mondumas/views/dossier.py Normal file
View File

@@ -0,0 +1,249 @@
# -*- coding: utf8 -*-
from pyramid.response import Response
from pyramid.renderers import render, get_renderer
from pyramid.view import (
view_config,
forbidden_view_config,
)
from pyramid.security import (
remember,
forget,
)
from pyramid.httpexceptions import (
HTTPFound,
HTTPNotFound,
HTTPForbidden,
)
from pyramid_mailer import get_mailer
from pyramid_mailer.message import Message, Attachment
from datetime import *
import hashlib
from sqlalchemy.exc import DBAPIError
from ..security import groupfinder
import json
from ..views.default import *
from ..models.default import *
from ..models.dossier import *
@view_config(route_name='dossier_lookup', renderer='../templates/dossier/dossier_lookup.pt', permission='view')
@view_config(route_name='dossier_select', renderer='../templates/dossier/dossier_lookup.pt', permission='view')
def dossier_lookup(request):
if 'dossier_select' in request.current_route_path() :
# récupérer les paramètres de l'appel de la view
datePlan = request.matchdict['date']
# sélectionner dossier -> goto planning
goto_url = '/dossier_selected/agenda/%s/' % datePlan
url = request.route_url('dossier_select', date=datePlan)
else:
# recherche dossier -> goto fiche dossier
goto_url = '/dossier_selected/dossier_view/%s/' % date.today().strftime('%Y-%m-%d')
url = request.route_url('dossier_lookup')
message = u''
societes = ['PE','ME','PL','PO','CD']
societe = 'PE'
liste=[]
name = u''
cb_tous = "non"
if 'form.submitted' in request.params:
name = request.params['name']
societe = request.params['societe']
# si afficher tous les fiches ?
if 'cb_tous' in request.params:
cb_tous = "oui"
chantiers = get_chantiers_byName(request, societe, name, True)
else:
cb_tous = "non"
chantiers = get_chantiers_byName(request, societe, name, False)
if len(chantiers) == 0:
message = u"Chantier non trouvé : %s" % name
# construire la liste
for item in chantiers:
d = ('%s-%s' % (societe, item.numero),item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant),
item.nosin, item.status)
liste.append(d)
return {
'page_title': u"Rechercher un chantier",
'url': url,
'goto_url': goto_url,
'message': message,
'dt_data': json.dumps(liste),
'societes': societes,
'societe': societe,
'name': name,
'cb_tous': cb_tous,
}
@view_config(route_name='dossier_view', renderer='../templates/dossier/dossier_view.pt', permission='view')
def dossier_view(request):
nodossier = request.matchdict['nodossier']
societe = nodossier[0:2]
url = request.route_url("dossier_view", nodossier=nodossier)
dossier = get_dossier_by_no(request, nodossier)
if dossier is None:
request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger')
return HTTPFound(location=request.route_url("dossier_lookup"))
# lire tous le suivi du dossier
details = get_dossier_rdv_by_no(request, nodossier, '0')
# lire toutes les dossiers du chantiers
documents = get_documents_byChantier(request, nodossier)
# lire toutes les dossiers similaires
similaires = get_similaires_byChantier(request, dossier.societe, dossier.C_NOM, dossier.C_ADR, dossier.C_CP, dossier.C_VILLE)
# lire tous les documents attachés
docs_attaches = get_docs_attaches(request, 'DOCS_ATTACHES', nodossier)
# select background color according to society
bg_color = "bg-%s" % societe
return {
'page_title': u"Dossier : %s" % (nodossier),
'nodossier': nodossier,
'dossier': dossier,
'details': details,
'documents': documents,
'similaires': similaires,
'docs_attaches': docs_attaches,
'docs_url': request.static_url(request.registry.settings['mondumas.DEVFAC14']),
'bg_color': bg_color,
}
@view_config(route_name='devis_view', renderer='../templates/dossier/devis_view.pt', permission='view')
def devis_view(request):
nodossier = request.matchdict['nodossier']
societe = nodossier[0:2]
url = request.route_url("devis_view", nodossier=nodossier)
type_doc = nodossier[3:5]
if type_doc == 'DE':
page_title = u"Devis no : %s" % (nodossier)
elif type_doc == 'FA':
page_title = u"Facture no : %s" % (nodossier)
else:
page_title = u"Proforma no : %s" % (nodossier)
dossier = get_devis_by_no(request, nodossier)
if dossier is None:
request.session.flash(u"Le document no %s est introuvable" % (nodossier), 'danger')
return HTTPFound(location=request.route_url("dossier_lookup"))
# lire tous les lignes du devis
details = get_devis_lig_by_no(request, nodossier)
# select background color according to society
bg_color = "bg-%s" % societe
return {
'page_title': page_title,
'nodossier': nodossier,
'dossier': dossier,
'details': details,
'bg_color': bg_color,
}
@view_config(route_name='dossier_selected', permission='view')
def dossier_selected(request):
# récupérer les paramètres de l'appel de la view
goto = request.matchdict['goto']
datePlan = request.matchdict['date']
nodossier = request.matchdict['nodossier']
# fiche dossier
dossier = get_dossier_by_no(request, nodossier)
# memorize nodossier et nom dossier
request.session['mem_nodossier'] = nodossier
request.session['mem_nomdossier'] = '%s %s' % (dossier.C_QUALITE, dossier.C_NOM)
if goto == 'dossier_view':
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
else:
return HTTPFound(location=request.route_url('agenda', date=datePlan))
@view_config(route_name='suivi_edit', renderer='../templates/dossier/suivi_edit.pt', permission='view')
def suivi_edit(request):
logged_in = request.authenticated_userid
nodossier = request.matchdict['nodossier']
nolig = request.matchdict['nolig']
url = request.route_url("suivi_edit", nodossier=nodossier, nolig=nolig)
message = ''
if nolig == '0':
# nouveau
suivi = {}
suivi['COMMENT'] = ''
suivi['USERMAJ'] = logged_in.upper()
suivi['DATEMAJ'] = datetime.now()
page_title= 'Nouveau suivi'
else:
# lire le suivi
suivi = get_dossier_rdv_by_no(request, nodossier, nolig)
if not suivi:
request.session.flash(u"Suivi non trouvé : %s" % nodossier, 'warning')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
page_title= u"Modification du suivi %s" % (nolig)
if 'form.submitted' in request.params:
new_values = {}
for param, db_value in suivi.items():
if param in request.params and request.params[param] != db_value:
new_values[param] = request.params[param]
if new_values:
new_values['USERMAJ'] = logged_in.upper()
new_values['DATE'] = date.today()
update_suivi(request, nodossier, nolig, new_values)
request.session.flash(u"Le suivi a été mis à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
if 'form.deleted' in request.params:
delete_rdv(request, nodossier, nolig)
request.session.flash(u"Le suivi a été supprimé avec succès.", 'success')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
return {
'page_title': page_title,
'logged_in': logged_in,
'url': url,
'nodossier': nodossier,
'nolig': nolig,
'suivi': suivi,
'message': message,
}
@view_config(route_name='dossier_edit', renderer='../templates/dossier/dossier_edit.pt', permission='view')
def dossier_edit(request):
logged_in = request.authenticated_userid
nodossier = request.matchdict['nodossier']
url = request.route_url('dossier_edit', nodossier=nodossier)
dossier = get_dossier_by_no(request, nodossier)
if not dossier:
request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger')
return HTTPFound(location=request.route_url('dossier_lookup'))
if 'form.submitted' in request.params:
new_values = {}
for param, db_value in dossier.items():
if param in request.params and request.params[param] != db_value:
new_values[param] = request.params[param]
if new_values:
update_dossier(request, nodossier, new_values)
request.session.flash(u"Le dossier a été mis à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier))
return {
'page_title': u"Modifier le dossier : %s" % nodossier,
'url': url,
'dossier': dossier,
'nodossier': nodossier,
}

View File

@@ -1,7 +1,7 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
from pyramid.view import notfound_view_config from pyramid.view import notfound_view_config
@notfound_view_config(renderer='../templates/404.pt') @notfound_view_config(renderer='../templates/default/404.pt')
def notfound_view(request): def notfound_view(request):
request.response.status = 404 request.response.status = 404
return { return {

View File

@@ -22,6 +22,7 @@ import json
from ..models.parametres import * from ..models.parametres import *
from ..models.default import * from ..models.default import *
from ..views.default import *
@view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage') @view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage')
def parametres(request): def parametres(request):
@@ -40,11 +41,6 @@ def users_list(request):
# construire la liste # construire la liste
liste=[] liste=[]
for item in items: for item in items:
if item.dern_cnx_le:
der_cnx_le = item.dern_cnx_le.strftime('%d/%m/%Y - %H:%M')
else:
der_cnx_le = ""
if item.actif == 0: if item.actif == 0:
etat = 'Inactif' etat = 'Inactif'
else: else:
@@ -59,7 +55,7 @@ def users_list(request):
else: else:
role = 'Gestion' role = 'Gestion'
d = (item.CD_UTI, item.NOM, item.email, item.agenda, role, der_cnx_le, etat) d = (item.CD_UTI, item.NOM, item.email, item.agenda, role, etat)
liste.append(d) liste.append(d)
return { return {
@@ -67,6 +63,28 @@ def users_list(request):
'dt_data': json.dumps(liste), 'dt_data': json.dumps(liste),
} }
@view_config(route_name='users_ua', renderer='../templates/parametres/users_ua.pt', permission='manage')
def users_ua(request):
# lire les utilisateurs
items = get_member_by_id(request, '0')
# construire la liste
liste=[]
for item in items:
# utilisateur a au moins une connexion ?
if item.dern_cnx_le:
der_cnx_le = item.dern_cnx_le.strftime('%d/%m/%Y - %H:%M')
d = (der_cnx_le, item.CD_UTI, item.NOM, item.ua_string)
liste.append(d)
return {
'page_title': u'Liste des connexions',
'dt_data': json.dumps(liste),
}
@view_config(route_name='user_edit', renderer='../templates/parametres/user_edit.pt', permission='manage') @view_config(route_name='user_edit', renderer='../templates/parametres/user_edit.pt', permission='manage')
def user_edit(request): def user_edit(request):
cd_uti = request.matchdict['cd_uti'] cd_uti = request.matchdict['cd_uti']
@@ -77,8 +95,8 @@ def user_edit(request):
if cd_uti == '0': if cd_uti == '0':
# nouveau # nouveau
individu = {} individu = {}
individu['cd_uti'] = '0' individu['CD_UTI'] = '0'
individu['nom'] = '' individu['NOM'] = ''
individu['email'] = '' individu['email'] = ''
individu['access'] = '0 | Production' individu['access'] = '0 | Production'
individu['actif'] = 1 individu['actif'] = 1
@@ -163,3 +181,59 @@ def last_emailing(request):
'page_title': u'Liste des derniers emailing', 'page_title': u'Liste des derniers emailing',
'dt_data': json.dumps(liste), 'dt_data': json.dumps(liste),
} }
@view_config(route_name='orphans_de', renderer='../templates/parametres/orphans_de.pt', permission='manage')
def orphans_de(request):
societe = request.matchdict['societe']
url = request.route_url('orphans_de', societe=societe)
message = u''
societes = ['PE','ME','PL','PO','CD']
nochantier = '0'
# prendre en compte les paramètres de saisie
if 'societe' in request.params:
societe = request.params["societe"]
url = request.route_url('orphans_de', societe=societe)
if 'form.nochantier' in request.params:
message = ''
nochantier = request.params['nochantier']
# oui, NestedMultiDict([('form.submitted', u''), ('id0', u'271246'), ('id1', u'370929')])
for param in request.params:
if param[:2] == 'id':
update_nochantier(request, societe, request.params[param], int(nochantier))
message = u"Le numéro de chantier est mis à jour avec succès"
# lire le premier devis orphelin
devis = get_orphans_DE(request, societe)
# lire tous les dossiers de ce chantier
dossiers = get_dossiers_byChantier(request, societe, '%s;%s;%s' % (devis.C_NOM, devis.C_ADR, devis.C_VILLE))
liste=[]
nochantiers=[]
# construire la liste
for item in dossiers:
dossier_id = '%s-%s' % (item.TYPE, item.numero)
if item.nochantier != 0:
nochantiers.append(item.nochantier)
nochantier = item.nochantier
d = (dossier_id, dossier_id, item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant),
item.nosin, item.nochantier)
liste.append(d)
if len(nochantiers) == 0:
nochantiers.append(1)
return {
'page_title': u"DEVIS orphelins",
'url': url,
'message': message,
'devis': devis,
'dt_data': json.dumps(liste),
'societes': societes,
'societe': societe,
'nochantiers': nochantiers,
'nochantier': nochantier,
}

BIN
nssm.exe Normal file

Binary file not shown.

View File

@@ -16,12 +16,12 @@ pyramid.includes =
pyramid_layout pyramid_layout
pyramid_mailer pyramid_mailer
pyramid_tm pyramid_tm
pyramid_exclog
sqlalchemy.url = mysql://root:cni/@srvbd/bddevfac?charset=utf8 sqlalchemy.url = mysql://root:cni/@srvbd/bddevfac?charset=utf8
sqlalchemy.pool_recycle = 3600 sqlalchemy.pool_recycle = 3600
mondumas.admin_email = phuoc@caotek.fr mondumas.admin_email = phuoc@caotek.fr
mondumas.DEVFAC14 = mondumas:static/img/DEVFAC14/
# Mailer configuration # Mailer configuration
mail.host = smtp.orange.fr mail.host = smtp.orange.fr
@@ -84,12 +84,6 @@ qualname = sqlalchemy.engine
# "level = DEBUG" logs SQL queries and results. # "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither. (Recommended for production systems.) # "level = WARN" logs neither. (Recommended for production systems.)
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic] [formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s

View File

@@ -1,51 +0,0 @@
# uncomment the next import line to get print to show up or see early
# exceptions if there are errors then run
# python -m win32traceutil
# to see the output
#import win32traceutil
import win32serviceutil
PORT_TO_BIND = 9180
CONFIG_FILE = 'production.ini'
SERVER_NAME = 'gestion.entreprise-dumas.com'
SERVICE_NAME = "Pyramid_Service"
SERVICE_DISPLAY_NAME = "Pyramid Web Service"
SERVICE_DESCRIPTION = """Permet de laner l'application Pyramid comme un servcie."""
class PyWebService(win32serviceutil.ServiceFramework):
"""Python Web Service."""
_svc_name_ = SERVICE_NAME
_svc_display_name_ = SERVICE_DISPLAY_NAME
_svc_deps_ = None # sequence of service names on which this depends
# Only exists on Windows 2000 or later, ignored on Windows NT
_svc_description_ = SERVICE_DESCRIPTION
def SvcDoRun(self):
from cherrypy import wsgiserver
from pyramid.paster import get_app
from pyramid.paster import setup_logging
import os, sys
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
app = get_app(CONFIG_FILE)
setup_logging(CONFIG_FILE)
self.server = wsgiserver.CherryPyWSGIServer(
('0.0.0.0', PORT_TO_BIND), app,
server_name=SERVER_NAME)
self.server.start()
def SvcStop(self):
self.server.stop()
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(PyWebService)

View File

@@ -10,7 +10,6 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
requires = [ requires = [
'pyramid', 'pyramid',
# 'pyramid_jinja2',
'pyramid_chameleon', 'pyramid_chameleon',
'pyramid_debugtoolbar', 'pyramid_debugtoolbar',
'pyramid_layout', 'pyramid_layout',
@@ -23,6 +22,7 @@ requires = [
'mysqlclient', 'mysqlclient',
'python-dateutil', 'python-dateutil',
'docutils', 'docutils',
'user-agents',
] ]
tests_require = [ tests_require = [
@@ -32,7 +32,7 @@ tests_require = [
] ]
setup(name='mondumas', setup(name='mondumas',
version='0.1', version='1.0',
description='mondumas', description='mondumas',
long_description=README + '\n\n' + CHANGES, long_description=README + '\n\n' + CHANGES,
classifiers=[ classifiers=[