From 1c4fa0f4481f53a61f0fb2720921ded52b3229a7 Mon Sep 17 00:00:00 2001 From: Samuel Arleo Date: Tue, 20 Feb 2018 05:52:12 +0000 Subject: [PATCH 01/91] Adding new views of the SMyDP module --- controllers/smydp.py | 30 ++++++++++++++++++ static/css/smydp_desechos.css | 51 +++++++++++++++++++++++++++++++ static/css/smydp_inventarios.css | 29 ++++++++++++++++++ static/css/smydp_listado.css | 51 +++++++++++++++++++++++++++++++ static/css/smydp_sustancias.css | 51 +++++++++++++++++++++++++++++++ static/images/clipboard2.png | Bin 0 -> 29011 bytes static/images/desechos.png | Bin 0 -> 35143 bytes static/images/inventario.png | Bin 0 -> 10483 bytes static/images/sustancias.png | Bin 0 -> 12356 bytes views/smydp/index.html | 40 ++++++++++++++++++++++++ views/smydp/inventarios.html | 47 ++++++++++++++++++++++++++++ views/smydp/sustancias.html | 41 +++++++++++++++++++++++++ 12 files changed, 340 insertions(+) create mode 100755 controllers/smydp.py create mode 100755 static/css/smydp_desechos.css create mode 100755 static/css/smydp_inventarios.css create mode 100755 static/css/smydp_listado.css create mode 100755 static/css/smydp_sustancias.css create mode 100644 static/images/clipboard2.png create mode 100644 static/images/desechos.png create mode 100644 static/images/inventario.png create mode 100644 static/images/sustancias.png create mode 100644 views/smydp/index.html create mode 100644 views/smydp/inventarios.html create mode 100644 views/smydp/sustancias.html diff --git a/controllers/smydp.py b/controllers/smydp.py new file mode 100755 index 00000000..a9c5a1b6 --- /dev/null +++ b/controllers/smydp.py @@ -0,0 +1,30 @@ +#----------------------------------------------------------------------------- +# Controladores provisionales utilizados solo para probar las vistas del modulo de SMyDP +# +# - Samuel Arleo +#----------------------------------------------------------------------------- + + +@auth.requires_login(otherwise=URL('modulos', 'login')) +def index(): + return locals() + + +@auth.requires_login(otherwise=URL('modulos', 'login')) +def sustancias(): + return locals() + + +@auth.requires_login(otherwise=URL('modulos', 'login')) +def listado(): + return locals() + + +@auth.requires_login(otherwise=URL('modulos', 'login')) +def inventarios(): + return locals() + + +@auth.requires_login(otherwise=URL('modulos', 'login')) +def desechos(): + return locals() \ No newline at end of file diff --git a/static/css/smydp_desechos.css b/static/css/smydp_desechos.css new file mode 100755 index 00000000..0efb2e0b --- /dev/null +++ b/static/css/smydp_desechos.css @@ -0,0 +1,51 @@ +.columnas { + text-align: center; +} + +#tituloBienvenida { + text-align: center; +} + +.iconos { + width: 130px; +} + +.opciones { + text-align: center; + color: #606060; +} + +.opciones:hover { + color: #909090; +} + +#fila2 { + padding: 30px 0 60px 0; + margin-top: 50px; +} + +.columnas>a:hover { + color: #0300d7; + text-decoration: none; +} + +.columnas>a { + color: black; +} + + +@media only screen and (max-width: 767px) { + + #main { + margin-top: 0; + } + + #fila1 { + padding: 0 0 20px 0; + } + + #fila2 { + padding: 30px 0 10px 0; + } + +} diff --git a/static/css/smydp_inventarios.css b/static/css/smydp_inventarios.css new file mode 100755 index 00000000..dc94f6e3 --- /dev/null +++ b/static/css/smydp_inventarios.css @@ -0,0 +1,29 @@ + +.columnas { + text-align: center; +} + +.caja{ + padding: 50px 0 50px 0; + margin: 0 5px 0 5px; + border: solid; + border-width: 2px; + border-color: #00b3d0; + background-color: #FFFFFF; +} + +.dependencia{ + margin: 0; + text-transform: uppercase; + color: #545454; + font-weight: bold; +} + +.opciones { + text-align: center; + color: #606060; +} + +#fila2 { + padding: 30px 0 30px 0; +} \ No newline at end of file diff --git a/static/css/smydp_listado.css b/static/css/smydp_listado.css new file mode 100755 index 00000000..0efb2e0b --- /dev/null +++ b/static/css/smydp_listado.css @@ -0,0 +1,51 @@ +.columnas { + text-align: center; +} + +#tituloBienvenida { + text-align: center; +} + +.iconos { + width: 130px; +} + +.opciones { + text-align: center; + color: #606060; +} + +.opciones:hover { + color: #909090; +} + +#fila2 { + padding: 30px 0 60px 0; + margin-top: 50px; +} + +.columnas>a:hover { + color: #0300d7; + text-decoration: none; +} + +.columnas>a { + color: black; +} + + +@media only screen and (max-width: 767px) { + + #main { + margin-top: 0; + } + + #fila1 { + padding: 0 0 20px 0; + } + + #fila2 { + padding: 30px 0 10px 0; + } + +} diff --git a/static/css/smydp_sustancias.css b/static/css/smydp_sustancias.css new file mode 100755 index 00000000..0efb2e0b --- /dev/null +++ b/static/css/smydp_sustancias.css @@ -0,0 +1,51 @@ +.columnas { + text-align: center; +} + +#tituloBienvenida { + text-align: center; +} + +.iconos { + width: 130px; +} + +.opciones { + text-align: center; + color: #606060; +} + +.opciones:hover { + color: #909090; +} + +#fila2 { + padding: 30px 0 60px 0; + margin-top: 50px; +} + +.columnas>a:hover { + color: #0300d7; + text-decoration: none; +} + +.columnas>a { + color: black; +} + + +@media only screen and (max-width: 767px) { + + #main { + margin-top: 0; + } + + #fila1 { + padding: 0 0 20px 0; + } + + #fila2 { + padding: 30px 0 10px 0; + } + +} diff --git a/static/images/clipboard2.png b/static/images/clipboard2.png new file mode 100644 index 0000000000000000000000000000000000000000..0ffdb452c39b00195daed17e4ae0866040bb1ead GIT binary patch literal 29011 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 literal 0 HcmV?d00001 diff --git a/static/images/desechos.png b/static/images/desechos.png new file mode 100644 index 0000000000000000000000000000000000000000..f99c76ba4c78f5f5bf8c91e1c37e278b4b2687f7 GIT binary patch literal 35143 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 literal 0 HcmV?d00001 diff --git a/static/images/sustancias.png b/static/images/sustancias.png new file mode 100644 index 0000000000000000000000000000000000000000..01e97ca7d40d8b7ab473f8c5577016f97c14f08a GIT binary patch literal 12356 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 literal 0 HcmV?d00001 diff --git a/views/smydp/index.html b/views/smydp/index.html new file mode 100644 index 00000000..10d71372 --- /dev/null +++ b/views/smydp/index.html @@ -0,0 +1,40 @@ +{{extend 'layout.html'}} + +{{block head}} + +{{end}} + +{{block center}} + + +{{end}} \ No newline at end of file diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html new file mode 100644 index 00000000..1482ff67 --- /dev/null +++ b/views/smydp/inventarios.html @@ -0,0 +1,47 @@ +{{extend 'layout.html'}} + +{{block head}} + +{{end}} + +{{block center}} + +
+
+
+ + {{ labs = ['Laboratorio A', 'Laboratorio B', 'Laboratorio C', 'Laboratorio D', 'Laboratorio E', 'Laboratorio F', 'Laboratorio G'] }} + {{ n = len(labs) }} + {{ filas = n//3 if n%3 == 0 else n//3+1 }} + {{ k = 0 }} + {{ while k < filas:}} +
+ +
+
+

{{=labs[3*k]}}

+
+
+ {{ if 3*k+1 < n: }} +
+
+

{{=labs[3*k+1]}}

+
+
+ {{pass}} + {{ if 3*k+2 < n: }} +
+
+

{{=labs[3*k+2]}}

+
+
+ {{ pass }} +
+ {{k=k+1}} + {{pass}} +
+ +{{end}} \ No newline at end of file diff --git a/views/smydp/sustancias.html b/views/smydp/sustancias.html new file mode 100644 index 00000000..f4ac55d9 --- /dev/null +++ b/views/smydp/sustancias.html @@ -0,0 +1,41 @@ +{{extend 'layout.html'}} + +{{block head}} + +{{end}} + +{{block center}} +
+
+
+ +
+
+
+ + +
+
+ +{{end}} \ No newline at end of file From 86de09799cbf39d27edbd9f3441661699d735959 Mon Sep 17 00:00:00 2001 From: Samuel Arleo Date: Tue, 20 Feb 2018 06:28:02 +0000 Subject: [PATCH 02/91] Cambiando icono de desechos --- static/images/desechos.png | Bin 35143 -> 22252 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/static/images/desechos.png b/static/images/desechos.png index f99c76ba4c78f5f5bf8c91e1c37e278b4b2687f7..391a8bee972dffcc93c886122ca2bd74bb55c7dc 100644 GIT binary patch literal 22252 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 Date: Tue, 20 Feb 2018 06:50:28 +0000 Subject: [PATCH 03/91] Haciendo las cajas de los espacios fisicos mas pequenas --- views/smydp/inventarios.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 1482ff67..54de4939 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -17,24 +17,26 @@ {{ while k < filas:}}
-
+
+

{{=labs[3*k]}}

{{ if 3*k+1 < n: }} -
+

{{=labs[3*k+1]}}

{{pass}} {{ if 3*k+2 < n: }} -
+

{{=labs[3*k+2]}}

+
{{ pass }}
{{k=k+1}} From 363a6e39d63c18f56948d2058bb60ab6f077767a Mon Sep 17 00:00:00 2001 From: Samuel Arleo Date: Tue, 20 Feb 2018 07:00:53 +0000 Subject: [PATCH 04/91] Otro estilo para las cajas de las dependencias --- static/css/smydp_inventarios.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/css/smydp_inventarios.css b/static/css/smydp_inventarios.css index dc94f6e3..366c8aee 100755 --- a/static/css/smydp_inventarios.css +++ b/static/css/smydp_inventarios.css @@ -8,14 +8,14 @@ margin: 0 5px 0 5px; border: solid; border-width: 2px; - border-color: #00b3d0; - background-color: #FFFFFF; + border-color: #FEE501; + background-color: #606060; } .dependencia{ margin: 0; text-transform: uppercase; - color: #545454; + color: #FFFFFF; font-weight: bold; } From 76e676664417047f5050086981c5b323e029d0ac Mon Sep 17 00:00:00 2001 From: Samuel Arleo Date: Tue, 20 Feb 2018 07:07:42 +0000 Subject: [PATCH 05/91] Adding hover to the boxes --- static/css/smydp_inventarios.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/static/css/smydp_inventarios.css b/static/css/smydp_inventarios.css index 366c8aee..3b613f1d 100755 --- a/static/css/smydp_inventarios.css +++ b/static/css/smydp_inventarios.css @@ -10,12 +10,17 @@ border-width: 2px; border-color: #FEE501; background-color: #606060; + color: #FFFFFF; +} + +.caja:hover { + background-color: #F0F0F0; + color: #606060; } .dependencia{ margin: 0; text-transform: uppercase; - color: #FFFFFF; font-weight: bold; } From 0ec7a08ff17b3e7e74c40e483f8526ab4fd547ed Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sat, 24 Feb 2018 10:04:20 +0000 Subject: [PATCH 06/91] Adding link to SMyDP module to the modules main view --- static/images/smydp_icono.png | Bin 0 -> 5514 bytes views/modulos/index.html | 11 +++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 static/images/smydp_icono.png diff --git a/static/images/smydp_icono.png b/static/images/smydp_icono.png new file mode 100644 index 0000000000000000000000000000000000000000..49cf4b5e0b4422361988c089e68db9701cccdcb0 GIT binary patch literal 5514 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 literal 0 HcmV?d00001 diff --git a/views/modulos/index.html b/views/modulos/index.html index 04323a38..6171d2e5 100644 --- a/views/modulos/index.html +++ b/views/modulos/index.html @@ -15,14 +15,21 @@
-
+ -
+ + +

Servicios

From 9007a49d05e0e59a49a4c6e7aa8a2fc27ea73e15 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sat, 24 Feb 2018 10:19:44 +0000 Subject: [PATCH 07/91] Changing clipboard picture of SMyDP --- static/images/clipboard2.png | Bin 29011 -> 13795 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/static/images/clipboard2.png b/static/images/clipboard2.png index 0ffdb452c39b00195daed17e4ae0866040bb1ead..a890b1c31bc6c6d33e3b9dd7c2c667460f547412 100644 GIT binary patch literal 13795 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 bQsir2?b%s4RSIt)b1*HJPpoW9xS9KZ)V!O9 literal 29011 zcmdRWc{r5s-}XKBHI-};^;IOKQkIyeU6xW*LJd(QG+K=r%#^et62$B#3KW5P_zrhbNH*1T75MS`;B_TZu{EwvH5y$J`=aHqqhikm| zK#<>4%Y*w)qB|#h{ENC<;t|vI#-CXqi_X6vt?KA-^|9GbUFm6@P@uDS|Brhs?T#3| z$;lwDxn*w*f1~}zLBg`*g1!I#tzunkLbi9zQiQ6+SXf&95gO~h$H$vDZ(1~k|G;{b z(E>QiE;kS_SkG@DBW}DA&iS9Lqb_S=T}UmUqbHH}jp;nKr7aLM7489clcHQ#+dM|>Ub#e<0hL*%n6}`2)+#-o@`*MOI z=Y6X7GtX}GnzGzWjdzI0l6F@L9Czlv3Or+3)37)Rmf6>yuKpc*lq_)-_(T2c$ zK2ko8}d08-1hJP+suu=w&nXO`6AqF)kdM5vxcdWiz|DNAnkf5#?zW@AB*S<_b zE$plaYt`2lrUjU|tAyXs{)ilTi2Q?KQ7Y_eD_uVO70!NX5t&Q|J-C;9|Gut^@T?5f zu+~pawJyBTUMeS3sI-0Y+H3(-v~ns+IAbUhETRF-9PI8*PmVmkvmz+}d3!d?3o3Dv z@c64Lxuzktok98bP+n_=oWs_eYBX77eL>RO!y~$BRRo)qTz?gO*y)dFPaNBUYbrE= zV@$E2sW0=@FzTAMdfg#}P$F-`8<7K%$S(A`bCss8@43cVa|o;{ta7(3>XY4AsG0xN zmn-uVj%J5%?-vZJ??|io$~L((=eEd(!(r2jI_NN>SdQ~?u+s8F9X6jyhsIFQ3g)%_ zk8V0qCSJXo(M<`))XIvh<@63@4ch*mPqVPaw~y!E;6~hzLG>|^I~sn#WkzdWSr{mh zKWFAffBq=8t+rNDx6Lb{*`H2fBD~wW7b-lM+Cl85RBe*<+Px+_-27V<@LyM$y?O8{ zmg^jFV;|<)NMmg!SUs&VX~AOewi;;Xok<^30OM;AM7@1q9rANl`}^5+#u$sIOJRwv zF()1;b@aO^t^xDv+vgaAAzXAsh@331l{5fPSL`m9Q5VYD@M!tT-#=*NtPr9opLxgK zPZ+_5;c~Necj}nVj$9mbjG2?F{T%$GAMwN9&sNAts3`a8@=ZTK;Fuax?`d<}A>Q-c zh33>)4xVW5UD-Qx?ViGTp1CxM3`;ahUcR_Rb!~RCa~aNiC&Kz^hG0Z)W}nfkKlS6c zM)=yN-aem>)sDlaRl_lVRroGVrVw0w14?E#1?te_&5mpuKl) z2ehEy4YPp;Q7)L-yO>wD^j2HwM#fH3zilK^3R!%Xw;S(XdNyIrcwT8JRCa=_aaVAq z&72f8O%j%?JeU0)1YFc`mgDuW0bpgEFlhIv+^tVHsr@`cVHUKCiw#S(dQ>R zAilM0N(LU6tWZ_|7}!`Vsq^tLI_6@~K)o3~9xk;eFKD#Uu*Z8$Wbb9LR4iu-d;*4Z zp|>rjmX)nCa`q{~zef$i@f8JNjlRWhsjp}Xd1Yby$e%km&I`D7Y2?xFSm&#!qzoUU zCEsey*-c=7dcTx9*GClIYj(;!f7G)BLqFBQSXe7VrzF*!E-48}S2?$!kz^W2#%z#K9EyFX7G#fGUnGOwPz1z$bR%vYu#g38vm8hYWt zN6jl?X0J`J>1N=*tUP~Sddk|gR9I}2DCm|lz0KLUto7;-#{!u+{uCpG?;{J5Ri zs}nc#JGG`tl*JPlG?Y7UA#Uv{-Y|*Q7DBHj$wrtr3!2<9zs5WYdjBL;zlbTRWL|3} zbx$3>oif#fl``(RQR`datMTL(!(e_Y#2twdoj1L3aboUGV{*{DyJjDEdtM0K+r((= z)bw+a_YvpX{@o(pZ8BvAl(k=RDui7}431uE^aSO_F5|LGety&GUP^pP!(sOtQC0VB z&9H*0&!QcKi}tS>zdKE#;3592hiqv$Mg=3a*T1g8&lXbqP+kGQBUmMg#wI4{eVvuK zANxEX=<}eQ!8;Lg*BVA2R;o5o`uVprmT%-?9@}}jPAEX+_&clw#LDw-u#hN_`K&1< z(#_lttz$h`2_}_(V~I4^#$t!+bBDJ2el@87R&bwBu`3U#_#yGd*r3C)|r@H*Y1p) zJZ6rhM$#!|K^7BarSb$}>c@A;M7MXDTlGq&VY4>7w@pb=n=Bh`1O9wJ*E4k z-uT@#(~*>`HWN23eYwrF^G&yP!+X>v1F}W^*5Mr^%;h6pFn}PTjC9Mk#w4&S7PeddQkTSpK^zUd-@gtuL7d;PuE`j@&6 zS{fGE&OcxeIxvhm9UW>Tc`rGD(&~`?TPbVKx*v0AH}e}o*f!9AVlKXE#hJDGMwVTg zo9NG>!}D0dO&-{zNzf75d&!QJ5V<|2)mIZEtLH>+4L=Mx{Yjj?6&*Bj^F@<~1{-rG zH2Gfbkxq3TY>LQB8+h<&JiT%c?1`ETJhzlh$4v)7kHZHfr+&&aw0?#MKkRNXI^R}t zm7kI~`Sf!k>2s#x`4NUSInba@5(u36?p@8X8Jj=S)$C-T zA^PGbr^&G8L;U-W6=3X|#)bVZtszI(n@eW<|Jd-U9pyBhv;&iCO;Pv4I*n`In(B5; z-05W}>amVE`*Us##ch4%0ImJGW#cAgj0dJUs8+-%YBzIZ=`ru7LJKh@gHg@jE;=l@ zcy>*h^d(_W=ugF~#JB{(eN==;{`!X*M-T1Ve{@SaO ze77N`Pk-#*clV*F%&`^l4au|hv6YAnkEZ!2 z1D1&3(TB5`KK8K77TFFwT@g=Hzl|Fbq@(t?%NIsy1!2E4-e?eK4`PDU(|LvGTn;Y= zzmo7LxddgOg6@fk9zbOp3xjyKC{OaZVK+(s)|ny%ZB9G+>5SfH@)5(V{Ew$U6kK_2 zY(+|dsEg{hH)sjZ{l{=8-JP`xT2ttEB)c><>5-7wfzr~)F5-Jd_o|R?LC%o5By|JC z5=JZIucY$wl1hUk2U>VCSZ%&8CivCLoSDxrU3XKQ3BSd>!Nw5^)rRCE2N`$Oi6zl?h1pK|!)+fw_RBWEoy^5db!(>F zgK@pY(Rka%Xx9|cJRd2Q9Oh0XW~ zs7#z%4JCUG#y25UM`R-$$Xq#fZ|IaFKd@9*^-2nEGT*ywro-K~`&7nBM0I~}0L5Mv zx4O$H3!bkN96tFu$gIH`qFO`Ake>=ZU|+H%H~02ZR!ruLkUSVna=J#Q(M?PKk1q+PEzfotS%CoTG#~5usuTv z4Hhg5q;y9``2M$A7I%z~>ddL6O&_ji)YrOl%C}bN&ewgrt5W@KUe7v$p=M#sUHmJ+ z>J&zsTs-!qdF!GI{)1cg_m`(9l1?XKrXL-Ve>zkE5AvI>YuaEqxA48j-Y*@7 zGsV|pFkcW-t`a-gv;vkB26A-TCI+xjfK>*6>zd5?J1go7X5Olo3WXuLtd6a!2}Iw8 z#p^kfPj8<<7;+b$^eGhh-@JM5v(GO{gq~v9Tx{!L55hmZeYUoGlbHJh|IPSQRvGl% zg<3{ONB_=IcCM-V+mlj z_*{K4%l&oG)|(cs@0?ux@#I<)V;_%quk{SKr*Iz~ty}UiUr9HOL#LrZ|fToo7{{ciA7ptg*ms+fN99 zctX_mFmZXfQGudULu!cKJk4nS@m;p)PN-}1v=uWRLYqOd*4&UyGzJst!ZYr7+#t=8T55HFBUkh9ScEpXr-X}0%E$y6S4lvSKsr51h=tUbO^oF}Qg<;3526sxbm_CLgN z`r|#5ClB+u1g~Uba_Y&o%2=Uo_3?K!^^_k{lwgS$>dRYHz&)$8o)?R6)X;bv;52?w z)tIuVGS~}VI->a5pES6)0WNef@zi(f;KsfrS*q{bbv8-VPoFk5zL_A;?%eYH$6{I& z>B9i#&bY-3qzm4&o!>_kIxcYref;>g)r7CGvmRsRE%nLl5k*z!`MSFUU;XH+%CvQ` zeMkMk>quiT*-oHz_E}lWl-^f~I|6Qki&E3AGHUK=*sKE&y4d{Fd`~!23%0Q8FSSAN zl+I-SDB(PcVG(q@GYz+(xK&#E@N1SZ+KdhRlU+ZO$vGSrO)abDGxK z69zmI#ZZJ_@pYfHwAA4{#s_rfMvZpIb+)*>*S?Jp2vnvAiIFm2@;8(QUl?6VDa-Ik zIb6b4XYSYj@)vC$;`UtuK0b~+?IRmCB^JnLn z>)53~>)QW;C#*v=J9R?YZ)zR6!&-6<7OvfOKtwI@|I73;$>Y!r+s8i)Fs3vr69xpzHYCrf>axOeQEF!=8N61Cu?mwDd+rq zO0ow`Xf3Au%n)!zTtPU9*kXHlbtA3&IyuPj@ZR%t2VN_&MfP6X=7n`GyaHF<8~ZIO zMLi7R{96!KeMr`DoikGO6}Zg7C*8Ga{{1QT*>W>tuc}y%>Qw6b?WGlQ_eXrY8tZUn zSK-p6JpsdlceG|K^oWtKz5qp0rUNb|5Os&4l|+1+a_U2CJ8U8E+wTo^!fuJs5jibi zdW^G?UPGtj`kOQds~$JUHVxh9KYH`pRAD|(qlpk*0%8q6M;H~HIl3W#z<>CsN_u?? zZgya0H@^qR53w)w`L!F>{;@~Pp7W9EjxmY(~58L;RK|0krx& zeQUBaD2CKeKNE9v2+&7mrD(?MqtBS_kE;90G5)$|GKin-elipX*99-UBCCUMIQ{2h zJQ-G{S+x)vfxo`$ny%^nE(zNDD$pL!K-9Lp$7A;mnY|&7p>IT@9y(;4tdBm)dH&hx zXrf79ae7Mdj|4}~ua2fGqY4JqSJfm;DQ@UOVYEIz3i1h;M~M}#LSEX-o0(YxPInWF z1BT`2$pC4^*_3)`pKJb*zsKlfY+F6bG1TQ}f`7~PSUuBVg5;uin>)iZs{NS(l5EcO z8By)J^Ww<>ORK0*IC$+Yipf)}512eH{=~T+R1|#!{09-}IJ8YFp>0<|6vi7DK zta;>O#+|j_nz+k*_=(P9?S};v_QLw9%fC9-=G}PYkY-oIMSC}@3Qg~ZTpq7R9d@vD zP>v?*nTx*cqARHCb!(c$WfBYr&^p0P{-{@a66d@yv;AbLbqK)5Q?1 zN5Hj)vjEf+u%$6u&z%Lpx4&!q3^Js9#$TqY&6u%hT|O>7J@FgCafhT}(sEK#T5|OD zMYj8P`gq+^kGaU5xGVp->(V8jTXn(>-UuLjqJlXXg8VU)D8h*uS;meJ)=NQ$;laHk*72pjp*H!TJdkn(>dz zShW7mL=cQ8QWo3abMN5pmWUl!RJ1`-PDGT-P^Jq#8efaDR1=A3mfyx^9=y#!K$w!j zmqXr!-89a+%a?g}(?59qaue_a(+1{hc{wj#KhMsuBiFuWZeEkg-(`;b)c?F?u_-k+ zU7NcQK|S}}lNW8rR!JtlDSgElE9UD!vH&n?v}%cRw|%Hjwaeh8^esyJRJt`@!=3Y> zSw|w1lV=BvUl(r4=IEp~w6^Z*n&#w>nM$a9rD=$K??)6wn8Lp2F#UYGC>PK?A%c#* z7R!1vaI~?u*|2XRV#GJRKdlhHtyOTBAaN3fUOLB}_}(&jaPDvtbfG)ICzKtdAH`G} zag0eTO^mLORVSFk?H~6(pr}J+C@$s{FAy2ow`kpy3$Y^hUUksh9v59IImiG0irLXB zwkXXQyio?|tI_xX&OJ;??vLIxwyeB;JiEEf&C>C!ZLE;1zGpEXa7;yMfc>^IeYP7A zg4br%njiNnBdPpaH|!-@(2RAf?%{I{cU_xi?)t0uGnEFx{(jDG#sa)Q(#3_oUdAlg znen+(z4g7X^#g~`N^B|oplj1~w4K#8+6FjoARs7+Am^Rs9)UWdi38o4m^7JdiSkjt z#W5PcSPD0J34c=wvbMU-S|q3>j!c@{eD6h5xGcmOQ9tiwur>@(fElGo2}imJKf?Lg zVtCKy@yY@&&9c@$mGbm^(ysG#g8%_}E{S|~ya==AQX3-y%j-xna^X09Jp1ae2tn)V z5vPp}aknY9u)vnWvtyuL+XtSuNxO%BtZFD7Fs5@h^;?o%q>}Hjhg|L>VVAajcoOY; zhEqvHou%)Ai1j-_-z^z>wZG@?h%(hfimOo{7p*Izl8MoeaIbi%C18~INC1qYzNGIe z%6&UdkR!P&3ZC<%5Zjp-#FHM@Aj%TRz?&p}9U45)PLyPlqSt>2(wPc=%!wtjw_Ax2^$*r^rz? zt#o|tJdZ^pWym^;VH(b5oI%_5`~m#~f8Xf-aS$k5M${6~l{X@RF4Eu_Ds${{M}Kzr zxTo8|(Q6|FXj7y{?W)vgo9j%nM#z{Hjs=8&#*;t_tzGIdePzrgVk!XoiR-9 zabRoCF@cC=dkMD%PKg#&g4d42vt3}**`*cz8k94fQNeG0aPK!(C%iJ=iG;HvVGWRv zB7ZujF|h5)YCwd~j-(Bx?QFDb@bz8A@EA0O#8d+S@>1kW=zoPBd3+ZwXu?20(*2zs zbAJluLkcva=&@$UF4NbyPE(k#K{%!dlt#SB_JmET-tPZ+#tq;afl|S>4DqK$l* ztZ;FI{T<6@cSbtUtKipv+dqCKg{pif{bHq!6Tm%!F2uK{fEr$Z1F{A=p$k0=vHWUp zrK5-gziIUDsa>dDBc69ZZ;4&E{CZtu)A^;Q2&c`Fmd}TlYm}&%>cvb!SF?9TR=UJE z7@m5w9fWF4)j++KK;F6vz}VHlgX~>asf*t>JzoEkf_7{cgj;~rR3;JHe+AZZnnH6v zX16T^n@ARjtFted-8yxSoKUpXR1{7#S>dx^Hq~_p<9+M+Bb$5{~FIynY%k`=S30=L_ic}5 zxWFV{AOZlqcO%?5Tq1_w-=8Ls1hP^>}u!|WE6%&4+ORe-buR*}V9B^)#nklR1U{d%IX(_2f)mo>RWBB*SXnEd@HVLQB?G zC+!T!jG`-KvWnE`*ZVPFg%km)ubx>1IHKZTi>weRE>ZVrd#oz@dtV_Dc)rNA9P|Me zC`WRDon1lQ2YEy0*%9Ck40c62*j)_R8!iuxmcJRgx@Y|H++!g>U3{ca-1ZgMci@Ra z3p0K9HJo;ugSoR~p5a^!09EoA(e>~+AM>fqb%X05SBMmR!aS|TOe1KPQFC8?H?8Mh z71-e~tA`OyY|FVbf+88LNCOjPMI2+%@Q1EYkx*k8LP}Kn@j&VM$xc;%D+xrXb)7py ziKbJO%M+3)76rn33d+>7{LPf0Q_MZ0)acF0IQ9xTIb5DoRz=Rz4cF6mdNP#yb&6d4 z4wt%puOQqBsrmNd^amsVw#N*l1QqcbT~1y%{uOXGxeZqny=5N)7;qAvb~w3OJPh|S zS*YQh;h3a!8F<=1wuROsbXN#5uP@)R*4L%_>M^5@;N5qC0J}cVnNtH^gFk%X)`|5M z--N`pEhgXwql|)w?V_y4GOzQk;jD*rDVuN=Vw?^kgnJ_>qxLqsXQTyl5-o+}RXu!JO=1`gGj_U1R=+ALG(5*BCCkGzto4qTXiZPwKQ>qc$@UlHAwQ zxURyDCgA$d>i=WR@JZ>U&@MgG*I`6d>Ag5~*Z1*z>{5QqVWfN|u}=YS^aD5^`q}oQ zjJFd3#KqWh_V9yg=_(r{HjDvxCfS*r$YFQjkVe`QmiBY?G0l$0$s43A|V&K=sh zR0o5=O(nz%7rlGh{%xM1Oq$$30A%jG*u%K7V}n|TlyGzL4Z;gtZAg!|%IRKq;f;;o zx;!Z7p|alZ-fnE36si3#SX#-KmNU6VPd3Qp9;bcK*A7l*meQU-Y!_yg@uL}~S_Rcy zXzR+gU~hO0ryQu%S(&q1er7NLR=ACgu}m>cq2K-Ce0)EPT7l zPI?FFbbHd8d4VoserFr_m#$%D$_Yt1hLymh(SA!k`^}FTyt2EX!5HJ;Cst2ouIdzr zy5B@&EMK`QR9AUxyvgUO;S>7yJc}KsnJJN+@9-?7y9WM(RP6+Q7hl?^h1!|RZ|Rnn z2SO~Ho%1ixWv{b97^f%A1sAchkJj{Vg7zqCQmU!-6)dz=3Vm~twu(HLpBg&JFod#? zZpU2({v3}Dt{+h-K%}+})~cy$!7{teK0Il0-7$@RyY^KUG~F1-P?w<2bka}Da{`0> z=xl9A4t+nV^=^3KeWB^qMTP56LniBg+FR|@ai!ItyE>2-o5C`|!-}e_H2UJpT6;xU z;+l+^1mb4f@}xNj;SGfXI}KA`TPLmsUhlcCIH;fo7L_ivaG@fFZU;$o5kBX!6SqN> zOs!!m4HH&RQNQwG(`ygv@t&Ev056I-si%qiiY1?vEB#+kqn}|J;ECL%kK; zVU6Pa6Wb?l&?Sl-azBdr?YSIc8_E(-tvWs_D*&OJaFQ6QDVcWy4J5DC^*lf5kY)LW z;a$wlmg$q3RvFFC;SR8c?f4L9P9PHs)TJ`>Kf{AXsN!D3D05Wn`&Rk;_kOhFD^rrO z3REY^FpVW%8nLBG)$kaw2LaBIYHB~dbwWb=aAx~MGjD(Y_CCpPX0oIqL(gM$uNmgt zSMJ-LCLg^u^3r6|ODI>be1@p03`6dqNV0nQR8NcB6~BeEtGAyl#tIbWmv(#w{L95C zaZyptHfx%z97wF=b9%KHlX$c~5QFLMF1TiC_uw+-Wn2|n-zQQU)*XL{Csb;_VeDfM@EoC0_f-d&L2@M9&p%x7EXL`X_JgIfGR*l270!A=+qO#$uYvQM zv0r)dxU5ct1(&~G!=gh)HJb*aV@RK>)tL``&2UGjT~j_^tZk!%!s9$WBMxGf;cyR> zJh9y?sOubu$u#{t>}zjM&uD)^14Ih8$#ig`Mb+HyEW~ql)IH=c7tU>hrvxwbeuyHd z2P7gZaoOqlJh^Xyg}5WU7@>u;5{#oon*3Dsi9JnQi&$Lo-1?MitmFR0Fg9Z(o_2`h zfPXw;`+N{>ID4<^1C6&Ga-UiyA#?aHfVI_VRoK}?Ki*cM=|@)|7z?4#*%)LJL`glS zL)nxV?KtB1h~%fpH$kE!KY4j)^u&7F6jv>wu77c;7yWa(0F-w}yM$mZ_tbELs*_-fOpt|Uw6&35 z|D`FvnY5&v-yKAWch_A0Az4+TOj7dZbJw+$EpCh^CgqdOHg3cX7>%+u;Ew7nPe%db zTcQqLsLRctp z8i=y*Hk#S}YN5R=;kg}4qOMmTqG)czwZC0sK$vHKoa67M@)A9H|6mi6*_$6e22KC&chdlvy$hCXtMcSStM3FB#L;7>pEaCgzMMV6+j_3}TIH!{Oi#zQ>W%&}v)5QV@sTZnE=R14Bc2@CMY5kO#_hNL zBQ*=qWysXnSa4L^@A@KS#bSvUpbjVoaGYmy!0)3mrxpT)7?0?Iqq~NJq)ASDgK_J3 z;xa0|@#)n1-_q*`74e>X&eN|wyJOh{;C~Ie1i0!XS#UP?+K=AcN;k$SK#`3ZZNS~v z2>y|y6s1$kIR8maXbt-cP0yRpfEQWRJ+0U4 zX2n}!;>z#I^{7L~`-YO@pa-2*Cnu@wEf-*IaGx^xG`S0zhGU5JfV)u9=Io1-j2r(iL`9m z=I3Hn$x!(9w^Tv4u1?zZjCHHXLD-I*VmJ1?GE6C`g36i1W5)*-lxdX)Ic-M{-t_-6R`5+z!|&+pf7x!`y0nMK9NxsG#`Jta33#N*mVyc2b&g#&tlvVVPkA{b>?Dwx?~4dBb2?K3Wab3Czc#*5Xu;BIv6;&aQrddfgnxAdL#xje z;+sh~yT16VMOF!JtsB(`APta{OiRxW2xZp=NsZ9XusuQR&`~SgxAVjwftKTNM9z-XScbn3S1|Ac#)6>~Wl7qIaxw*27 zJWlF3i+gD4&PM$RUQ5#VqaLLy0W0w3hnHn+In=KR#e#K`43EB~z?p{*odwLv(=!g6 z*AVl3em#38DX5sqzG?@azfk%;iws)%^2+(c8|ESHK^N#pz$gvCyC5SU?~swJ#U7F1(u~3i!?+ zY*F#A{RVpg$Zs4!2uPm9zjM!C-=UzgB?9zs4#$LAw z=2FwW1Ik;rgBo^{_2}R7gn&N*MUTSZ|07>RhXMWL|6jf)sqfT>Q{zAvOmx~Rhadyb z{QK6+k!`sv=2|IC3C+ zUicd#L{<_FOM%9<2AIjmSWEdr#rNaqpD2zCTw`A7snm^nyveC^IPMqPuLADJ(}gGp2gXKuK_|Tb zlSi6o8To!0$G>{@3MK56Ulz3elz=6?IJsOyZaIAR_>FD9(A|z*ja|jpJ+IcrWc7;A z=3OYr?%W`t2|v#-^O>=@br?}Vp9hzh=PZPgQ_c$9y1^&CJss`33eV_uFJBDG_5Ydt z{1QYM&nAv87Mu&RxYOl-2?)WPG6Z9hPdnyS-*52kpEe6Ec>!<&T_SfCG3rC^-2;NM zuf?YPApP3kjjJrw=9e;g?brWH*gc>0?J6L6kGEwZa(scUuh(S$(ks`X<8FeGi4BhwF=lmi;rQw~GUNyJYr&m0$4fRABESlBkiu|*1 z5+TTibk43&X4V`?3nyE8q~2>@LU@( zjq-D)y`0*8bEUzeB;t$|U}D`F#$QW*kDcPb$q%+TYjA;$l%aY&1as*5I`*F%T59Wag8<#4 z2gO!1{t^_cfx2m&L-Rj|uALvKGNZ-Tezh=r3{O3)e&x5imp}NLL}sx2^4h+FucKwK zD5N(szp&6Bi$al;q!oX5wKO*mtmpHxPti9(*Q*{HxAIy(x40Zba9gg+kX_y*-;Cmq zN@^XA?ByIF6mCE=#9vASsJsZ=6Mp9SYCyi+7k+TF7f~_4u<6=X9*74QBe292yKW(c zTvImABf1LUh_u*3;CwiqaWd!DfID=ci z3m0FxTxqS}J6i5%Rol%h)P03c|GLh{UkraaoZK!>b?9L8#_#Ea9?FxP4S)2$Gs4c7 z^#F;HyQzBx;uz2AVQjJr`IO$Aby-! zD}u%{()lVo*usDg28CKrF!^$hUnCIJm@fiT9jYfY@2|V{ofd5uxp5UrAJ?25bgL^8 zyfS51J#G9xwimbmpxmm0YOSJPo*~(#=flY@Wb4hi6a8tPIUpvI5mIYfH1LHd(gOaQ z_?+}5R~<8wcuro+1}%)YvJ)?9!_-U`_A*ii0?SaYEkQGWWYsGqTGtXGW?p!IV5IWd zZfndnIFK=vVWD&4u8i1!xA5KR{BgijVTXySTNrLqVZd!*4r?8whP(dh%)*gp;w8Qg zy|?CCKO~Q{15tSPwdf9H$Ry)5Ac3yeYCxB=Xh%l%MlD&hY7$d&5GY%zbE0TX)Y-XZ zQEy4;xUpg$I)0>dAfPrjg=3mEhkEuiWx%9Y-0#xleI_h0OToYudsd7U&+le>cFk{; zOxgrrOm2%4>Eqt^1$+<3GFw9@V4p4h6d{-Al`+*-gVZ3^69%vX%R_FlQmj z`VK(b!URBVz>Xi=hO?%wXiA8EB3@*$ZMQ1v$x9Ab^Red@#_L!->)_e!=HEd6@ECc{ zt<>ni-lMvpO)i}W(&qFTjw;6ZYfv(xhEsQ}18dkF&)YbJI&hLa-G3%%) z@F`-GDMf}Lu*cwJNO4#Zp^#O5K-)S(Y41aRA#cKMpcKM5`(1e-kLe&WlQgdWd+j%f z?>li*2e0fHsQZ3><&Jw~oRDko!u>)SI>U5zzi%T}9?zbs=`EsUL6l89aSlT7HmV6M zL9s+*34gbj4O*Fq?|L|~$X8ZBq=PWodsLqMtCsT}z#`446i*lFmkxV*V=3CxWkfs& zF3S4xjksxzpb_n_Y#846d@`QvxR*EhO}Fl!8p>$WeJZC%ih6GUj6W>UVWY?}T~i|N z!I2|8fOUMur(Mn`zvP-$b7~$sy!QN4=DqP(Z(jUnx|Av@q!iJ}A?0l{K6k#m5Owq~kM2WKpd zj@-A%R=g~~ZkeVFQs0ksYR!y2#RIzbvJNi~)s(;K(@BdStUrL^l~VSJugmdndSgk0 zDgQLV&9PR?sKyWrb<@hW1ONstgQWt|eFr6bQ*!Gy{#~tq`YRyr34&M%%zqIDzAn*M zdG!{g1WDQNDVVA2znqbqTRV=0hUPfi-$|5*T?b|DKz) z(ldE&v9JZp!;8S~v;De!Tr|=Cm?;@=ppg1I{HVy_bSu(7iF`Ol!o)45LH+C)wF!$th?E=%2oq>qi=aG zMiHl`z%ub>+ndUi&4T>*@}y!|7YdB5ou%dT8>~B;3npbQXQc@Fnc<1Tn>SR9=cUof zz*YeAa4m5K{2yi>g9eaS0ywITuGdl&XIOgOwQp0A@0-OIRqwEc;tJ4`GKBd*usxHw z7HGKCc-xMW#5b;XER&R*@4=B_l(h~H9E(1)L;*zqFA&^*E?9(>HYOU9HhQW zpa*wS29)1-6Urd+NB&ow==w{%!DXL=%H&!|>Y=eL9UPxrIQQ!K!ilIwwi+H0Cn!HB zr+yXmRHQ!BJFu!@xXb?owU1awe{x_&u$?zosE9R7 zSEIF~Le2c9Px-k#cJ~1lOQUt#KWq`bBJW_}>}+2I)6uh^TQpC*Bp^|4v+oh-pedzk z0V@)V|2HJQNBfKFeuG*8J*^B35*G%pdM=q$ zivHc&puY2Oznj3NlQi;aA&j|f&+QfhHXS*4PlaczmvGEmfwg7W9LRu*xDCL`GuZpU zLB_Gj0a((|t(RMe>pK|~ABZpFf9y^$l%QYhBtSL^Z*AfycJ^5c*7ia3|1d8!SBgoq zBvxn{X2)At7UdR1_(OQI5PFk&Y+bZnj$Y{8I12mu!-w(fwJ}N4T(?gndHcZZrVajk zJ=#uQQ>yE~e9}{MJ~?(4-PHlayi?HI0NhAdSuQYFE1k|R>kELxdpzl#`CWqo|3%GG zX&OpTz-8=o6)xKj?PEz?CVuPJc$K!DdgxlI?}R=yZLxDJPxEZPQxNatxe@~wS1wAx z7byIpe9cREa{TqAe~EF+l_|w&UQ4Lx^E~TFSWb`&MBOh8Yyt+m{#b$xMn(w&qeIG& zz`BOmxNLN|qD$|BhB3I6?(AUYy|L#7RX&)#ln*o{n_Pm)#_wF;k&#x)GipYu2Z2JqpG-N-+b zuJnKT8^#M}z=;Hf?#9oMQ)gMO%mWaFCy;Bo8D>utel9Ui;eE`1W1Pg%y`p{>xElIb zdiMznIuQ`jm(#AYCq~qR!)TlLmNNCr&g+9XanWeMabTfHneGLVC2F9?zFX5GLv34;EGfFt$qIlK87M zoM>}(FZQ3ckRsn`CI(tCe=;(^AcgOh0K6`I)xQOtDtEJ_|LL!U3?SV5YZt+!IMS(>Vc^4Be*QK1O#fmy&sV?-k=NRKNqhP z96l5%Lh^kCX_B=(MV*#)wz&VqKQH#=imtpS4cMhU;Yp{CSS{J*zUY@;g!Uv%&oA_Y zws{Vh1d~1ePxl;h`@dBX*C}6aj?+-RW$w4zFpBsMkiW1plwWlTSzEY1UT*6f2M9sD$D(N4%-}7J2Z3Orz=@$ zC4D7cLkOI0OSk6*N|7R??XIuxRwv)MsX#uLH*!W@V|L^a*m1AVe}S)nShA$kq>4F1 zQTmT{g8goHfM<_@T5Em3%SAu-e(;WC4Ds#{Rwz-h(?{9y0+n>rkcrg!22jxYSE_|%QIYoJ0HZ|@Dx80g3jQ>K^s^(G(?X=MLL zc4N(ws7P{3!0>4M8-b^`v+jT0BK;>W@>N~NOy)nhSDC4hvSBth3(TVqR@~3Wa~^?F zYXx-(e>6{EmNvr__?m$|aH$TkPOjlUTG})(3XFvUas6`s`yWGna>gq3vuQ2L%d#Z@N>?IA(Pom2*vt z4Re4^ufa$7iPs{fNih_DX!xtkTX1^3hiE*OT{a~f8)(Q^^d`OxJWQ?djZtf?#N}yg zQ`RpX!O8VyKLFMQfAAp(SAa?TBEn}5^nv2C`3(OV7-cS(i*n4N#%VYIa5;$DfoGB6 zCpz0>iJeErpOzE!1*-2H5=M20l8;*jF&iy3N+w>0tWcZf;2OF6beHUl^XMVL5lK<1 zi)k3{ZdE@WV|Hu8yr2~gva{!vvc)#htiV0BpN|==$&A!4hJPt3DMQcHSo32%cz>Y{ zg#8S#Kd0$EGph2EKC2+n24jAy&BN>?2R$t^Q>KQH=!RPR|Br}1Bs-?~b` z5h4xnF&811hnYA1{psG0Z3Ym1Jj=OD9r&leRE9;ePj&+H{2ocFG2{_Cm_39Zt(ncM z3O;b)fWukrWM|m1Jf!zAdr?u}>3D+^Uxvg> zCB%ri?ty!^{gl?S87Z_NO|Xb$p@rkKoElx=#$dKgPfuG|rQMGFHn%$;vFoDDsYl3> zX6ziw`b(%vsLj#G?~+=lu}IcNWx6ixtS~j<1fn;;{UbN7?RT-|VD|iCVp$o*xGuq% zRkLavn@gXAC|w76F96|TO4;NmF3H>dsG4{3bZL|MKMb9qC>e|+5@GMOl`zPb*VqBLV0ie?E6=}OJmB5hlop1Fy2|5BuEtF?u@IPe zOf$qG9#&`DU#~hoG`b5AP`l#t%t3+nghS9E6^IPL)kv&rb|9F7C}R|51`g#q*QL;y z@O*k%?$(jf(W}?KyAbN2X_Vxk0Z=M_&QU~M?Hc$in=}TKiI?*)FP}{K+sn3z>T0|J z7b%2xuV9o3k<9Mw=>-X}H$5NOc$sIOLY|`2OQ_)E6uJ}bd8OM~zzcDh(PY>Kjx}%M zX-ENDYcTR30vo_zgTXlo&xpOyf>i}0Se;}?r_AJ$%VN@aIri-C`y|&A+W-9tjz1DWi<>x)>}r9TtbCC9!_0 ztErXB;Geh5AGhKLjW$)L$Uh?<;*s0kczd&b35VwRE4ww0)Vo|}Sg|g@Wu@s1i-GFu z&``FWo}!B=RS~k6|Ixdlz?XlCH3iS^EnOU~g??K3Va-jk^O?r1+1ZZ$Glj(2`e)$t zM4-Kaxb>#EjBf&GLGWVxzs|xd;?6HRe{x$Cc;yQ>#Urxj!rHQ&`3_lgUXoYjN{B>y z#C4i_v7;3@Oap&rW{r7Wsy@oSJ$--O8Giw8Q|Tg1vS!y5iovn78(!anxg8TMcnqbLo=6Ctl0{Cll8C zHeFa>&LX_lE)BH(f7(0qc&PffkDsv?#a*O@sM{U65lX9N+KWQb z6QUU{QY5r6#xfI?%GM@ALyP1tlnP~rp^%?6S}a*+EHRasVK9aTndeLnBgCwoNTU~Q4O84Mo`xDv7J2_(A7uKnh+0p>M}Cv>mC zYiG zt+f?3q+-3x{%3bW8CNtV;84LE9-FUlwuEHp;=kU?Qv@pEC6J?ePtU-GbG6emf9zIl zQnyxoh^SQz7jo`{$pIv+(@s+r4M^M!w?I^9`lv7?Fs||5qRm0p8ATc){g+d&Bo{${ z+w#sc(f*me)`l=4&7}`_OjQ|v@EcRBKDT@8>lCucNEuzZ{uR)N{X5dSA2k+MJdh&H zBBww3R|@BP-GS@wG=H#%`MVlL2t(#p*gj5PD}wOMHTxtrgH@eN=TvLKhh2gXV~q7r z7!VF4?(od-UzO%=!0|(}!#&K`ZocWW$%`G=aXc_`p#V~O-x^p|uk>@l`}L{O!msTN z5AtwS+VtV@k33xqP^NNvI&2RjGT4}R8oe4 zS`OBGukK`zm}L&ko>s;BF9a7wK5~7!0m!Mm+(GayeE)nk9=E7vX!-5`;o0E8?f?Gi z2~*~NI?Yw#CTGK*t~$l@d9yf1zPcfT4QB{xYDPpuU@47;mPLI{H*m@QY_vWGuRZ)> zh5Ck?D6yMi>4IiS`u^kFh9i7xCnF_Ka8CVLp&RfK^2oXNuUU_3hc#q^gH{-WE=8C@ z?y$~?gb@?jV##cec6=q;Vr1eI>+VeY!r_bzURhMmlG#`8V=wO2%)9=1f zpt)Dt=65!D)dl;5@$s~3A0MVBtBWf!KGVsKD||vg4*SeGR(X z+`M=1oPoVoU9GLwX%#Eo-g_}WSZB0SC=_ofz5-DF*X7Wg1l+lYqYS!emo0TBZR-b2 z(o8f-Kw85*Ew9PF3e1o8sh8Zi;a?8MH?p52g2jQg}J9I==tR=j>@M8c5?= zC^c|fh`(wX&m~ABOOBY3X1@#xWujReXpv2%4#bjJMw01@~^ucq9ijd}xu^|u~*Bnv^pOhIfuj4YH8k{68QT{J^KRev#$2{p48=8L*9xyp9}Jg-3_jfnMZ~k4 z=^tP7hTM7?H4wA$+HA4!MZH_ACbS|tmkZ7r_dJ{$c%oB-dg5(z_?Udpt5t25;JNO< zO)wCx4w^{3N|yH<6P)O<9;dMvp^gN|7kx*|`El0L-v%xGJn^IzjWN0cgpic@;ek`;4%Wt$A&D{tV|b! zh=iLbjr*g#QI5F|3H?4Y)}DKQJTtR&04zTN*$hac<#tsLWg{|GDdwo`gj;iGuk_l5 zy}73yWw_gr4|fPN@;C@N2o0&=Iw{_bN|B^vxFSfp?KKS4L7_Yg?+?YJu5)-QZYHM4 z`C6+QwGCz>gxD51v6W3AsMSmkvyCmP{t?XK{Ph%qIj@3dG}ZCX<<4mY8KhPbRZ_IU zbg}Ul!O7@;B{{A(=}P#XsO}Ln1h0yYrOgDr{`8-o)8eGIvQILjVQaP`eHL=>Y@kUl zX9Mz9Me^6+mzwB6ky#`uI_P`uL&R-c)>FMdkFF%U@54oPyI??2XDFcGrWY<=TIX5I z7kHpqR6VTcem>ve9LUf=#Ysb$^E<)1#F6#AQw_(f!ufYglzP{Eg%Ihye zD79IrjR`IEd#o49U%dy|o@;f=Ee8>!X9iue>MNQou@Q_qwBHF?CD;fd^On6v(<)!Z zH}RZP>r}$5Di8F=c7wTUXMTKhK^!WJ0>CH6E9-d=bN}O^n-D}3Ft6!d&GX<2ES24? zw2e9k7fY{_r~8MaB+vcShr=H{YjPL8(*G10BDG-kxTP?*1C%9?)|h-PmF(J8IrbUB z$G{)L_RPe~wOm%kvYZj-JBTd>xlU{8RE3l#lr4Wh9@Rk1de3dzV&x>%CThuW7ezS; zLwc9U`A#Q)(hDhki3!d|BU1TN^g0J|_@-;zbBNjto|?m|@so>E%T<$h3mLjm%iDFA zKeM||yFAp5WiNkh(Id^hH@-syQ4TdRdxb=w&l=v~s^fKh*&rk4kx#24319Z&WF^NOLG$d5k&Hgv$XLf-)J!#o%JWwTk zJ=9%gTUZ#4$V+WTf~461tUZQAB2*RnynLU;;24$)Q_FW+oH?*P@-_$V{#nt>eFECR z5ybM{XZDCfQ_Qjq#>y!$ShFCl(l#J9w2+L&tXguhZgc4+%}1*A8l+G*&rXe{#a;0i zv^yC)#qiiU?Cr%f)S{fSRRYk`k@QEsb0Gf}-rU zxXPC-Cb;0FwL=S^&tYqZKoCrK3L#=`*$7^_$!B!ifzIq3gs(SR4YPOa7qI{|%wN32 ziPR#QDUIk)y2iLan*i3tq9y>G4^)`S`e|}AzZ;}`HxIwz!vk{P+2BG;NR#NEBWSm7 z9tsYS$~UeQMz@DdopEo8?E)N8E^yBQ0k|CeDyA%cgyo`I;LJWr-*1z0NZe zd&yVClx`_)7k=wPs3!Mj5Bf2c+#ECoyug&Li%EW1O^apbUXX0ly40j)+69Z|&R3TKc3}0Wy71&7v z_07e{%x1PlfAtO@x%Z+~hL<<3$5k5PPDgky{Z#Lj;IRmT#7kg8ot!vbbz~>iw%g8T z-iEjMY{34a4flZU z3A%11wM$qCMDr$~M&5QrHY8i(rG`$G^y=&t8ikw5pS~-sn!~tSI0lc&q<61Xau3WTnH||@Df}KZ+DfU z5CL8a9=dmC_sl>3x_CAwAIlbIMvR!A{wy3_QB1h{7Lr9wpRTcm1aza1ZE-!&Ci#kb zb(7!Qhl-Rehv@Uc|MskQ!|D!5DUFESTLlF>^`7C5gMe}-U_RLl5saR$7N)6XV<>+y zMpcMX)o!~N>PeioU7vDknsl=h|6-|QntaxahDSy$wVyq?t6Mg*ctH{NH~5-u5Ww-3 zG*Kq0Qm<$nWGJvqFfxy<53$e+-ISr(fPJo8PqkvlQVcldi0D{}=sW09OCW!v-}EaJ zt_q(SMxOCTufu0PInt(*by~h>40;?^;5WL^drY3|?=a{AhNJe$_A7Le=yg9&v1fFs z_!=*7K7BPrkM1X4F9HVk!6bVErFK}9PiX;P&T@_|!oWkkNOMjuRc}TtjDFiCVsRxApOa8bss4vzm>_@u1&%_qw%JaHt({ad2}8^ok~}UHZO)d zi^tUVWzz}opaYfr^3muGNjyf}EBz_BI3ABl1=^k2%(tv)NM4ePstHNGrcDeGno;PMKmEsxF>Hb0abYUhh!S+GG$2Jbv>&ck8JtWbd+W zMgk(dmy;M^*>N=7bMmNJ%)YsD+{gwkq+W|&cs8uYY+uQl(6nppr1)BJfogu-11a9K zVeU2w#5;0NL`Wo;?<(=Bi)$-xJM0)@41Js#3! zqp>l()AfN5YCL}FGKTpmM+Z&R)7}}L745Q$S-HXIFqPP&CH+%;CXjPpTZvYmd$SRg zhXw%aj-9cB>Iu>>lNP;y+pfOLP5T5biYI-8EK-pn+*-)d$QwnvhpG|-MX-FNrECg@ zLjN6fy;Q~Y+HmBQ;xdIBi4u21G=Yy0FimU<|H7pr(srQdxC7Jl4YsWJE~=fB6aSq+ zawE_SV<5*(mrLGlz4tjQbc7OGGPS&Uew)|}5Cc9J9{=J_wWW&^Oks`uh8EF+o9ZOf z;*O|EB}nlF`~hgntkmC~JV*eR73_k5iarvwIGSI7PE_|K-3_$_38D1xPgQKGvlHs~ zN9$NS)X|Xn%On6C=^db;>1X7ai`ixXIa-yn95f5KCnPTai>7ig8KEwJF@Gg%a*;XF zqD2WEx=@XS=O~~Sk9t3U4qn5X9RO$(_@8S?F&m{9viXwPARA;A|71IhT(qMq*>!B* zPT9Z-5oH1!_KL~7g4TuoUzUses6??YBM!MGA>sd^H9&1c?4K71*5raZw%<2W}vQRFM_)yl> z2o8x1YeUxwqQ>jJvBP$@=y19de;sa{`|Qz9yb=KN^#PFY=p=lpE^)M6=>ExuV1mpe zR{=9;{5n*0+cjTkI#`x;nZ4j3QZyz*F2$~|3QTPuI+=B=bh#9@1(1F4#8vIO zT!sQDZ9s3^ezWo`Wy}iET(MldcPGxl1$CH@F7StYCR3U+h}IeDCp5WysjFgIQ_O&9 z5gYT-PMuQpbb^5PLyh)u{&qQe%Sh3~!5dL%?ccxVebPgqbiB2*vuJv)BHrd*mjn$9 znI+dHtT^7C(5r~6o2U5r0x9<2O4b*DV+h`TmA9$FTbC9!awK5b?T0AdW=U;CJ=ekE z7L-t)azT8U9)UEP#RtW+B_oj7P$C!Dyun-lgASWuK$}11`L)m9dd^g% zEUIFP|3^<``RE06h?M}|~?~eAEn+P_MFQ>?P z#DVFvSH*-z$5$SiR+C`act)6pTFL!KwM6AeIJDnpssg{z6EX7n>~7NV%vDp=08n<~ zYro{8x!2Lpc=jCLfU%PH$UejMTgP#YwX}w(=trOt-1Y zXOD<#9*GYing&Y_^MJ$mgJn14@RSi(J?)U(se)}4C`8e%>#Ta;pN-JMZ7HS@G}n*BQ)vbA0f{7W;}LZ{XFt$O((Yz)#Vov@HP7UbXg=IaP7 z3k_HYREi&9Wl;pyQ#bp;e<4d8t!Y-=x5{ZB->ffQ^U}|h8jf`t4UTEInT3w%Pby7g zdtvF;?66NUL3Mirzz3b~sbN@{3eD!&WB&lA^epWqi`OJ1Qv)zg zvr3nJb-RsTo~u-ms8AUe)wYxz%d8(Z0dweIP1iBv>_M>8dE3nrV7A)APz4q+e#zb! zL&O9}tc3g8EZpQ2s8#kB#lBK$0n+tLDIN`y-OB~K3^oVU%I`Zi`nuug!fJC^o-Fp_g=>AeG52?S&K z8nF~TihG8Z5k9m}w;?t3U`Gu;)|G|6p22sQ*mb5DWQQPbv8ir%14of8dEbW@fSwI^ z=8g7!2OwEiQQ+UroK>f?2m5}I=ymR#*@jeyKd0~d0TaOQ@AYXKLk3@91=KmX+Ej{f-WT(n)0(Tdwy&_$IdL~L}B}v2W`ZAAA#XAEa!_% zgQUm~GtB+H!+g=Y>Jq828Jzhit1(HMLEkS_#aRys!jyI3_}(q62#Tm3&dH}78PJx^ z4&{&*|6Q4|!t$WpkN3_Hi|i?|}foXgXP2IQHR=Uc{T0SFR#o9FNqyctqE43X!=jZXPi`9=v^FlGc_TQ5mQ0xX3BF?7 zo;7pFW2a#LT#w}8nQCL-srRxF0&Z!G#cAK_26bt(GJUnk2-6Y33Ogv7;(h4=zOrt6qG|7Kz*Bf%tHuUg0o-(IahI%1-~qQS#0QRel7E`Lz$nu% z)w|Iz=!3{ynwz3pHXs2qkApkC+5c(UoBM?9Dt7bE9DXp#g?>hxqks zu>Doyfd#Z)nkJGh#ns7=RhC;Jt>ll62x)Q+yj4u=E$nqxgvN2-kQ`Ho5w?G?M}>CYNw0Ig62O8DAx`?10vvX{qMyV|%*pZEhPsQfkq{-2E)NhPxv^pItU9&FabM zX@~EjTRAdzji3Dd=2OQ2cuV1;lbf7Q9^7}*ea(U6?(iS7)YxQ|q482f6VqMBCTmPg s;m6Q;#TsMdH5O$TCT-yDbMVNa!2i6#Hn-5_umNJV$#!GbdbhCu21*MFLI3~& From 83c5083396fb5416c58f1fba856ff1d202b5e2f6 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Feb 2018 03:04:50 +0000 Subject: [PATCH 08/91] Creando modelo para el modulo de SMyDP --- models/smydp.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 models/smydp.py diff --git a/models/smydp.py b/models/smydp.py new file mode 100644 index 00000000..c51bf78b --- /dev/null +++ b/models/smydp.py @@ -0,0 +1,26 @@ +#------------------------------------ Modulo de Sustancias, materiales y desechos ------------------------------------------- + + +""" +#t_Sustancia: Tabla de sustancias de la cual se obtiene informacion del listado (catalogo de sustancias) +db.define_table( + #Nombre de la entidad + 't_Sustancia', + #Atributos; + Field('f_nombre', 'string', label=T('Nombre'),requires=IS_NOT_EMPTY(), + Field('f_cas', 'string', label=T('CAS'),requires=IS_NOT_EMPTY()), + Field('f_pureza', 'integer',requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), + Field('f_estado', 'integer', requires=IS_IN_DB(db,db.t_estado.id,'%(f_estado)s'), label=T('Estado'), + Field('f_control', 'integer', label=T('Control'), requires=IS_IN_DB(db,db.t_regimenes.id,'%(f_nombre)s'), + Field('f_peligrosidad', 'list:string', label=T('Peligrosidad'),requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), + widget=SQLFORM.widgets.checkboxes.widget), + Field('f_reporte','upload',label=T('MSDS'),requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf'))), + format='%(f_nombre)s', + migrate=settings.migrate) + +db.t_sustancias.id.readable=False +db.t_sustancias.id.writable=False +db.t_sustancias.f_reporte.readable=(auth.has_membership('Gestor de Sustancias')or auth.has_membership('WebMaster')) +db.t_sustancias._singular='Listado de Sustancias' +db.t_sustancias._plural='Listado de Sustancias' +""" \ No newline at end of file From 3d5c9ed977841730349ac07d14f8e691203487d9 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Feb 2018 06:38:59 +0000 Subject: [PATCH 09/91] Agregando tabla de sustancias (catalogo/listado de sustancias) --- languages/es.py | 8 ++++++++ models/smydp.py | 38 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/languages/es.py b/languages/es.py index c309e1b0..6eda95a5 100755 --- a/languages/es.py +++ b/languages/es.py @@ -101,6 +101,7 @@ 'cannot create file': 'no es posible crear archivo', 'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"', 'Cargo': 'Cargo', +'CAS': 'CAS', 'Categoría': 'Categoría', 'Certificado de calibración': 'Certificado de calibración', 'Certificado de conformidad del producto (ensayado o calibrado)': 'Certificado de conformidad del producto (ensayado o calibrado)', @@ -130,6 +131,7 @@ 'Config.ini': 'Config.ini', 'Confirm Password': 'Confirm Password', 'contains': 'contiene', +'Control': 'Control', 'Controller': 'Controlador', 'Controllers': 'Controladores', 'controllers': 'controladores', @@ -226,6 +228,7 @@ 'Errors in form, please check it out.': 'Hay errores en el formulario, por favor compruébelo.', 'Espacio Fisico': 'Espacio Fisico', 'Espacio Físico': 'Espacio Físico', +'Estado': 'Estado', 'Estatus': 'Estatus', 'export as csv file': 'exportar como archivo CSV', 'Export:': 'Exportar:', @@ -242,6 +245,7 @@ 'Fecha de Ingreso': 'Fecha de Ingreso', 'Fecha de Salida': 'Fecha de Salida', 'Fecha de Solicitud': 'Fecha de Solicitud', +'file': 'file', 'file "%(filename)s" created': 'archivo "%(filename)s" creado', 'file "%(filename)s" deleted': 'archivo "%(filename)s" eliminado', 'file "%(filename)s" uploaded': 'archivo "%(filename)s" subido', @@ -266,6 +270,7 @@ 'help': 'ayuda', 'Helping web2py': 'Ayudando a web2py', 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})', +'Hoja de seguridad': 'Hoja de seguridad', 'Hola! Por favor, ingresa en el siguiente enlace http://127.0.0.1:8000/recoverpassword/?key=%(key)s para recuperar tu clave de acceso.': 'Hola! Por favor, ingresa en el siguiente enlace http://127.0.0.1:8000/recoverpassword/?key=%(key)s para recuperar tu clave de acceso.', 'Home': 'Inicio', 'How did you get here?': '¿Cómo llegaste aquí?', @@ -394,6 +399,7 @@ "Password fields don't match": 'Los campos de contraseña no coinciden', 'Password reset': 'Reinicio de contraseña', 'Peeking at file': 'Visualizando archivo', +'Peligrosidad': 'Peligrosidad', 'Pendiente por aprobar': 'Pendiente por aprobar', 'Permission': 'Permiso', 'Permissions': 'Permisos', @@ -419,6 +425,7 @@ 'Profile': 'Perfil', 'Profile updated': 'Perfil actualizado', 'Propósito del servicio solicitado': 'Propósito del servicio solicitado', +'Pureza': 'Pureza', 'pygraphviz library not found': 'Libreria pygraphviz no encontrada', 'Python': 'Python', 'Página web': 'Página web', @@ -581,6 +588,7 @@ 'Value already in database or empty': 'Value already in database or empty', 'value already in database or empty': 'el valor ya existe en la base de datos o está vacío', 'value not allowed': 'valor no permitido', +'Value not allowed': 'Value not allowed', 'Value not in database': 'Value not in database', 'value not in database': 'el valor no está en la base de datos', 'Verify Password': 'Verificar Contraseña', diff --git a/models/smydp.py b/models/smydp.py index c51bf78b..754c5a2c 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -1,26 +1,28 @@ -#------------------------------------ Modulo de Sustancias, materiales y desechos ------------------------------------------- +#------------------------------------ Modulo de Sustancias, materiales y desechos peligrosos------------------------------------------- -""" #t_Sustancia: Tabla de sustancias de la cual se obtiene informacion del listado (catalogo de sustancias) db.define_table( #Nombre de la entidad 't_Sustancia', #Atributos; - Field('f_nombre', 'string', label=T('Nombre'),requires=IS_NOT_EMPTY(), - Field('f_cas', 'string', label=T('CAS'),requires=IS_NOT_EMPTY()), - Field('f_pureza', 'integer',requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), - Field('f_estado', 'integer', requires=IS_IN_DB(db,db.t_estado.id,'%(f_estado)s'), label=T('Estado'), - Field('f_control', 'integer', label=T('Control'), requires=IS_IN_DB(db,db.t_regimenes.id,'%(f_nombre)s'), - Field('f_peligrosidad', 'list:string', label=T('Peligrosidad'),requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), - widget=SQLFORM.widgets.checkboxes.widget), - Field('f_reporte','upload',label=T('MSDS'),requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf'))), - format='%(f_nombre)s', - migrate=settings.migrate) + Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), + Field('f_cas', 'string', requires=IS_NOT_EMPTY(), unique=True, label=T('CAS')), + Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), + Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), + widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), + Field('f_control', 'list:integer',requires=IS_IN_SET(['Ninguno','RL4','RL7', 'RL4 y RL7']), + widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), + Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), + widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), + # Hoja de seguridad (archivo pdf) + Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad')), + format='%(f_nombre)s') + +#db.t_sustancias.id.readable=False #Si se muestra en la forma, descomentar +#db.t_sustancias.id.writable=False +db.t_Sustancia.f_hds.readable=(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')) #-*-* Chequear permisos aqui +db.t_Sustancia._singular='Catálogo de Sustancias' +db.t_Sustancia._plural='Catálogo de Sustancias' + -db.t_sustancias.id.readable=False -db.t_sustancias.id.writable=False -db.t_sustancias.f_reporte.readable=(auth.has_membership('Gestor de Sustancias')or auth.has_membership('WebMaster')) -db.t_sustancias._singular='Listado de Sustancias' -db.t_sustancias._plural='Listado de Sustancias' -""" \ No newline at end of file From 947c5d3f7a1e3fa5b5e40efb87a71333619975ea Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Feb 2018 10:44:24 +0000 Subject: [PATCH 10/91] Migrando lista de sustancias --- controllers/smydp.py | 23 +++++++++++++++++++---- models/smydp.py | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index a9c5a1b6..8fa7bf85 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -16,15 +16,30 @@ def sustancias(): @auth.requires_login(otherwise=URL('modulos', 'login')) -def listado(): +def inventarios(): return locals() @auth.requires_login(otherwise=URL('modulos', 'login')) -def inventarios(): +def desechos(): return locals() +#-------------------------------------- Catalogo --------------------------------------- +""" @auth.requires_login(otherwise=URL('modulos', 'login')) -def desechos(): - return locals() \ No newline at end of file +def catalogo(): + + if not 'view' in request.args: + db.t_sustancias.f_peligrosidad.represent = lambda v,r: v[0] if v else "Ninguna" + + if 'edit' in request.args or 'new' in request.args: + mark_not_empty(db.t_sustancias) + + if(auth.has_membership('Gestor de SMyDP') or \ + auth.has_membership('WebMaster')): + table = SQLFORM.smartgrid(db.t_sustancias,onupdate=auth.archive,links_in_grid=False,csv=False,user_signature=True,paginate=10) + else: + table = SQLFORM.smartgrid(db.t_sustancias,editable=False,deletable=False,csv=False,links_in_grid=False,create=False,paginate=10) + return locals() +""" \ No newline at end of file diff --git a/models/smydp.py b/models/smydp.py index 754c5a2c..af925f79 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -26,3 +26,5 @@ db.t_Sustancia._plural='Catálogo de Sustancias' + + From 9477758bf7e32d84a2d2cb90c64eccc89ab6e672 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Feb 2018 11:40:30 +0000 Subject: [PATCH 11/91] Nada importante --- controllers/smydp.py | 16 ++++------------ models/smydp.py | 8 ++------ views/smydp/catalogo.html | 0 3 files changed, 6 insertions(+), 18 deletions(-) create mode 100644 views/smydp/catalogo.html diff --git a/controllers/smydp.py b/controllers/smydp.py index 8fa7bf85..e36c2baa 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -26,20 +26,12 @@ def desechos(): #-------------------------------------- Catalogo --------------------------------------- -""" + @auth.requires_login(otherwise=URL('modulos', 'login')) def catalogo(): - if not 'view' in request.args: - db.t_sustancias.f_peligrosidad.represent = lambda v,r: v[0] if v else "Ninguna" - - if 'edit' in request.args or 'new' in request.args: - mark_not_empty(db.t_sustancias) - - if(auth.has_membership('Gestor de SMyDP') or \ - auth.has_membership('WebMaster')): - table = SQLFORM.smartgrid(db.t_sustancias,onupdate=auth.archive,links_in_grid=False,csv=False,user_signature=True,paginate=10) + if(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')): + table = SQLFORM.smartgrid(db.t_Sustancia,onupdate=auth.archive,links_in_grid=False,csv=False,user_signature=True,paginate=10) else: - table = SQLFORM.smartgrid(db.t_sustancias,editable=False,deletable=False,csv=False,links_in_grid=False,create=False,paginate=10) + table = SQLFORM.smartgrid(db.t_Sustancia,editable=False,deletable=False,csv=False,links_in_grid=False,create=False,paginate=10) return locals() -""" \ No newline at end of file diff --git a/models/smydp.py b/models/smydp.py index af925f79..4342b7d4 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -11,7 +11,7 @@ Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), - Field('f_control', 'list:integer',requires=IS_IN_SET(['Ninguno','RL4','RL7', 'RL4 y RL7']), + Field('f_control', 'list:string',requires=IS_IN_SET(['Ninguno','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), @@ -23,8 +23,4 @@ #db.t_sustancias.id.writable=False db.t_Sustancia.f_hds.readable=(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')) #-*-* Chequear permisos aqui db.t_Sustancia._singular='Catálogo de Sustancias' -db.t_Sustancia._plural='Catálogo de Sustancias' - - - - +db.t_Sustancia._plural='Catálogo de Sustancias' \ No newline at end of file diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html new file mode 100644 index 00000000..e69de29b From 162d5b9a58ce136efac361389118bc0ae07c98af Mon Sep 17 00:00:00 2001 From: saar1312 Date: Wed, 28 Feb 2018 03:49:04 +0000 Subject: [PATCH 12/91] Agregando auth.event a la tabla del catalogo de sustancias --- controllers/smydp.py | 1 + languages/es.py | 3 ++ models/smydp.py | 68 +++++++++++++++++++++++++-- static/css/smydp_catalogo.css | 88 +++++++++++++++++++++++++++++++++++ static/css/smydp_listado.css | 51 -------------------- views/smydp/catalogo.html | 15 ++++++ views/smydp/sustancias.html | 4 +- 7 files changed, 174 insertions(+), 56 deletions(-) create mode 100755 static/css/smydp_catalogo.css delete mode 100755 static/css/smydp_listado.css diff --git a/controllers/smydp.py b/controllers/smydp.py index e36c2baa..de981c3d 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -35,3 +35,4 @@ def catalogo(): else: table = SQLFORM.smartgrid(db.t_Sustancia,editable=False,deletable=False,csv=False,links_in_grid=False,create=False,paginate=10) return locals() + diff --git a/languages/es.py b/languages/es.py index 6eda95a5..f1ee03b3 100755 --- a/languages/es.py +++ b/languages/es.py @@ -103,6 +103,7 @@ 'Cargo': 'Cargo', 'CAS': 'CAS', 'Categoría': 'Categoría', +'Catálogo de Sustancias': 'Catálogo de Sustancias', 'Certificado de calibración': 'Certificado de calibración', 'Certificado de conformidad del producto (ensayado o calibrado)': 'Certificado de conformidad del producto (ensayado o calibrado)', 'Certificado de conformidad del producto (ensayado o calibrado) ': 'Certificado de conformidad del producto (ensayado o calibrado) ', @@ -251,6 +252,7 @@ 'file "%(filename)s" uploaded': 'archivo "%(filename)s" subido', 'file "%(filename)s" was not deleted': 'archivo "%(filename)s" no fué eliminado', 'file "%s" of %s restored': 'archivo "%s" de %s restaurado', +'file ## download': 'file ', 'file changed on disk': 'archivo modificado en el disco', 'file does not exist': 'archivo no existe', 'file saved on %(time)s': 'archivo guardado %(time)s', @@ -372,6 +374,7 @@ 'Nombre': 'Nombre', 'Nombre de la Sede': 'Nombre de la Sede', 'Not authorized': 'No autorizado', +'not authorized': 'not authorized', 'not in': 'no en', 'Number of entries: **%s**': 'Numero de entradas: **%s**', 'Número de cedula no válido.': 'Número de cedula no válido.', diff --git a/models/smydp.py b/models/smydp.py index 4342b7d4..65c42405 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -11,16 +11,78 @@ Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), - Field('f_control', 'list:string',requires=IS_IN_SET(['Ninguno','RL4','RL7', 'RL4 y RL7']), + Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), # Hoja de seguridad (archivo pdf) Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad')), - format='%(f_nombre)s') + format='%(f_nombre)s', + auth.signature) # Agregar los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla #db.t_sustancias.id.readable=False #Si se muestra en la forma, descomentar #db.t_sustancias.id.writable=False db.t_Sustancia.f_hds.readable=(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')) #-*-* Chequear permisos aqui db.t_Sustancia._singular='Catálogo de Sustancias' -db.t_Sustancia._plural='Catálogo de Sustancias' \ No newline at end of file +db.t_Sustancia._plural='Catálogo de Sustancias' + + +""" +if db(db.t_Sustancia).isempty(): + db.t_Sustancia.insert(f_nombre='Acetato de Etilo', f_cas='141-78-6', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) + db.t_Sustancia.insert(f_nombre='Acetona', f_cas='67-64-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) + db.t_Sustancia.insert(f_nombre='Ácido Antranílico', f_cas='118-92-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Comburente']) + db.t_Sustancia.insert(f_nombre='Ácido Clorhídrico', f_cas='7647-01-0', f_pureza='37', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico','Corrosivo']) + db.t_Sustancia.insert(f_nombre='Ácido Fenilacético y sus sales', f_cas='103-82-2', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Comburente']) + db.t_Sustancia.insert(f_nombre='Ácido Nítrico', f_cas='7697-37-2', f_pureza='5', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Tóxico','Irritante']) + db.t_Sustancia.insert(f_nombre='Ácido Pícrico (trinitrofenol)', f_cas='88-89-1', f_pureza='3', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Ácido Sulfúrico', f_cas='7664-93-9', f_pureza='97', f_estado='Líquido', f_control='RL4 y RL7', f_peligrosidad=['Corrosivo','Irritante']) + db.t_Sustancia.insert(f_nombre='Aluminio en polvo', f_cas='7429-90-5', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable']) + db.t_Sustancia.insert(f_nombre='Amoníaco Anhídrico', f_cas='7664-41-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Inflamable']) + db.t_Sustancia.insert(f_nombre='Amoníaco en disolución acuosa', f_cas='001336-21-6', f_pureza='25', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico','Corrosivo']) + db.t_Sustancia.insert(f_nombre='Anhídrico acético', f_cas='108-24-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Nocivo']) + db.t_Sustancia.insert(f_nombre='Azidas (de sodio)', f_cas='26628-22-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) + db.t_Sustancia.insert(f_nombre='Benceno', f_cas='71-43-2', f_pureza='99', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Tóxico','Inflamable']) + db.t_Sustancia.insert(f_nombre='Butanona (metilcetona)', f_cas='78-93-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) + db.t_Sustancia.insert(f_nombre='Carbonato de Sodio', f_cas='497-19-8', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Corrosivo','Irritante']) + db.t_Sustancia.insert(f_nombre='Clorato de Potasio', f_cas='3811-04-9', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Clorato de Sodio', f_cas='7775-09-9', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Cloroformo', f_cas='67-66-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Diclorometano', f_cas='75-09-2', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Inflamable']) + db.t_Sustancia.insert(f_nombre='Dinitrofenol', f_cas='51-28-5', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Nocivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Dinitrotolueno', f_cas='606-20-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Nocivo']) + db.t_Sustancia.insert(f_nombre='Etanol', f_cas='64-17-5', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) + db.t_Sustancia.insert(f_nombre='Eter Etílico', f_cas='60-29-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Explosivo','Nocivo']) + db.t_Sustancia.insert(f_nombre='Fósforo blanco', f_cas='7723-14-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable','Nocivo']) + db.t_Sustancia.insert(f_nombre='Fulminato de Mercurio', f_cas='', f_pureza='', f_estado='', f_control='RL7', f_peligrosidad=['N/A']) + db.t_Sustancia.insert(f_nombre='Heptano', f_cas='142-82-5', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) + db.t_Sustancia.insert(f_nombre='Hexano', f_cas='110-54-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable']) + db.t_Sustancia.insert(f_nombre='Hidrogenocarbonato (Bicarbonato) de Sodio', f_cas='144-55-8', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Irritante']) + db.t_Sustancia.insert(f_nombre='Hipoclorito de calcio', f_cas='7778-54-3', f_pureza='68', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Irritante']) + db.t_Sustancia.insert(f_nombre='Hipoclorito de Sodio', f_cas='7681-52-9', f_pureza='', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Metanol', f_cas='67-56-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) + db.t_Sustancia.insert(f_nombre='Nitrato de Amonio (salitre de chile)', f_cas='6484-52-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo']) + db.t_Sustancia.insert(f_nombre='Nitrato de Bismuto', f_cas='7697-37-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrato de Calcio', f_cas='13477-34-4', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrato de Plata', f_cas='7761-88-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrato de Plomo', f_cas='10099-74-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrato de Potasio', f_cas='7757-79-1', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrato de Sodio', f_cas='7631-99-4', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrito de Sodio', f_cas='7632-00-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrobenceno', f_cas='98-95-3', f_pureza='99', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Nocivo','Tóxico']) + db.t_Sustancia.insert(f_nombre='Nitrocelulosa', f_cas='9004-70-0', f_pureza='12', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable']) + db.t_Sustancia.insert(f_nombre='Nitroglicerina', f_cas='55-63-0', f_pureza='1', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo']) + db.t_Sustancia.insert(f_nombre='Perclorato de Potasio', f_cas='7778-74-7', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) + db.t_Sustancia.insert(f_nombre='Perclorato de Sodio', f_cas='7601-89-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Nocivo']) + db.t_Sustancia.insert(f_nombre='Permanganato de Potasio', f_cas='7722-64-7', f_pureza='99', f_estado='Sólido', f_control='RL4 y RL7', f_peligrosidad=['Comburente','Corrosivo']) + db.t_Sustancia.insert(f_nombre='Sesquicarbonato de Sodio', f_cas='6106-20-3', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Corrosivo','Irritante']) + db.t_Sustancia.insert(f_nombre='Sulfato de Amonio', f_cas='7783-20-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Irritante']) + db.t_Sustancia.insert(f_nombre='Sulfato de Magnesio', f_cas='7487-88-9', f_pureza='65', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Irritante']) + db.t_Sustancia.insert(f_nombre='Sulfuro de Potasio', f_cas='1312-73-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable','Corrosivo']) + db.t_Sustancia.insert(f_nombre='Tetrahidrofurano', f_cas='109-99-9', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) + db.t_Sustancia.insert(f_nombre='Tolueno', f_cas='108-88-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) + db.t_Sustancia.insert(f_nombre='Trinitrotolueno (TNT)', f_cas='118-96-7', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo','Nocivo']) + db.t_Sustancia.insert(f_nombre='Urea', f_cas='57-13-6 ', f_pureza='', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Irritante','Comburente']) + db.t_Sustancia.insert(f_nombre='4-metilpentan-2-ona (Metilisobutilcetona)', f_cas='108-10-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico']) + db.t_Sustancia.insert(f_nombre='Fósforos rojos o amorfos', f_cas='7723-14-0', f_pureza='99', f_estado='Sólido', f_control='N/A', f_peligrosidad=['Inflamable','Nocivo']) +""" \ No newline at end of file diff --git a/static/css/smydp_catalogo.css b/static/css/smydp_catalogo.css new file mode 100755 index 00000000..64cfcf28 --- /dev/null +++ b/static/css/smydp_catalogo.css @@ -0,0 +1,88 @@ +select{ + border-top: 0px !important; + border-left: 0px !important; + border-right: 0px !important; + box-shadow: none !important; + border-radius: 0px !important; + border-bottom-width: 2px !important; + background-color: transparent !important; + +} + +th input[type=text]{ + border-top: 0px !important; + border-left: 0px !important; + border-right: 0px !important; + box-shadow: none !important; + border-bottom-width: 2px !important; + border-radius: 0px; + background-color: transparent; + height: 35px !important; + width: 100%; +} + +th { + width: 150px; +} + +#datatable_length select { + height: 30px; +} + +#collapseFiltros { + margin-top: 10px; + margin-bottom: 10px; +} + +#columnBotonAgregar { + text-align: right; +} + +.botonesListado { + background-color: #0300d7; + border-color: #0300d7; + color: white; +} + +.botonesListado:hover { + color: white; +} + +#containerAgregar{ + margin-top: -30px; +} + +#listadoContainer { + padding-top: 25px; +} + +.tablaListado { + border: 1.5px !important; + border-style: solid !important; + border-color: #ddd !important; +} + +#titulosListado { + background-color: #505050; +} + +.camposTabla { + text-align: center; +} + +.linksNombres { + color: white; +} + +.linksNombres:hover { + color: rgba(6, 164, 252, 1); + text-decoration: none; +} + +.filtros { + width: 200px; +} + +#filtroInput { + margin-left: 100px; +} \ No newline at end of file diff --git a/static/css/smydp_listado.css b/static/css/smydp_listado.css deleted file mode 100755 index 0efb2e0b..00000000 --- a/static/css/smydp_listado.css +++ /dev/null @@ -1,51 +0,0 @@ -.columnas { - text-align: center; -} - -#tituloBienvenida { - text-align: center; -} - -.iconos { - width: 130px; -} - -.opciones { - text-align: center; - color: #606060; -} - -.opciones:hover { - color: #909090; -} - -#fila2 { - padding: 30px 0 60px 0; - margin-top: 50px; -} - -.columnas>a:hover { - color: #0300d7; - text-decoration: none; -} - -.columnas>a { - color: black; -} - - -@media only screen and (max-width: 767px) { - - #main { - margin-top: 0; - } - - #fila1 { - padding: 0 0 20px 0; - } - - #fila2 { - padding: 30px 0 10px 0; - } - -} diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html index e69de29b..0af0cfaa 100644 --- a/views/smydp/catalogo.html +++ b/views/smydp/catalogo.html @@ -0,0 +1,15 @@ +{{extend 'layout.html'}} + +{{block head}} + +{{end}} + +{{block center}} + +
+
+

{{=table}}

+
+
+ +{{end}} \ No newline at end of file diff --git a/views/smydp/sustancias.html b/views/smydp/sustancias.html index f4ac55d9..ea68212f 100644 --- a/views/smydp/sustancias.html +++ b/views/smydp/sustancias.html @@ -16,9 +16,9 @@
+ From 5b9b6949ced7c2ad97be2cdd484dfc2319eefc54 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 22 Mar 2018 22:12:28 +0000 Subject: [PATCH 56/91] Fix: Jefes de seccion ya pueden ver sus espacios fisicos al navegar por la jerarquia de la ULAB (inventarios) --- controllers/modulos.py | 3 ++ controllers/smydp.py | 45 ++++++++++++++---------- static/css/tags.css | 5 --- views/modulos/ajax_eliminar_espacio.html | 2 +- views/modulos/ajax_mostrar_espacios.html | 2 +- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/controllers/modulos.py b/controllers/modulos.py index f350a190..a9a9bb82 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -223,6 +223,9 @@ def register(): rolid = request.post_vars.rol roltype = db(db.auth_group.id == int(rolid)).select(db.auth_group.ALL)[0].role + import pdb + pdb.set_trace() + if roltype == "TÉCNICO": # Se agregan los espacios fisicos seleccionados por el usuario (tags) a la tabla # 'es_encargado' diff --git a/controllers/smydp.py b/controllers/smydp.py index bc74e010..30e5b8e5 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -52,16 +52,16 @@ def find_dep_id(dependencias, nombre): # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion # de esta -def acceso_permitido(user_id, dep_id, es_espacio): +def acceso_permitido(user, dep_id, es_espacio): """ Args: - * user_id (): id del usuario en la tabla t_Personal (diferente de auth.user.id) - * dep_id (): id de la dependencia a la cual pertenece el recurso que se + * user_id (str): id del usuario en la tabla t_Personal (diferente de auth.user.id) + * dep_id (str): id de la dependencia a la cual pertenece el recurso que se desea acceder * es_espacio (str): 'True' si el usuario viene de seleccionar un espacio fisico """ - + # Valor a retornar que determina si el usuario tiene o no acceso al recurso permitido = False # dep_actual es un apuntador que permitira recorrer la jerarquia de dependencias @@ -117,21 +117,21 @@ def acceso_permitido(user_id, dep_id, es_espacio): @auth.requires_login(otherwise=URL('modulos', 'login')) def inventarios(): - import pdb - pdb.set_trace() - # Inicializando listas de espacios fisicos y dependencias espacios = [] dependencias = [] dep_nombre = "" es_espacio = False + import pdb + pdb.set_trace() + # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id - if auth.has_membership("TÉCNICO"): - # Si el tecnico ha seleccionado un espacio fisico + if auth.has_membership("TÉCNICO") or auth.has_membership("JEFE DE SECCIÓN"): + # Si el tecnico o jefe de seccion ha seleccionado un espacio fisico if request.vars.dependencia: # Evaluando la correctitud de los parametros del GET @@ -143,15 +143,22 @@ def inventarios(): # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias pass - # Si el tecnico no ha seleccionado un espacio sino que acaba de entrar - # a la opcion de inventarios + # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de + # entrar a la opcion de inventarios else: - # Buscando espacios fisicos que tengan a user_id como encargado en - # la tabla 'es_encargado' - espacios = list(db( - (db.es_encargado.tecnico == user_id) & - (db.es_encargado.espacio_fisico == db.espacios_fisicos.id)).select( - db.espacios_fisicos.ALL)) + # Si es un tecnico + if auth.has_membership("TÉCNICO"): + # Buscando espacios fisicos que tengan a user_id como encargado en + # la tabla 'es_encargado' + espacios = list(db( + (db.es_encargado.tecnico == user_id) & + (db.es_encargado.espacio_fisico == db.espacios_fisicos.id)).select( + db.espacios_fisicos.ALL)) + # Si es un jefe de seccion + else: + espacios = list(db( + db.espacios_fisicos.dependencia == user.f_dependencia + ).select(db.espacios_fisicos.ALL)) es_espacio = True # Si el usuario no es tecnico, para la base de datos es indiferente su ROL # pues la jerarquia de dependencias esta almacenada en la misma tabla @@ -167,7 +174,9 @@ def inventarios(): # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not acceso_permitido(user_id, int(request.vars.dependencia), request.vars.es_espacio): + if not acceso_permitido(user, + int(request.vars.dependencia), + request.vars.es_espacio): redirect(URL('inventarios')) if request.vars.es_espacio == "True": diff --git a/static/css/tags.css b/static/css/tags.css index bec634dc..79e73cbe 100644 --- a/static/css/tags.css +++ b/static/css/tags.css @@ -1,8 +1,3 @@ -.boton{ - padding-bottom: 5px; - display: inline-block; -} - .tag { margin-bottom: 0px !important; display: inline-block; diff --git a/views/modulos/ajax_eliminar_espacio.html b/views/modulos/ajax_eliminar_espacio.html index 858c282b..3fa28d3a 100644 --- a/views/modulos/ajax_eliminar_espacio.html +++ b/views/modulos/ajax_eliminar_espacio.html @@ -1,7 +1,7 @@ {{if tags:}}
{{for trace, espacio in tags.iteritems():}} - diff --git a/views/modulos/ajax_mostrar_espacios.html b/views/modulos/ajax_mostrar_espacios.html index 858c282b..3fa28d3a 100644 --- a/views/modulos/ajax_mostrar_espacios.html +++ b/views/modulos/ajax_mostrar_espacios.html @@ -1,7 +1,7 @@ {{if tags:}}
{{for trace, espacio in tags.iteritems():}} - From 0f2c53d03aa85e8f08029013008284b304a3d910 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 22 Mar 2018 22:50:05 +0000 Subject: [PATCH 57/91] Add: Agregando validacion de acceso a recursos por parte de tecnicos a espacios fisicos en la funcion acceso_permitido --- controllers/modulos.py | 5 ++++- controllers/smydp.py | 15 ++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/controllers/modulos.py b/controllers/modulos.py index a9a9bb82..ab4856ee 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -192,6 +192,9 @@ def register(): """ user = db(db.auth_user.email == request.post_vars.email).select(db.auth_user.ALL)[0] + import pdb + pdb.set_trace() + if request.post_vars.seccion: # El registrado pertenece directamente a una sección de un laboratorio. depid = request.post_vars.seccion @@ -214,7 +217,7 @@ def register(): f_telefono = 0, f_pagina_web = "N/A", f_categoria = "N/A", - f_cargo = "N/A", + f_cargo = "N/A", # *?* No deberia ser request.vars.rol? f_fecha_ingreso = "1/01/1989", f_fecha_salida = "1/02/1989", f_dependencia = depid) diff --git a/controllers/smydp.py b/controllers/smydp.py index 30e5b8e5..eb11861c 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -71,8 +71,9 @@ def acceso_permitido(user, dep_id, es_espacio): # Si el usuario es tecnico se busca en la tabla de es_encargado si el usuario # es encargado del espacio con id dep_id - if user.f_cargo == 'TÉCNICO': - pass + if auth.has_membership("TÉCNICO"): + if db(db.es_encargado.espacio_fisico == dep_id).select()[0].tecnico == user.id: + permitido = True else: # Dependencia a la que pertenece el usuario o que tiene a cargo @@ -123,9 +124,6 @@ def inventarios(): dep_nombre = "" es_espacio = False - import pdb - pdb.set_trace() - # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -139,6 +137,13 @@ def inventarios(): is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) + # Determinando si el usuario tiene privilegios suficientes para + # consultar la dependencia en request.vars.dependencia + if not acceso_permitido(user, + int(request.vars.dependencia), + request.vars.es_espacio): + redirect(URL('inventarios')) + # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias From 2c81bbd7c80e9481bf80c4b284bdb5a3d0042f72 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sat, 24 Mar 2018 23:38:43 +0000 Subject: [PATCH 58/91] Flecha de retorno funciona para webmaster --- controllers/smydp.py | 40 +++++++++++++++++++++--- static/css/smydp_inventarios.css | 52 +++++++++++++++++++++++++++++++ static/images/regresar.png | Bin 0 -> 15428 bytes views/smydp/inventarios.html | 47 ++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 static/images/regresar.png diff --git a/controllers/smydp.py b/controllers/smydp.py index eb11861c..0a57ad55 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -117,12 +117,15 @@ def acceso_permitido(user, dep_id, es_espacio): # a cargo @auth.requires_login(otherwise=URL('modulos', 'login')) def inventarios(): - + # Inicializando listas de espacios fisicos y dependencias espacios = [] dependencias = [] dep_nombre = "" + dep_padre_id = "" + dep_padre_nombre = "" es_espacio = False + direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] @@ -147,7 +150,14 @@ def inventarios(): # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias - pass + + # Guardando el ID y nombre de la dependencia a la que pertenece el + # espacio fisico visitado + dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia + ).select().first().dependencia + dep_padre_nombre = db(db.dependencias.id == dep_padre_id + ).select().first().nombre + # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios else: @@ -189,6 +199,14 @@ def inventarios(): espacio_id = request.vars.dependencia dep_nombre = db.espacios_fisicos(db.espacios_fisicos.id == espacio_id).nombre + # Guardando el ID y nombre de la dependencia padre para el link + # de navegacion de retorno + dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia + ).select().first().dependencia + dep_padre_nombre = db(db.dependencias.id == dep_padre_id + ).select().first().nombre + + else: # Se muestran las dependencias que componen a esta dependencia padre # y se lista el inventario agregado @@ -205,6 +223,16 @@ def inventarios(): db.espacios_fisicos.ALL)) es_espacio = True + #import pdb + #pdb.set_trace() + + # Guardando el ID y nombre de la dependencia padre para el link + # de navegacion de retorno + dep_padre_id = db(db.dependencias.id == request.vars.dependencia + ).select().first().unidad_de_adscripcion + dep_padre_nombre = db(db.dependencias.id == dep_padre_id + ).select().first().nombre + else: # Dependencia a la que pertenece el usuario o que tiene a cargo dep_id = user.f_dependencia @@ -212,13 +240,15 @@ def inventarios(): # Se muestran las dependencias que componen a la dependencia que # tiene a cargo el usuario y el inventario agregado de esta - dependencias = list(db(db.dependencias.unidad_de_adscripcion == dep_id).select( - db.dependencias.ALL)) + dependencias = list(db(db.dependencias.unidad_de_adscripcion == dep_id).select(db.dependencias.ALL)) return dict(dep_nombre=dep_nombre, dependencias=dependencias, espacios=espacios, - es_espacio=es_espacio) + es_espacio=es_espacio, + dep_padre_id=dep_padre_id, + dep_padre_nombre=dep_padre_nombre, + direccion_id=direccion_id) @auth.requires_login(otherwise=URL('modulos', 'login')) diff --git a/static/css/smydp_inventarios.css b/static/css/smydp_inventarios.css index 3d748d2b..9da90808 100755 --- a/static/css/smydp_inventarios.css +++ b/static/css/smydp_inventarios.css @@ -1,3 +1,55 @@ +h3[class="flecha"]{ + display: inline-block; +} + +.icono_regresar { + width: 40px; +} + +@media (max-width: @screen-xs) { + body{font-size: 10px;} +} + +@media (max-width: @screen-sm) { + body{font-size: 14px;} +} + +h3{ + font-size: 2em; +} + +.separador{ + height: 100px; +} + +.titulo{ + padding-top: 30px; + padding-bottom: 30px; + text-align: center; +} + +.dep-titulo{ + text-transform: uppercase; + text-align: center; + color: #464646; + display: inline-block; +} + +.boton-retorno{ + text-align: center; + border-color: #464646; + padding-left: 20px; +} + +/* +.titulo{ + text-transform: uppercase; + text-align: center; + padding: 20px 0px 30px 40px; + color: #464646; + display: inline-block; +}*/ + .columnas { text-align: center; padding-bottom: 20px; diff --git a/static/images/regresar.png b/static/images/regresar.png new file mode 100644 index 0000000000000000000000000000000000000000..65c7bc1b8876f25ad9f2f13bc679afc2d443e3f8 GIT binary patch literal 15428 zcmb_jdmvQl`=4&KA=PfF6kCxkp>iwNwzkVqv|Y$;_-;v(Mk@@1QMOu1YJ_s_CM#)* zN-|@}mWG&6CSk@cLuAGb#*8uZd(Sy@(PjVpoqx)ibKdj5@AEvL=k|Hyb~|m?n6-Eo z3Wd@@@Az#G3N;n{cPeV83ixLj_f`b{nI60uy>BMCB4-}@8-@BAh5qf=eYlLzZGjio zG)FOpSb6uYogW?~g^dnIXt?eEiA4zu+_XmT>W(;u^`01?r0%Wa$&Dy+t=3mn{ z&zkr9p-ZSZt#I6_-ItcT*-*;g&nEj<9h_@0H*RTXX)*iwlHYU&5-51f(GTgR{I?;v z`rN~HF0LW_NA`tD^Ly}m`RqDdzL36=9U+z8ziU^8Zm6gj&(zDU>8a}4LekgPfv>DU z6OGKIvGlH?|An4uztt(=BG<9-JY&N%zY$Z-yw*QRGTU>5S6&HUMeLjxbv2$5Gb_6O zn5qe1^aom6DAym#_RkZm%kJDsJvtgwzDKZRGxsyGJ=b-iI`TQ@d0SUj&U)N(|6IMX zq4hIn$Zm_skIEcRmf*rE-;>yG>dlF|KCNiHs_mNGksrT_})Mjq+kun|* zcc!Af1HKCC_fB!Q80%lEse;S^yA{JEii}59W6!}CVMNLJ&q()M^4H`HJ4rDyC?RAjHaayHgtwLCGXzv_I`)ekI^EeAtk?<@1- zicL|f?^@K{6}L^XhJWgzyB_Qha_{wYS#{`>Bse~0r7Ao%?B7hMwY+XlRaa&Fiqnn% z1UK7GCFOrUa470eWQk{cKW}rASS5_Va7As?uOJn=J{+M{z}upIvsi1RuwVEz$iZiE z^z}8u?1hWvQ!#Z;Yb&Eu8o-!AefGzbGd-pk+igUawPmC;Ok%KKNFKCCF2h(e>uI82h-gmBKD~S4UU@!}SyUh~6uMb_Mk(A$t*4KQ2nvUDOfI9v1A04-?Stm`NrJztQ~Lzk>FL2YJd z&W`oSUSb1X_bEpH0X?o=qT>Nrmd5{f;Cte&J%PEb(nFI zwq@1~&c&H;*c0^Yiu7Z`-Fx^h9ahiHK?wNcGzVd(qL?%FQbZoM*!(#e6(^UK4fSe1puu4wG|cq4MQ> z70~3ag-TJ_!aZP8_vDsCatrW89nh7l6+h+Ja`_-4ijP%Z&=RiIX+%Fd0{;z8qYMd% z;^&5_Wn-9g%FoZS&27%3Y84a$BMwuGTB9MeOA<3U&3-(WjGCDlW~F{ysq-7r9{NmR zNH_SQlZM$%DR^~RFQKx;-v36hTh67tj*6-CCw+yI>C;VPC03nlBs(t-F)rQS{;qvT z#f-^Mw7sHv=boUB%_{##Z|tE$6z}l(%SqHMcB+J*a#r^jM~T5%xv?`|Cmk;41alr; z73;6kNR@QCG?z?LjeRE3Y{H&odd;9P`?7clHrfczQj==7{|){XxljU3_QtA?CG`dn z?O_pMq?B#CZO-~a->D3xVKP1#+M%8{$+bRxCrogdAEaM!y6^V$6XpF1>zYgVAAQMkZLdPVC64X&@4SHV9V0zi0m%U);O$NU03 zp0EqeV|*+W_+BfsMYn2j^f`V~#;d{s&p*9S#zpUUkg$uRyR@le0p6kp?f$U|NEeQh z#nIB|eq)_e%h72>@zDMJu>Ph3gGN2!c4i;eppH_z)jdOO_`#AaCM--iE>15E<3#(< zr|JSV!EC|aRmow%{eLjGZR$B`$(+>T4 z^aL4#%Z7WXpc*}iF|f+O52aD#qhWe><0cM7djquVPD!d!jU>?#E9U;_JU|#(P4#YF zQwP3tN!;B&v0NUB<^!>ce@|VGQ-5xv1TmIn>K;5l5dW+CTu)nh?l9hVk!#gS=Ed zU$@aed)kV&Z{O~HSCYp=hCJJ$pRRuKT=8*i8;!87B%K(2gNtWa#Pb2PS*kmy1xiaV z1I6wiwYV$}rf;0+tI}za@(f8fW061Bbc%tS(x|NQxMc|Y6<3DEHL*!qsxUiZwAoLv zuMu7;b1hj3TLmpemw;8HiB&9ISE4lKc6MGN@|2HFZnHMQga(BKr#T@DAz0RUT|^Y$ z${u@om--N1Q|wU2tl|knwU{}P#c!$_fY)1Kfv0)@*?`Xu@443Ug5!~451dW~&Z)>y z^3WBE7pxIOnZ{qUQW|fO8SO3Jj;wAW9sObTP*3)hnVH4bFchlvTyv5TBRk6sr5}*B zRkxg9f^OJwOq#vGDs}&?Yl|~hKl&N6N9{{~wn9f@O<}HnI=olE0EZb z{+(TjpN=tS|A1i4G@b}rbrQZoK5RmUIApOPo`kyKa9URz1Q8hDen+0B{e;na3rKje zJl@2%&TfL8afUcuiI1+$qGWMS{gH0pBalL=f|4-zof6`evyRde`2(%X;pzR& zDDLKDBnd>@h6{czP}R}N`r%916t$166IvUDm)O5TYaFo!gS`${db*K{{s3UszeV3X z1;4yXiKZA6vYi2NpTurg^XnrZDm7)Bi+ZD1(@cJRx)Sea zbu3V!s z$^9otAuVmNztFsi8I0{1T*nL6k)!fg!vpro-d(0IechiVxOg$TFb|o`*^U{F=rdh0 zjJZoRN%u8Y3GscVcsyRW>0?=|TKWrU#o8CxX810SzVM7I2!bd`v_mBLWu@9B-LWi_ z24|1AR<2A@JZn87xVe7;@X*I^B<55At=9g7Cw;C}#;w}5CLY=#%Y|R#{R&}N5A593 z!@rK7w(~fzS3tqYBL08DzMj;{2J(AZ>tL-M{z5A?F8<^>2ePiqV(XzDQ0)1V{Ed^= zc(p><;tp-}ui@Wu)RsRdc4Gq|*#Q+y#V6v>xi7j+(Ed+{b&IR(j7~%0A5ofY3s2(r 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 N^j4?e?r-)v{eN;dA_V{d literal 0 HcmV?d00001 diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 12de58d9..e6b9270c 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -18,6 +18,53 @@ +
+ {{if dep_padre_id:}} +
+
+

{{=dep_padre_nombre}}

+ + {{if dep_padre_id == direccion_id:}} + + + + {{else:}} + + + + {{pass}} +
+ +
+

{{=dep_nombre}}

+
+ {{else:}} +
+

{{=dep_nombre}}

+
+ {{pass}} +
+ +
From 4a89ded486bdb6248e66d49523584e1f9b89d2b5 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sun, 25 Mar 2018 00:17:47 +0000 Subject: [PATCH 59/91] Falta arreglar la flecha cuando se visita un espacio fisico --- controllers/smydp.py | 19 +++++++++++++------ views/smydp/inventarios.html | 18 ------------------ 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 0a57ad55..88995e54 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -72,8 +72,9 @@ def acceso_permitido(user, dep_id, es_espacio): # Si el usuario es tecnico se busca en la tabla de es_encargado si el usuario # es encargado del espacio con id dep_id if auth.has_membership("TÉCNICO"): - if db(db.es_encargado.espacio_fisico == dep_id).select()[0].tecnico == user.id: - permitido = True + encargado = db(db.es_encargado.espacio_fisico == dep_id).select().first() + if encargado: + permitido = encargado.tecnico == user.id else: # Dependencia a la que pertenece el usuario o que tiene a cargo @@ -127,6 +128,9 @@ def inventarios(): es_espacio = False direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id + import pdb + pdb.set_trace() + # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -147,10 +151,9 @@ def inventarios(): request.vars.es_espacio): redirect(URL('inventarios')) - # Se muestra solo el inventario de ese espacio y no se muestran mas - # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia - # de dependencias - + dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia + ).select().first().nombre + # Guardando el ID y nombre de la dependencia a la que pertenece el # espacio fisico visitado dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia @@ -158,6 +161,10 @@ def inventarios(): dep_padre_nombre = db(db.dependencias.id == dep_padre_id ).select().first().nombre + # Se muestra solo el inventario de ese espacio y no se muestran mas + # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia + # de dependencias + # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios else: diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index e6b9270c..469099c7 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -48,24 +48,6 @@

{{=dep_nombre}}

{{pass}}
- -
From 5dd249f1f2cfeb88c3ce2bc726d3f66b3d0b2163 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sun, 25 Mar 2018 21:26:38 +0100 Subject: [PATCH 60/91] Fix: Navegacion de tecnicos al querer salir del espacio que se estaba consultado, solucionado --- controllers/smydp.py | 7 +++---- views/smydp/inventarios.html | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 88995e54..fa5145d1 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -126,11 +126,9 @@ def inventarios(): dep_padre_id = "" dep_padre_nombre = "" es_espacio = False + es_tecnico = auth.has_membership("TÉCNICO") direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id - import pdb - pdb.set_trace() - # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -255,7 +253,8 @@ def inventarios(): es_espacio=es_espacio, dep_padre_id=dep_padre_id, dep_padre_nombre=dep_padre_nombre, - direccion_id=direccion_id) + direccion_id=direccion_id, + es_tecnico=es_tecnico) @auth.requires_login(otherwise=URL('modulos', 'login')) diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 469099c7..b63e440f 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -19,14 +19,15 @@
- {{if dep_padre_id:}} + + {{if dep_padre_id and not es_tecnico:}}

{{=dep_padre_nombre}}

+ los permisos) simplemente se redirije a 'inventarios', pues de no hacerlo, se enviaran + request.vars.dependencia != None lo cual rompe con el flujo de ejecucion programado + en el controlador--> {{if dep_padre_id == direccion_id:}} @@ -41,6 +42,22 @@

{{=dep_nombre}}

+ + {{elif dep_padre_id and es_tecnico:}} +
+
+ +
+

{{=dep_nombre}}

+
+ {{else:}}

{{=dep_nombre}}

From d33ea09efb4e7532d2c67bd293841fb217518381 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sun, 25 Mar 2018 23:28:15 +0100 Subject: [PATCH 61/91] Fix: Ya se muestra el titulo en el caso de los tecnicos 'Espacio fisico' --- controllers/smydp.py | 5 +++++ views/smydp/inventarios.html | 27 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index fa5145d1..b6f1ef54 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -129,6 +129,9 @@ def inventarios(): es_tecnico = auth.has_membership("TÉCNICO") direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id + import pdb + pdb.set_trace() + # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -168,6 +171,7 @@ def inventarios(): else: # Si es un tecnico if auth.has_membership("TÉCNICO"): + # Buscando espacios fisicos que tengan a user_id como encargado en # la tabla 'es_encargado' espacios = list(db( @@ -180,6 +184,7 @@ def inventarios(): db.espacios_fisicos.dependencia == user.f_dependencia ).select(db.espacios_fisicos.ALL)) es_espacio = True + # Si el usuario no es tecnico, para la base de datos es indiferente su ROL # pues la jerarquia de dependencias esta almacenada en la misma tabla # con una lista de adyacencias diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index b63e440f..7563cb9e 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -19,7 +19,8 @@
- + {{if dep_padre_id and not es_tecnico:}}
@@ -42,26 +43,36 @@

{{=dep_nombre}}

- + a cargo el tecnico --> {{elif dep_padre_id and es_tecnico:}}
-

{{=dep_padre_nombre}}

+

ESPACIOS FÍSICOS

-

{{=dep_nombre}}

{{else:}} -
-

{{=dep_nombre}}

-
+ + {{if not es_tecnico:}} +
+

{{=dep_nombre}}

+
+ + {{else:}} +
+

ESPACIOS FÍSICOS

+
+ {{pass}} {{pass}}
From 678af8f63f151c7a006dfd887d45a093530f14d5 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sun, 25 Mar 2018 23:39:56 +0100 Subject: [PATCH 62/91] Clean: Arreglando vista de inventarios --- views/smydp/inventarios.html | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 7563cb9e..1d192450 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -19,10 +19,12 @@
- - {{if dep_padre_id and not es_tecnico:}} + + {{if dep_padre_id:}}
+ + {{if not es_tecnico:}}

{{=dep_padre_nombre}}

{{if dep_padre_id == direccion_id:}} - - - + + + {{else:}} - - - + + + {{pass}}
- -
-

{{=dep_nombre}}

-
- - {{elif dep_padre_id and es_tecnico:}} -
+ + {{else:}}

ESPACIOS FÍSICOS

+ {{pass}}

{{=dep_nombre}}

- + {{else:}} From 5f87aaf9396958abddbedf95bf8a3198d2c8ffb6 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 26 Mar 2018 23:21:03 +0100 Subject: [PATCH 63/91] Fix: Funciona con los jefes de seccion --- controllers/smydp.py | 72 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index b6f1ef54..b0098131 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -135,13 +135,15 @@ def inventarios(): # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id + user_dep_id = user.f_dependencia - if auth.has_membership("TÉCNICO") or auth.has_membership("JEFE DE SECCIÓN"): + if auth.has_membership("TÉCNICO"): # Si el tecnico o jefe de seccion ha seleccionado un espacio fisico if request.vars.dependencia: + # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.dependencias) and + if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) @@ -155,12 +157,14 @@ def inventarios(): dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia ).select().first().nombre + """ **!** Ver si esto es necesario en el caso de los tecnicos # Guardando el ID y nombre de la dependencia a la que pertenece el # espacio fisico visitado dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia ).select().first().dependencia dep_padre_nombre = db(db.dependencias.id == dep_padre_id ).select().first().nombre + """ # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia @@ -169,20 +173,60 @@ def inventarios(): # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios else: - # Si es un tecnico - if auth.has_membership("TÉCNICO"): - - # Buscando espacios fisicos que tengan a user_id como encargado en - # la tabla 'es_encargado' - espacios = list(db( - (db.es_encargado.tecnico == user_id) & - (db.es_encargado.espacio_fisico == db.espacios_fisicos.id)).select( - db.espacios_fisicos.ALL)) - # Si es un jefe de seccion + # Buscando espacios fisicos que tengan a user_id como encargado en + # la tabla 'es_encargado' + espacios = list(db( + (db.es_encargado.tecnico == user_id) & + (db.es_encargado.espacio_fisico == db.espacios_fisicos.id)).select( + db.espacios_fisicos.ALL)) + es_espacio = True + + elif auth.has_membership("JEFE DE SECCIÓN"): + # Si el tecnico o jefe de seccion ha seleccionado un espacio fisico + if request.vars.dependencia: + # Determinando si el usuario tiene privilegios suficientes para + # consultar la dependencia en request.vars.dependencia + if not acceso_permitido(user, + int(request.vars.dependencia), + request.vars.es_espacio): + redirect(URL('inventarios')) + if request.vars.es_espacio == 'True': + # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias + # Evaluando la correctitud de los parametros del GET + if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + is_bool(request.vars.es_espacio)): + redirect(URL('inventarios')) + + dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia).select().first().nombre + + # Guardando el ID y nombre de la dependencia a la que pertenece el + # espacio fisico visitado + dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia).select().first().dependencia + dep_padre_nombre = db(db.dependencias.id == dep_padre_id).select().first().nombre else: + # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias + # Evaluando la correctitud de los parametros del GET + if not (is_valid_id(request.vars.dependencia, db.dependencias) and + is_bool(request.vars.es_espacio)): + redirect(URL('inventarios')) + + dep_nombre = db(db.dependencias.id == request.vars.dependencia).select().first().nombre espacios = list(db( - db.espacios_fisicos.dependencia == user.f_dependencia - ).select(db.espacios_fisicos.ALL)) + db.espacios_fisicos.dependencia == user_dep_id + ).select(db.espacios_fisicos.ALL)) + # Se muestra solo el inventario de ese espacio y no se muestran mas + # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia + # de dependencias + + # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de + # entrar a la opcion de inventarios + else: + # *!* TERMINAR + espacios = list(db( + db.espacios_fisicos.dependencia == user_dep_id + ).select(db.espacios_fisicos.ALL)) + dep_nombre = db(db.dependencias.id == user_dep_id).select().first().nombre + es_espacio = True # Si el usuario no es tecnico, para la base de datos es indiferente su ROL From 8ee7f40630a53dcbca705926c3a2c882df769eca Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 26 Mar 2018 23:45:08 +0100 Subject: [PATCH 64/91] Fix: arreglado problema con tecnicos. Falta el bug con tecnicos cuando se regresa de un espacio --- controllers/smydp.py | 3 -- views/smydp/inventarios.html | 96 ++++++++++++++++++------------------ 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index b0098131..232720eb 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -129,9 +129,6 @@ def inventarios(): es_tecnico = auth.has_membership("TÉCNICO") direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id - import pdb - pdb.set_trace() - # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 1d192450..571cd736 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -19,61 +19,63 @@
- + + {{if es_tecnico:}} + + {{if espacios:}} +
+

ESPACIOS FÍSICOS

+
+ + {{else:}} +
+

ESPACIOS FÍSICOS

+ + + +
+
+

{{=dep_nombre}}

+
+
+ {{pass}} + + {{else:}} + {{if dep_padre_id:}} -
- - {{if not es_tecnico:}} -
-

{{=dep_padre_nombre}}

- - {{if dep_padre_id == direccion_id:}} - - - - {{else:}} - - - - {{pass}} -
- - {{else:}} -
-

ESPACIOS FÍSICOS

+
+

{{=dep_padre_nombre}}

+ + {{if dep_padre_id == direccion_id:}} -
- {{pass}} -
-

{{=dep_nombre}}

-
- + {{else:}} + + + + {{pass}} +
+
+

{{=dep_nombre}}

+
+
+ {{else:}} - - {{if not es_tecnico:}} -
-

{{=dep_nombre}}

-
- - {{else:}} -
-

ESPACIOS FÍSICOS

-
- {{pass}} +
+

{{=dep_nombre}}

+
{{pass}} + {{pass}}
+
From 23efa6d429e47b31ae8b5ba2518da5f49d2a9329 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Mar 2018 13:46:23 +0100 Subject: [PATCH 65/91] Fix: Arreglado problema con jefes de seccion en la navegacion del inventario --- controllers/smydp.py | 69 +++++++++++++++----------------- static/css/smydp_inventarios.css | 1 - views/smydp/inventarios.html | 4 +- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 232720eb..c010fc2a 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -153,16 +153,6 @@ def inventarios(): dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia ).select().first().nombre - - """ **!** Ver si esto es necesario en el caso de los tecnicos - # Guardando el ID y nombre de la dependencia a la que pertenece el - # espacio fisico visitado - dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia - ).select().first().dependencia - dep_padre_nombre = db(db.dependencias.id == dep_padre_id - ).select().first().nombre - """ - # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias @@ -180,45 +170,52 @@ def inventarios(): elif auth.has_membership("JEFE DE SECCIÓN"): # Si el tecnico o jefe de seccion ha seleccionado un espacio fisico - if request.vars.dependencia: + if request.vars.es_espacio == 'True': # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia if not acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) - if request.vars.es_espacio == 'True': - # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias - # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - is_bool(request.vars.es_espacio)): - redirect(URL('inventarios')) - dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia).select().first().nombre + # Evaluando la correctitud de los parametros del GET + if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + is_bool(request.vars.es_espacio)): + redirect(URL('inventarios')) - # Guardando el ID y nombre de la dependencia a la que pertenece el - # espacio fisico visitado - dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia).select().first().dependencia - dep_padre_nombre = db(db.dependencias.id == dep_padre_id).select().first().nombre - else: - # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias - # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.dependencias) and - is_bool(request.vars.es_espacio)): - redirect(URL('inventarios')) + dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia + ).select().first().nombre - dep_nombre = db(db.dependencias.id == request.vars.dependencia).select().first().nombre - espacios = list(db( - db.espacios_fisicos.dependencia == user_dep_id - ).select(db.espacios_fisicos.ALL)) + # Guardando el ID y nombre de la dependencia a la que pertenece el + # espacio fisico visitado + dep_padre_id = db(db.espacios_fisicos.id == request.vars.dependencia + ).select().first().dependencia + dep_padre_nombre = db(db.dependencias.id == dep_padre_id + ).select().first().nombre # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios + elif request.vars.es_espacio == 'False': + if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + is_bool(request.vars.es_espacio)): + redirect(URL('inventarios')) + # Determinando si el usuario tiene privilegios suficientes para + # consultar la dependencia en request.vars.dependencia + if not acceso_permitido(user, + int(request.vars.dependencia), + request.vars.es_espacio): + redirect(URL('inventarios')) + espacios = list(db( + db.espacios_fisicos.dependencia == user_dep_id + ).select(db.espacios_fisicos.ALL)) + dep_nombre = db(db.dependencias.id == user_dep_id).select().first().nombre + + es_espacio = True + else: - # *!* TERMINAR espacios = list(db( db.espacios_fisicos.dependencia == user_dep_id ).select(db.espacios_fisicos.ALL)) @@ -274,9 +271,6 @@ def inventarios(): db.espacios_fisicos.ALL)) es_espacio = True - #import pdb - #pdb.set_trace() - # Guardando el ID y nombre de la dependencia padre para el link # de navegacion de retorno dep_padre_id = db(db.dependencias.id == request.vars.dependencia @@ -291,7 +285,8 @@ def inventarios(): # Se muestran las dependencias que componen a la dependencia que # tiene a cargo el usuario y el inventario agregado de esta - dependencias = list(db(db.dependencias.unidad_de_adscripcion == dep_id).select(db.dependencias.ALL)) + dependencias = list(db(db.dependencias.unidad_de_adscripcion == dep_id + ).select(db.dependencias.ALL)) return dict(dep_nombre=dep_nombre, dependencias=dependencias, diff --git a/static/css/smydp_inventarios.css b/static/css/smydp_inventarios.css index 9da90808..21e62341 100755 --- a/static/css/smydp_inventarios.css +++ b/static/css/smydp_inventarios.css @@ -32,7 +32,6 @@ h3{ text-transform: uppercase; text-align: center; color: #464646; - display: inline-block; } .boton-retorno{ diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 571cd736..c673ea36 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -30,7 +30,7 @@

ESPACIOS FÍSICOS

{{else:}}
-

ESPACIOS FÍSICOS

+

ESPACIOS FÍSICOS

@@ -46,7 +46,7 @@

{{=dep_nombre}}

siguiente nivel superior de jerarquia --> {{if dep_padre_id:}}
-

{{=dep_padre_nombre}}

+

{{=dep_padre_nombre}}

- {{for seccion in lista:}} diff --git a/views/modulos/ajax_unidad_rol.html b/views/modulos/ajax_unidad_rol.html index 270d9073..09097e2b 100644 --- a/views/modulos/ajax_unidad_rol.html +++ b/views/modulos/ajax_unidad_rol.html @@ -1,8 +1,6 @@ {{if lista:}}
- {{for dependencia in lista:}} diff --git a/views/modulos/register.html b/views/modulos/register.html index e1495099..288b5d0d 100755 --- a/views/modulos/register.html +++ b/views/modulos/register.html @@ -105,10 +105,7 @@

Nuevo Usuario

- {{for rol in roles:}} @@ -177,7 +174,7 @@

¿Estás seguro que deseas cancelar el registro?

- + @@ -315,12 +312,19 @@

¿Estás seguro que deseas cancelar el registro?

var x = document.getElementById("esphidden"); x.value = espacioelegido; - ajax('ajax_mostrar_espacios', ['rolhidden', + ajax('ajax_agregar_espacio', ['rolhidden', 'dephidden', 'seccionhidden', 'esphidden'], 'tagsdiv'); } + function showEspacios(){ + /* + Esta funcion es llamada para mostrar los espacios que actualmente se han seleccionado + */ + ajax('ajax_mostrar_espacios', [], 'tagsdiv'); + } + function deleteEspacio(espacio_id){ var x = document.getElementById("borrarhidden"); diff --git a/views/servicios/listado.html b/views/servicios/listado.html index 019a7fd2..3dd4530b 100644 --- a/views/servicios/listado.html +++ b/views/servicios/listado.html @@ -31,7 +31,7 @@ Listado
- +
From 27dd531d2871480a4285f6e1ae3293ac083b4eba Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Mar 2018 18:14:22 +0100 Subject: [PATCH 70/91] Commit fantasma --- views/modulos/register.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/views/modulos/register.html b/views/modulos/register.html index 288b5d0d..3ac0c9f6 100755 --- a/views/modulos/register.html +++ b/views/modulos/register.html @@ -105,7 +105,10 @@

Nuevo Usuario

- {{for rol in roles:}} From b98c0fa703569890f0807a6e1e18dca478ffec28 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Mar 2018 19:36:03 +0100 Subject: [PATCH 71/91] Commit fantasma. Medio funciona --- views/modulos/ajax_mostrar_espacios.html | 10 ++++++++++ views/modulos/ajax_registro_seccion.html | 3 ++- views/modulos/ajax_unidad_rol.html | 4 +++- views/modulos/register.html | 17 +++++------------ 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/views/modulos/ajax_mostrar_espacios.html b/views/modulos/ajax_mostrar_espacios.html index e69de29b..3fa28d3a 100644 --- a/views/modulos/ajax_mostrar_espacios.html +++ b/views/modulos/ajax_mostrar_espacios.html @@ -0,0 +1,10 @@ +{{if tags:}} +
+ {{for trace, espacio in tags.iteritems():}} + + {{pass}} +
+{{pass}} \ No newline at end of file diff --git a/views/modulos/ajax_registro_seccion.html b/views/modulos/ajax_registro_seccion.html index 67cbad3f..a2460b1e 100644 --- a/views/modulos/ajax_registro_seccion.html +++ b/views/modulos/ajax_registro_seccion.html @@ -1,7 +1,8 @@ {{if lista:}}
- {{for seccion in lista:}} diff --git a/views/modulos/ajax_unidad_rol.html b/views/modulos/ajax_unidad_rol.html index 09097e2b..270d9073 100644 --- a/views/modulos/ajax_unidad_rol.html +++ b/views/modulos/ajax_unidad_rol.html @@ -1,6 +1,8 @@ {{if lista:}}
- {{for dependencia in lista:}} diff --git a/views/modulos/register.html b/views/modulos/register.html index 3ac0c9f6..21c05607 100755 --- a/views/modulos/register.html +++ b/views/modulos/register.html @@ -105,10 +105,10 @@

Nuevo Usuario

- {{for rol in roles:}} @@ -315,19 +315,12 @@

¿Estás seguro que deseas cancelar el registro?

var x = document.getElementById("esphidden"); x.value = espacioelegido; - ajax('ajax_agregar_espacio', ['rolhidden', + ajax('ajax_mostrar_espacios', ['rolhidden', 'dephidden', 'seccionhidden', 'esphidden'], 'tagsdiv'); } - function showEspacios(){ - /* - Esta funcion es llamada para mostrar los espacios que actualmente se han seleccionado - */ - ajax('ajax_mostrar_espacios', [], 'tagsdiv'); - } - function deleteEspacio(espacio_id){ var x = document.getElementById("borrarhidden"); From eab8565d0700a1efdde3a6169a7474c2567d7ac5 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Mar 2018 20:00:58 +0100 Subject: [PATCH 72/91] Fix: Bug de espacios repetidos solucionado --- controllers/modulos.py | 20 ++++---------------- views/modulos/ajax_registro_seccion.html | 3 +-- views/modulos/ajax_unidad_rol.html | 2 +- views/modulos/register.html | 6 +++++- 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/controllers/modulos.py b/controllers/modulos.py index c6a687d2..991a5f2a 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -191,7 +191,7 @@ def register(): en la tabla "es_tecnico" si el usuario tiene el rol de tecnico. """ user = db(db.auth_user.email == request.post_vars.email).select(db.auth_user.ALL)[0] - + if request.post_vars.seccion: # El registrado pertenece directamente a una sección de un laboratorio. depid = request.post_vars.seccion @@ -319,14 +319,10 @@ def ajax_registro_espacio(): return dict(lista=espacios) + # Guardando los espacios seleccionados por el usuario para guardar en la case de datos # aquellos espacios de los que el tecnico es responsable -def ajax_agregar_espacio(): - - print "\nMOSTRAR" - print "request.vars", request.vars - print "session.tags", session.tags - print "\n" +def ajax_mostrar_espacios(): rolid = request.post_vars.rolhidden roltype = db(db.auth_group.id == int(rolid)).select(db.auth_group.ALL)[0].role @@ -351,19 +347,11 @@ def ajax_agregar_espacio(): # espacio que se desea eliminar def ajax_eliminar_espacio(): - print "\ELIMINAR" - print "request.vars", request.vars - print "session.tags", session.tags - print "\n" - espid = request.post_vars.borrarhidden session.tags.pop(espid) return dict(tags=session.tags) -# Muestra los espacios seleccionados sin realizar ninguna operacion. Se usa cuando hay -# que actualizar la lista de espacios seleccionados, por ejemplo, si al registrar el -# usuario se cambia el rol -def ajax_eliminar_espacio(): +def ajax_prueba(): # Los tags se mostraran solo si el usuario es un tecnico if roltype != "TÉCNICO": diff --git a/views/modulos/ajax_registro_seccion.html b/views/modulos/ajax_registro_seccion.html index a2460b1e..67cbad3f 100644 --- a/views/modulos/ajax_registro_seccion.html +++ b/views/modulos/ajax_registro_seccion.html @@ -1,8 +1,7 @@ {{if lista:}}
- {{for seccion in lista:}} diff --git a/views/modulos/ajax_unidad_rol.html b/views/modulos/ajax_unidad_rol.html index 270d9073..a852a0fd 100644 --- a/views/modulos/ajax_unidad_rol.html +++ b/views/modulos/ajax_unidad_rol.html @@ -2,7 +2,7 @@
+ prueba();"> {{for rol in roles:}} @@ -329,6 +329,10 @@

¿Estás seguro que deseas cancelar el registro?

ajax('ajax_eliminar_espacio', ["borrarhidden"], 'tagsdiv'); } + function prueba(){ + ajax('ajax_prueba', [], 'tagsdiv'); + } + function mostrarContrasena(idContrasena) { var idContrasena = idContrasena var x = document.getElementById(idContrasena); From 96801048c854c610e548c4f2ae463cbac894eb99 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 27 Mar 2018 21:58:52 +0100 Subject: [PATCH 73/91] Fix: Arreglado bug al cambiar rol seguian los espacios seleccionados --- controllers/modulos.py | 7 +++++-- views/modulos/ajax_seleccionar_espacio.html | 10 ++++++++++ views/modulos/ajax_unidad_rol.html | 2 +- views/modulos/register.html | 17 ++++++++++------- 4 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 views/modulos/ajax_seleccionar_espacio.html diff --git a/controllers/modulos.py b/controllers/modulos.py index 991a5f2a..43792996 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -322,7 +322,7 @@ def ajax_registro_espacio(): # Guardando los espacios seleccionados por el usuario para guardar en la case de datos # aquellos espacios de los que el tecnico es responsable -def ajax_mostrar_espacios(): +def ajax_seleccionar_espacio(): rolid = request.post_vars.rolhidden roltype = db(db.auth_group.id == int(rolid)).select(db.auth_group.ALL)[0].role @@ -351,8 +351,11 @@ def ajax_eliminar_espacio(): session.tags.pop(espid) return dict(tags=session.tags) -def ajax_prueba(): +def ajax_mostrar_espacios(): + rolid = request.post_vars.rolhidden + roltype = db(db.auth_group.id == int(rolid)).select(db.auth_group.ALL)[0].role + # Los tags se mostraran solo si el usuario es un tecnico if roltype != "TÉCNICO": session.tags = {} diff --git a/views/modulos/ajax_seleccionar_espacio.html b/views/modulos/ajax_seleccionar_espacio.html new file mode 100644 index 00000000..3fa28d3a --- /dev/null +++ b/views/modulos/ajax_seleccionar_espacio.html @@ -0,0 +1,10 @@ +{{if tags:}} +
+ {{for trace, espacio in tags.iteritems():}} + + {{pass}} +
+{{pass}} \ No newline at end of file diff --git a/views/modulos/ajax_unidad_rol.html b/views/modulos/ajax_unidad_rol.html index a852a0fd..41bf2294 100644 --- a/views/modulos/ajax_unidad_rol.html +++ b/views/modulos/ajax_unidad_rol.html @@ -2,7 +2,7 @@
+ showEspacio();"> {{for rol in roles:}} @@ -315,10 +315,10 @@

¿Estás seguro que deseas cancelar el registro?

var x = document.getElementById("esphidden"); x.value = espacioelegido; - ajax('ajax_mostrar_espacios', ['rolhidden', - 'dephidden', - 'seccionhidden', - 'esphidden'], 'tagsdiv'); + ajax('ajax_seleccionar_espacio', ['rolhidden', + 'dephidden', + 'seccionhidden', + 'esphidden'], 'tagsdiv'); } function deleteEspacio(espacio_id){ @@ -329,8 +329,11 @@

¿Estás seguro que deseas cancelar el registro?

ajax('ajax_eliminar_espacio', ["borrarhidden"], 'tagsdiv'); } - function prueba(){ - ajax('ajax_prueba', [], 'tagsdiv'); + function showEspacio(){ + var opcionesrol = document.getElementById("rol"); + var rolelegida = opcionesrol.options[opcionesrol.selectedIndex].value; + + ajax('ajax_mostrar_espacios', ['rolhidden'], 'tagsdiv'); } function mostrarContrasena(idContrasena) { From 0b95af1ddfc474f2ec8f308ef95df3ab0c2e2da3 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 29 Mar 2018 01:58:20 +0100 Subject: [PATCH 74/91] Fix: Modulo de servicios no mostraba solicitud cuando el espacio fisico no era especificado --- controllers/modulos.py | 5 +---- controllers/servicios.py | 5 +++++ models/smydp.py | 22 ++++++++++++++++------ modules/servicios_libreria.py | 13 ++++++++++--- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/controllers/modulos.py b/controllers/modulos.py index 43792996..627a563c 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -222,10 +222,7 @@ def register(): # Mapea el usuario al espacio fisico que tiene a cargo rolid = request.post_vars.rol roltype = db(db.auth_group.id == int(rolid)).select(db.auth_group.ALL)[0].role - - import pdb - pdb.set_trace() - + if roltype == "TÉCNICO": # Se agregan los espacios fisicos seleccionados por el usuario (tags) a la tabla # 'es_encargado' diff --git a/controllers/servicios.py b/controllers/servicios.py index 0657f755..27b9dbef 100755 --- a/controllers/servicios.py +++ b/controllers/servicios.py @@ -497,6 +497,11 @@ def catalogoServicios(): @auth.requires_login(otherwise=URL('modulos', 'login')) def ajax_ficha_servicio(): + # Ver en que momento se esta agregando el espacio fisico cuando se llena la forma del nuevo servicio + # En servicios_libreria.py da error en query.ficha() linea + # ubicrow = db(entrada[0].ubicacion == db.espacios_fisicos.id).select(db.espacios_fisicos.ALL) + import pdb + pdb.set_trace() session.forget(response) # Servicio diff --git a/models/smydp.py b/models/smydp.py index 20d6c024..cd955f73 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -1,19 +1,29 @@ -#------------------------------------ Modulo de Sustancias, materiales y desechos peligrosos------------------------------------------- +#------------------------------------ Modulo de Sustancias, materiales y desechos peligrosos ------------------------------------------- #t_Sustancia: Tabla de sustancias de la cual se obtiene informacion del listado (catalogo de sustancias) db.define_table( #Nombre de la entidad 't_Sustancia', + #Atributos; - Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), - Field('f_cas', 'string', requires=[ IS_NOT_EMPTY(), - IS_MATCH('^[0-9]+\-[0-9]+\-[0-9]+$', - error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], unique=True, label=T('CAS')), + Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), + + Field('f_cas', 'string', requires=[ IS_NOT_EMPTY(), + IS_MATCH('^[0-9]+\-[0-9]+\-[0-9]+$', + error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], + unique=True, label=T('CAS')), + Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), + Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.options.widget, label=T('Estado')), + Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.options.widget, label=T('Control')), - Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), + + Field('f_peligrosidad', 'list:string', + requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'], + multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), + # Hoja de seguridad (archivo pdf) Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad'), format='%(f_nombre)s'), # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla diff --git a/modules/servicios_libreria.py b/modules/servicios_libreria.py index b178a03c..2c85949f 100644 --- a/modules/servicios_libreria.py +++ b/modules/servicios_libreria.py @@ -1539,9 +1539,16 @@ def query_ficha(db, idv): sedeid = sederow[0].id # Ubicacion Fisica - ubicrow = db(entrada[0].ubicacion == db.espacios_fisicos.id).select(db.espacios_fisicos.ALL) - ubicacion = ubicrow[0].codigo - ubicacionid = ubicrow[0].id + """ + *!* ERROR? si no fue seleccionado un espacio fisico, explota + """ + ubicrow = '' + ubicacion = '' + ubicacionid = '' + if entrada[0].ubicacion: + ubicrow = db(entrada[0].ubicacion == db.espacios_fisicos.id).select(db.espacios_fisicos.ALL) + ubicacion = ubicrow[0].codigo + ubicacionid = ubicrow[0].id # Responsable resprow = db(entrada[0].responsable == db.t_Personal.id).select(db.t_Personal.ALL) From ec26627f7db0eddd757b73149939e30465d7eae6 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 29 Mar 2018 01:59:16 +0100 Subject: [PATCH 75/91] Fix: Mismo commit anterior, borrando import pdb --- controllers/servicios.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/controllers/servicios.py b/controllers/servicios.py index 27b9dbef..38b36070 100755 --- a/controllers/servicios.py +++ b/controllers/servicios.py @@ -497,11 +497,7 @@ def catalogoServicios(): @auth.requires_login(otherwise=URL('modulos', 'login')) def ajax_ficha_servicio(): - # Ver en que momento se esta agregando el espacio fisico cuando se llena la forma del nuevo servicio - # En servicios_libreria.py da error en query.ficha() linea - # ubicrow = db(entrada[0].ubicacion == db.espacios_fisicos.id).select(db.espacios_fisicos.ALL) - import pdb - pdb.set_trace() + session.forget(response) # Servicio From b3cedd9538ce8613d741a9841dd4f20b12a9aa69 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 29 Mar 2018 10:12:49 +0100 Subject: [PATCH 76/91] Add: Creando includes de los inventarios dependiendo de si es un espacio o una dependencia --- controllers/smydp.py | 21 ++++++++++++++++++++- views/smydp/inventario_dependencia.html | 1 + views/smydp/inventario_espacio.html | 1 + views/smydp/inventarios.html | 10 ++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 views/smydp/inventario_dependencia.html create mode 100644 views/smydp/inventario_espacio.html diff --git a/controllers/smydp.py b/controllers/smydp.py index 8a04d761..b2653ae8 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -136,10 +136,23 @@ def inventarios(): dep_nombre = "" dep_padre_id = "" dep_padre_nombre = "" + + # Esta variable es enviada a la vista para que cuando el usuario seleccione + # un espacio fisico, se pase por GET es_espacio = "True". No quiere decir + # que la dependencia seleccionada sea un espacio, sino que la siguiente + # dependencia visitada sera un espacio fisico es_espacio = False + + # Permite saber si actualmente se esta visitando un espacio fisico (True) + # o una dependencia (False) + espacio_visitado = False + es_tecnico = auth.has_membership("TÉCNICO") direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id + # Lista de sustancias en el inventario del espacio fisico visitado + sustancias = [] + # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -149,7 +162,6 @@ def inventarios(): # Si el tecnico o jefe de seccion ha seleccionado un espacio fisico if request.vars.dependencia: - # **!** VERIFICAR si es db.espacios_fisicos o db.dependencias # Evaluando la correctitud de los parametros del GET if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and is_bool(request.vars.es_espacio)): @@ -164,6 +176,8 @@ def inventarios(): dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia ).select().first().nombre + + espacio_visitado = True # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias @@ -203,6 +217,8 @@ def inventarios(): ).select().first().dependencia dep_padre_nombre = db(db.dependencias.id == dep_padre_id ).select().first().nombre + + espacio_visitado = True # Se muestra solo el inventario de ese espacio y no se muestran mas # dependencias pues ya se alcanzo el nivel mas bajo de la jerarquia # de dependencias @@ -267,6 +283,8 @@ def inventarios(): dep_padre_nombre = db(db.dependencias.id == dep_padre_id ).select().first().nombre + espacio_visitado = True + else: # Se muestran las dependencias que componen a esta dependencia padre @@ -305,6 +323,7 @@ def inventarios(): dependencias=dependencias, espacios=espacios, es_espacio=es_espacio, + espacio_visitado=espacio_visitado, dep_padre_id=dep_padre_id, dep_padre_nombre=dep_padre_nombre, direccion_id=direccion_id, diff --git a/views/smydp/inventario_dependencia.html b/views/smydp/inventario_dependencia.html new file mode 100644 index 00000000..9ca06c22 --- /dev/null +++ b/views/smydp/inventario_dependencia.html @@ -0,0 +1 @@ +
SOY UNA DEPENDENCIA
\ No newline at end of file diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html new file mode 100644 index 00000000..0dd3944a --- /dev/null +++ b/views/smydp/inventario_espacio.html @@ -0,0 +1 @@ +
SOY UN ESPACIO
\ No newline at end of file diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index c673ea36..92abbad2 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -112,6 +112,16 @@

{{=dep_nombre}}

{{k=k+1}} {{pass}}
+ + + +{{if espacio_visitado:}} + {{include 'smydp/inventario_espacio.html'}} + +{{else:}} + {{include 'smydp/inventario_dependencia.html'}} +{{pass}} + + + + {{end}} {{block center}} @@ -18,6 +34,7 @@ +
{{if es_tecnico:}} @@ -113,18 +130,85 @@

{{=dep_nombre}}

{{pass}}
+ + + + + + {{if espacio_visitado:}} + {{include 'smydp/inventario_espacio.html'}} + + {{else:}} + {{include 'smydp/inventario_dependencia.html'}} + {{pass}} - -{{if espacio_visitado:}} - {{include 'smydp/inventario_espacio.html'}} - -{{else:}} - {{include 'smydp/inventario_dependencia.html'}} -{{pass}} + + + + + + + + + + + + + + + + + + + + + {{end}} \ No newline at end of file From 2a9b7b76562c6a7e4b53aeda4faa77013c45b7d2 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Fri, 30 Mar 2018 10:32:36 +0100 Subject: [PATCH 78/91] Cambiando funciones que no son controladores por '__' --- controllers/smydp.py | 58 ++++++++++++++++++----------- views/smydp/inventario_espacio.html | 7 +++- views/smydp/inventarios.html | 32 ++++++++++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index b2653ae8..300836b7 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -2,17 +2,23 @@ # Controladores provisionales utilizados solo para probar las vistas del modulo de SMyDP # # - Samuel Arleo +# +# - Convenciones: +# * Funciones "privadas" utilizadas por los controladores y decoradores tienen el +# prefijo "-" +# * Controladores no poseen prefijos +# #----------------------------------------------------------------------------- # Verifica si el usuario que intenta acceder al controlador tiene alguno de los # roles necesarios -def check_role(): +def _check_role(): roles_permitidos = ['WEBMASTER', 'DIRECTOR', 'ASISTENTE DEL DIRECTOR', 'JEFE DE LABORATORIO', 'JEFE DE SECCIÓN', 'TÉCNICO', 'GESTOR DE SMyDP'] return True in map(lambda x: auth.has_membership(x), roles_permitidos) - + @auth.requires_login(otherwise=URL('modulos', 'login')) def index(): @@ -25,7 +31,7 @@ def sustancias(): # Determina si el id de la dependencia es valido. Retorna False si el id no existe # o es de un tipo incorrecto -def is_valid_id(id_, tabla): +def _is_valid_id(id_, tabla): try: int(id_) except: @@ -38,7 +44,7 @@ def is_valid_id(id_, tabla): # Determina si una variable "booleana" pasada como parametro con GET es realmente # 'True' o 'False' (request.vars almacena todo como strings) -def is_bool(bool_var): +def _is_bool(bool_var): if not bool_var in ['True', 'False']: return False else: @@ -46,7 +52,7 @@ def is_bool(bool_var): # Dado el nombre de una dependencia, retorna el id de esta si la encuentra o # None si no lo hace -def find_dep_id(dependencias, nombre): +def _find_dep_id(dependencias, nombre): dep_id = None encontrado = False @@ -61,7 +67,7 @@ def find_dep_id(dependencias, nombre): # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion # de esta -def acceso_permitido(user, dep_id, es_espacio): +def _acceso_permitido(user, dep_id, es_espacio): """ Args: * user_id (str): id del usuario en la tabla t_Personal (diferente de auth.user.id) @@ -100,7 +106,7 @@ def acceso_permitido(user, dep_id, es_espacio): lista_adyacencias = {row.id: row.unidad_de_adscripcion for row in dependencias} # Buscando el id de la direccion para saber si ya se llego a la raiz - direccion_id = find_dep_id(dependencias, 'DIRECCIÓN') + direccion_id = _find_dep_id(dependencias, 'DIRECCIÓN') # Si dep_id es un espacio fisico, se sube un nivel en la jerarquia (hasta # las secciones) ya que los espacios fisicos no aparecen en la lista de @@ -126,7 +132,7 @@ def acceso_permitido(user, dep_id, es_espacio): # Muestra el inventario de acuerdo al cargo del usuario y la dependencia que tiene # a cargo -@auth.requires(lambda: check_role()) +@auth.requires(lambda: _check_role()) @auth.requires_login(otherwise=URL('modulos', 'login')) def inventarios(): @@ -136,6 +142,10 @@ def inventarios(): dep_nombre = "" dep_padre_id = "" dep_padre_nombre = "" + + # Lista de sustancias en el inventario de un espacio fisico o que componen + # el inventario agregado de una dependencia + sustancias = [] # Esta variable es enviada a la vista para que cuando el usuario seleccione # un espacio fisico, se pase por GET es_espacio = "True". No quiere decir @@ -148,7 +158,7 @@ def inventarios(): espacio_visitado = False es_tecnico = auth.has_membership("TÉCNICO") - direccion_id = db(db.dependencias.nombre == 'DIRECCIÓN').select().first().id + direccion_id = _find_dep_id(dependencias, 'DIRECCIÓN') # Lista de sustancias en el inventario del espacio fisico visitado sustancias = [] @@ -163,13 +173,13 @@ def inventarios(): if request.vars.dependencia: # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - is_bool(request.vars.es_espacio)): + if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + _is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not acceso_permitido(user, + if not _acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) @@ -198,14 +208,14 @@ def inventarios(): if request.vars.es_espacio == 'True': # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not acceso_permitido(user, + if not _acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - is_bool(request.vars.es_espacio)): + if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + _is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia @@ -226,12 +236,12 @@ def inventarios(): # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios elif request.vars.es_espacio == 'False': - if not (is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - is_bool(request.vars.es_espacio)): + if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + _is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not acceso_permitido(user, + if not _acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) @@ -260,13 +270,13 @@ def inventarios(): if request.vars.dependencia: # Evaluando la correctitud de los parametros del GET - if not (is_valid_id(request.vars.dependencia, db.dependencias) and - is_bool(request.vars.es_espacio)): + if not (_is_valid_id(request.vars.dependencia, db.dependencias) and + _is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not acceso_permitido(user, + if not _acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) @@ -285,6 +295,9 @@ def inventarios(): espacio_visitado = True + # Se muestra la lista de sustancias que tiene en inventario + sustancias = + else: # Se muestran las dependencias que componen a esta dependencia padre @@ -327,7 +340,8 @@ def inventarios(): dep_padre_id=dep_padre_id, dep_padre_nombre=dep_padre_nombre, direccion_id=direccion_id, - es_tecnico=es_tecnico) + es_tecnico=es_tecnico, + sustancias=sustancias) @auth.requires_login(otherwise=URL('modulos', 'login')) diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 8c1a893c..3f449794 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -57,7 +57,7 @@

Listado de Servicios

{{=sustancia['f_estado']}} {{=sustancia['f_existencia']}} {{=sustancia['f_unidad']}} - {{int(sustancia['f_existencia']) - int(sustancia['f_excedente'])}} + {{=int(sustancia['f_existencia']) - int(sustancia['f_excedente'])}} {{=sustancia['f_excedente']}} {{pass}} @@ -80,4 +80,7 @@

Listado de Servicios

- \ No newline at end of file + + + + diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index ea776631..7004ee40 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -211,4 +211,36 @@

{{=dep_nombre}}

} + + + {{end}} \ No newline at end of file From 981d8aed0c739c04d10723a6f21db58e14b2e24e Mon Sep 17 00:00:00 2001 From: saar1312 Date: Fri, 30 Mar 2018 10:32:46 +0100 Subject: [PATCH 79/91] Cambiando funciones que no son controladores por '__' --- controllers/smydp.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 300836b7..5910ec74 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -5,14 +5,14 @@ # # - Convenciones: # * Funciones "privadas" utilizadas por los controladores y decoradores tienen el -# prefijo "-" +# prefijo "__" # * Controladores no poseen prefijos # #----------------------------------------------------------------------------- # Verifica si el usuario que intenta acceder al controlador tiene alguno de los # roles necesarios -def _check_role(): +def __check_role(): roles_permitidos = ['WEBMASTER', 'DIRECTOR', 'ASISTENTE DEL DIRECTOR', 'JEFE DE LABORATORIO', 'JEFE DE SECCIÓN', 'TÉCNICO', @@ -31,7 +31,7 @@ def sustancias(): # Determina si el id de la dependencia es valido. Retorna False si el id no existe # o es de un tipo incorrecto -def _is_valid_id(id_, tabla): +def __is_valid_id(id_, tabla): try: int(id_) except: @@ -44,7 +44,7 @@ def _is_valid_id(id_, tabla): # Determina si una variable "booleana" pasada como parametro con GET es realmente # 'True' o 'False' (request.vars almacena todo como strings) -def _is_bool(bool_var): +def __is_bool(bool_var): if not bool_var in ['True', 'False']: return False else: @@ -52,7 +52,7 @@ def _is_bool(bool_var): # Dado el nombre de una dependencia, retorna el id de esta si la encuentra o # None si no lo hace -def _find_dep_id(dependencias, nombre): +def __find_dep_id(dependencias, nombre): dep_id = None encontrado = False @@ -67,7 +67,7 @@ def _find_dep_id(dependencias, nombre): # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion # de esta -def _acceso_permitido(user, dep_id, es_espacio): +def __acceso_permitido(user, dep_id, es_espacio): """ Args: * user_id (str): id del usuario en la tabla t_Personal (diferente de auth.user.id) @@ -106,7 +106,7 @@ def _acceso_permitido(user, dep_id, es_espacio): lista_adyacencias = {row.id: row.unidad_de_adscripcion for row in dependencias} # Buscando el id de la direccion para saber si ya se llego a la raiz - direccion_id = _find_dep_id(dependencias, 'DIRECCIÓN') + direccion_id = __find_dep_id(dependencias, 'DIRECCIÓN') # Si dep_id es un espacio fisico, se sube un nivel en la jerarquia (hasta # las secciones) ya que los espacios fisicos no aparecen en la lista de @@ -132,7 +132,7 @@ def _acceso_permitido(user, dep_id, es_espacio): # Muestra el inventario de acuerdo al cargo del usuario y la dependencia que tiene # a cargo -@auth.requires(lambda: _check_role()) +@auth.requires(lambda: __check_role()) @auth.requires_login(otherwise=URL('modulos', 'login')) def inventarios(): @@ -158,7 +158,7 @@ def inventarios(): espacio_visitado = False es_tecnico = auth.has_membership("TÉCNICO") - direccion_id = _find_dep_id(dependencias, 'DIRECCIÓN') + direccion_id = __find_dep_id(dependencias, 'DIRECCIÓN') # Lista de sustancias en el inventario del espacio fisico visitado sustancias = [] @@ -173,13 +173,13 @@ def inventarios(): if request.vars.dependencia: # Evaluando la correctitud de los parametros del GET - if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - _is_bool(request.vars.es_espacio)): + if not (__is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + __is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not _acceso_permitido(user, + if not __acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) @@ -208,14 +208,14 @@ def inventarios(): if request.vars.es_espacio == 'True': # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not _acceso_permitido(user, + if not __acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) # Evaluando la correctitud de los parametros del GET - if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - _is_bool(request.vars.es_espacio)): + if not (__is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + __is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) dep_nombre = db(db.espacios_fisicos.id == request.vars.dependencia @@ -236,12 +236,12 @@ def inventarios(): # Si el tecnico o jefe no ha seleccionado un espacio sino que acaba de # entrar a la opcion de inventarios elif request.vars.es_espacio == 'False': - if not (_is_valid_id(request.vars.dependencia, db.espacios_fisicos) and - _is_bool(request.vars.es_espacio)): + if not (__is_valid_id(request.vars.dependencia, db.espacios_fisicos) and + __is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not _acceso_permitido(user, + if not __acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) @@ -270,13 +270,13 @@ def inventarios(): if request.vars.dependencia: # Evaluando la correctitud de los parametros del GET - if not (_is_valid_id(request.vars.dependencia, db.dependencias) and - _is_bool(request.vars.es_espacio)): + if not (__is_valid_id(request.vars.dependencia, db.dependencias) and + __is_bool(request.vars.es_espacio)): redirect(URL('inventarios')) # Determinando si el usuario tiene privilegios suficientes para # consultar la dependencia en request.vars.dependencia - if not _acceso_permitido(user, + if not __acceso_permitido(user, int(request.vars.dependencia), request.vars.es_espacio): redirect(URL('inventarios')) From 61d563b566b354ac067903c3c4b88d4e2ef61c3e Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sat, 31 Mar 2018 09:35:12 +0100 Subject: [PATCH 80/91] Del: Quitando el campo f_unidad del catalogo de sustancias en la base de datos (ira en los inventarios) --- models/smydp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/smydp.py b/models/smydp.py index ad04be4d..220c4c54 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -20,7 +20,8 @@ Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.options.widget, label=T('Control')), - Field('f_unidad', 'list:string',requires=IS_IN_SET(['Litros','Kilos','Gramos', 'Mg']), widget=SQLFORM.widgets.options.widget, label=T('Unidad')), + # *!* La unidad no va aqui, porque alguien podria querer solicitar la sustancia en ml porque es muy poca y estaria obligada a usar una unidad + #Field('f_unidad', 'list:string',requires=IS_IN_SET(['kg','g','l', 'ml']), widget=SQLFORM.widgets.options.widget, label=T('Unidad')), Field('f_peligrosidad', 'list:string', requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'], From a05536143096bb7a7a4b86bd86d71bcaafb6d7ec Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 02:18:02 +0100 Subject: [PATCH 81/91] Add: Se lista el inventario de un espacio fisico --- controllers/smydp.py | 27 ++++++++++++++++++++------- languages/es.py | 3 +++ models/modelos_base.py | 8 +++++--- models/smydp.py | 27 +++++++++++++++++++++++++-- views/smydp/inventario_espacio.html | 26 +++++++++++++------------- 5 files changed, 66 insertions(+), 25 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 5910ec74..2f0bd0ba 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -64,6 +64,19 @@ def __find_dep_id(dependencias, nombre): k = k+1 return dep_id + +# Dado el id de un espacio fisico, retorna las sustancias que componen el inventario +# de ese espacio. Si ningun id es indicado, pero si el de una dependencia, busca +# todos los espacios fisicos que pertenecen a esta, agrega los inventarios y retorna +# la lista +def __get_inventario(espacio_id=None, dep_id=None): + + sustancias = [] + if espacio_id: + sustancias = list(db((db.t_Inventario.sustancia == db.t_Sustancia.id) & (db.t_Inventario.espacio == espacio_id)).select()) + + return sustancias + # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion # de esta @@ -160,9 +173,6 @@ def inventarios(): es_tecnico = auth.has_membership("TÉCNICO") direccion_id = __find_dep_id(dependencias, 'DIRECCIÓN') - # Lista de sustancias en el inventario del espacio fisico visitado - sustancias = [] - # Obteniendo la entrada en t_Personal del usuario conectado user = db(db.t_Personal.f_usuario == auth.user.id).select()[0] user_id = user.id @@ -296,7 +306,7 @@ def inventarios(): espacio_visitado = True # Se muestra la lista de sustancias que tiene en inventario - sustancias = + sustancias = __get_inventario(espacio_id) else: @@ -318,9 +328,12 @@ def inventarios(): # Guardando el ID y nombre de la dependencia padre para el link # de navegacion de retorno dep_padre_id = db(db.dependencias.id == request.vars.dependencia - ).select().first().unidad_de_adscripcion - dep_padre_nombre = db(db.dependencias.id == dep_padre_id - ).select().first().nombre + ).select().first().unidad_de_adscripcion + # Si dep_padre_id es None, se ha llegado al tope de la jerarquia + # y no hay un padre de este nodo + if dep_padre_id: + dep_padre_nombre = db(db.dependencias.id == dep_padre_id + ).select().first().nombre else: # Dependencia a la que pertenece el usuario o que tiene a cargo diff --git a/languages/es.py b/languages/es.py index 119c0beb..f7f528ff 100755 --- a/languages/es.py +++ b/languages/es.py @@ -232,6 +232,7 @@ 'Espacio Físico': 'Espacio Físico', 'Estado': 'Estado', 'Estatus': 'Estatus', +'Existencia': 'Existencia', 'export as csv file': 'exportar como archivo CSV', 'Export:': 'Exportar:', 'exposes': 'expone', @@ -506,6 +507,7 @@ 'Success!': '¡Correcto!', 'Support': 'Soporte', 'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?', +'Sustancia': 'Sustancia', 'Table': 'tabla', 'Table name': 'Nombre de la tabla', 'Telephone': 'Teléfono', @@ -589,6 +591,7 @@ 'Username retrieve': 'Recuperar nombre de usuario', 'Users': 'Usuarios', 'Uso del espacio físico': 'Uso del espacio físico', +'Uso interno': 'Uso interno', 'Usuario Asociado': 'Usuario Asociado', 'Value already in database or empty': 'Value already in database or empty', 'value already in database or empty': 'el valor ya existe en la base de datos o está vacío', diff --git a/models/modelos_base.py b/models/modelos_base.py index e89fa676..56244842 100755 --- a/models/modelos_base.py +++ b/models/modelos_base.py @@ -158,11 +158,12 @@ 'espacios_fisicos', #Atributos; Field('nombre', 'string', unique=True, notnull=True, label=T('Nombre')), + Field('uso', 'string', notnull=True, label=T('Uso del espacio físico')), - #Referencia (Revisar si el label es asistio o organizo) + Field('dependencia', 'reference dependencias', - requires=IS_IN_DB(db, db.dependencias.id, '%(nombre)s', zero=None), label=T('Dependencia')) - , migrate=False) + requires=IS_IN_DB(db, db.dependencias.id, '%(nombre)s', zero=None), label=T('Dependencia')), + migrate=False) db.espacios_fisicos._plural = 'Espacio Fisico' db.espacios_fisicos._singular = 'Espacio Fisico' @@ -173,6 +174,7 @@ #Atributos; Field('espacio_fisico', 'reference espacios_fisicos', requires=IS_IN_DB(db, db.espacios_fisicos.id, '%(codigo)s', zero=None)), + Field('tecnico', 'reference t_Personal', requires=IS_IN_DB(db, db.t_Personal.id, '%(f_email)s', zero=None)) ) \ No newline at end of file diff --git a/models/smydp.py b/models/smydp.py index 220c4c54..bfd2ef14 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -9,9 +9,9 @@ #Atributos; Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), - Field('f_cas', 'string', requires=[ IS_NOT_EMPTY(), + Field('f_cas', 'string', requires=[ IS_NOT_EMPTY(), IS_MATCH('^[0-9]+\-[0-9]+\-[0-9]+$', - error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], + error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], unique=True, label=T('CAS')), Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), @@ -40,3 +40,26 @@ db.t_Sustancia._plural='Catálogo de Sustancias' +#t_Inventario: Tabla de la entidad debil Inventario que contiene la existencia de cada sustancia en cada espacio fisico +db.define_table( + #Nombre de la entidad + 't_Inventario', + + #Atributos; + + # Cantidades (el excedente es calculado dinamicamente como existencia - uso interno) + Field('f_existencia', 'double', requires=IS_NOT_EMPTY(), label=T('Existencia')), + Field('f_uso_interno', 'double', requires=IS_NOT_EMPTY(), label=T('Uso interno')), + + # Referencias a otras tablas + Field('espacio', 'reference espacios_fisicos', + requires=IS_IN_DB(db, db.espacios_fisicos.id, '%(nombre)s', zero=None), label=T('Espacio Físico'), notnull=True), + Field('sustancia', 'reference t_Sustancia', + requires=IS_IN_DB(db, db.t_Sustancia.id, '%(f_nombre)s', zero=None), label=T('Sustancia'), notnull=True), + + # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla + auth.signature + ) + +db.t_Inventario._singular='Inventario' +db.t_Inventario._plural='Inventario' diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 3f449794..064a3e2d 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -15,11 +15,6 @@
-{{sustancias = [ - {'f_nombre': 'Bicarbonato', 'f_cas': '01-05-04', 'f_pureza': '70', 'f_estado': 'Solido', 'f_existencia': '5', 'f_unidad': 'Gramos', 'f_excedente': '5'}, - {'f_nombre': 'Acetona', 'f_cas': '05-0545-5014', 'f_pureza': '20', 'f_estado': 'Liquido', 'f_existencia': '6', 'f_unidad': 'ml', 'f_excedente': '5'} - ]}} -
@@ -41,7 +36,9 @@

Listado de Servicios

Pureza Estado Existencia + Uso interno Excedente @@ -49,16 +46,17 @@

Listado de Servicios

{{for sustancia in sustancias:}} + {{sust = sustancia['t_Sustancia']}} + {{inv = sustancia['t_Inventario']}} - {{=sustancia['f_nombre']}} + {{=sust.f_nombre}} - {{=sustancia['f_cas']}} - {{=sustancia['f_pureza']}} - {{=sustancia['f_estado']}} - {{=sustancia['f_existencia']}} - {{=sustancia['f_unidad']}} - {{=int(sustancia['f_existencia']) - int(sustancia['f_excedente'])}} - {{=sustancia['f_excedente']}} + {{=sust.f_cas}} + {{=sust.f_pureza}} + {{=sust.f_estado}} + {{=inv.f_existencia}} + {{=inv.f_uso_interno}} + {{=int(inv.f_existencia) - int(inv.f_uso_interno)}} {{pass}} @@ -70,7 +68,9 @@

Listado de Servicios

Pureza Estado Existencia + Uso interno Excedente From 514c0079c4ee698466db2e77ea45a3d27dadea40 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 12:23:16 +0100 Subject: [PATCH 82/91] Fix: Arreglado problema con los acentos --- controllers/smydp.py | 8 ++++++-- views/smydp/inventario_espacio.html | 2 +- views/smydp/inventarios.html | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 2f0bd0ba..74717ce8 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + #----------------------------------------------------------------------------- # Controladores provisionales utilizados solo para probar las vistas del modulo de SMyDP # @@ -10,6 +12,8 @@ # #----------------------------------------------------------------------------- + + # Verifica si el usuario que intenta acceder al controlador tiene alguno de los # roles necesarios def __check_role(): @@ -70,10 +74,10 @@ def __find_dep_id(dependencias, nombre): # todos los espacios fisicos que pertenecen a esta, agrega los inventarios y retorna # la lista def __get_inventario(espacio_id=None, dep_id=None): - sustancias = [] if espacio_id: - sustancias = list(db((db.t_Inventario.sustancia == db.t_Sustancia.id) & (db.t_Inventario.espacio == espacio_id)).select()) + sustancias = list(db((db.t_Inventario.sustancia == db.t_Sustancia.id) & + (db.t_Inventario.espacio == espacio_id)).select()) return sustancias diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 064a3e2d..57b7999f 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -53,7 +53,7 @@

Listado de Servicios

{{=sust.f_cas}} {{=sust.f_pureza}} - {{=sust.f_estado}} + {{=sust.f_estado[0] if len(sust.f_estado) > 0 else None}} {{=inv.f_existencia}} {{=inv.f_uso_interno}} {{=int(inv.f_existencia) - int(inv.f_uso_interno)}} diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 7004ee40..b12727f9 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -1,8 +1,9 @@ {{extend 'layout.html'}} {{block head}} - + + From 4ea289c323adea9309c39b1841c27efce8bf0864 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 14:15:07 +0100 Subject: [PATCH 83/91] Add: Se anadio forma de agregar sustancia --- controllers/smydp.py | 16 ++++--- static/css/smydp_listado.css | 6 ++- static/css/smydp_modal.css | 4 +- views/smydp/inventario_espacio.html | 70 ++++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 74717ce8..c57419f0 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -74,12 +74,12 @@ def __find_dep_id(dependencias, nombre): # todos los espacios fisicos que pertenecen a esta, agrega los inventarios y retorna # la lista def __get_inventario(espacio_id=None, dep_id=None): - sustancias = [] + inventario = [] if espacio_id: - sustancias = list(db((db.t_Inventario.sustancia == db.t_Sustancia.id) & + inventario = list(db((db.t_Inventario.sustancia == db.t_Sustancia.id) & (db.t_Inventario.espacio == espacio_id)).select()) - return sustancias + return inventario # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion @@ -162,8 +162,11 @@ def inventarios(): # Lista de sustancias en el inventario de un espacio fisico o que componen # el inventario agregado de una dependencia - sustancias = [] + inventario = [] + # Lista de sustancias en el catalogo + sustancias = [] + # Esta variable es enviada a la vista para que cuando el usuario seleccione # un espacio fisico, se pase por GET es_espacio = "True". No quiere decir # que la dependencia seleccionada sea un espacio, sino que la siguiente @@ -310,7 +313,9 @@ def inventarios(): espacio_visitado = True # Se muestra la lista de sustancias que tiene en inventario - sustancias = __get_inventario(espacio_id) + inventario = __get_inventario(espacio_id) + + sustancias = list(db(db.t_Sustancia.id > 0).select(db.t_Sustancia.ALL)) else: @@ -358,6 +363,7 @@ def inventarios(): dep_padre_nombre=dep_padre_nombre, direccion_id=direccion_id, es_tecnico=es_tecnico, + inventario=inventario, sustancias=sustancias) diff --git a/static/css/smydp_listado.css b/static/css/smydp_listado.css index 4507d814..2990a5f4 100644 --- a/static/css/smydp_listado.css +++ b/static/css/smydp_listado.css @@ -1,3 +1,5 @@ +/* Estilos de inventarios.html */ + select{ border-top: 0px !important; border-left: 0px !important; @@ -85,4 +87,6 @@ th { #filtroInput { margin-left: 100px; -} \ No newline at end of file +} + +/* Estilos de inventario_espacio.html */ \ No newline at end of file diff --git a/static/css/smydp_modal.css b/static/css/smydp_modal.css index 35ec801a..93f70c2f 100755 --- a/static/css/smydp_modal.css +++ b/static/css/smydp_modal.css @@ -45,7 +45,7 @@ height: 590px !important; } - #nuevoServicio{ + #nuevaSustancia{ text-align: left; padding-top: 12px; color: white; @@ -182,7 +182,7 @@ width: 100%; } - #nuevoServicio{ + #nuevaSustancia{ text-align: left; padding-top: 12px; color: white; diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 57b7999f..7be74092 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -8,7 +8,7 @@
- +
@@ -45,7 +45,7 @@

Listado de Servicios

- {{for sustancia in sustancias:}} + {{for sustancia in inventario:}} {{sust = sustancia['t_Sustancia']}} {{inv = sustancia['t_Inventario']}} @@ -84,3 +84,69 @@

Listado de Servicios

+ + + + + + + + From 2500bd44317588c4060226ca461fc49bdad1ea27 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 14:47:03 +0100 Subject: [PATCH 84/91] Add: Creado controlador para anadir sustancias al inventario de un espacio --- controllers/smydp.py | 15 +++++++++++++++ views/smydp/inventario_espacio.html | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index c57419f0..b00068c4 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -81,6 +81,15 @@ def __get_inventario(espacio_id=None, dep_id=None): return inventario + +# Registra una nueva sustancia en el espacio fisico indicado. Valida que +# la sustancia no exista ya en ese espacio, que las cantidades sean no negativas +# y que la cantidad para uso interno (uso_interno) sea menor que la existencia +def __agregar_sustancia(espacio_id, sustancia_id, existencia, uso_interno): + + print "espacio_id {0} sustancia_id {1} existencia {2} uso_interno {3}".format(espacio_id, sustancia_id, existencia, uso_interno) + + # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion # de esta @@ -317,6 +326,12 @@ def inventarios(): sustancias = list(db(db.t_Sustancia.id > 0).select(db.t_Sustancia.ALL)) + # Si se esta agregando una nueva sustancia, se registra en la DB + if request.vars.sustancia: + __agregar_sustancia(espacio_id, + request.vars.sustancia, + request.vars.existencia, + request.vars.uso_interno) else: # Se muestran las dependencias que componen a esta dependencia padre diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 7be74092..10585f89 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -126,7 +126,7 @@

Datos de ingreso

@@ -137,6 +137,7 @@

Datos de ingreso

+ From 9f2fecb8740d0f0a3e2fa23ba5012eb2bb4ceb44 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 15:49:11 +0100 Subject: [PATCH 85/91] Add: Agregada tabla de unidades de medida y algunas unidades en models/z.py --- languages/es.py | 1 + models/smydp.py | 13 ++++++++++++- models/z.py | 8 ++++++++ views/smydp/inventario_espacio.html | 17 ++++++++++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/languages/es.py b/languages/es.py index f7f528ff..8353eebe 100755 --- a/languages/es.py +++ b/languages/es.py @@ -563,6 +563,7 @@ 'unable to uninstall "%s"': 'no es posible instalar "%s"', 'uncheck all': 'desmarcar todos', 'Unidad de Adscripción': 'Unidad de Adscripción', +'Unidad de medida': 'Unidad de medida', 'uninstall': 'desinstalar', 'unknown': 'desconocido', 'update': 'actualizar', diff --git a/models/smydp.py b/models/smydp.py index bfd2ef14..33c4b995 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -1,6 +1,16 @@ #------------------------------------ Modulo de Sustancias, materiales y desechos peligrosos ------------------------------------------- +#t_Unidades_de_medida: Tabla de unidades de medida de las sustancias (ml, l, g, kg, etc.) +db.define_table( + #Nombre de la entidad + 't_Unidad_de_medida', + + #Atributos; + Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), + Field('f_abreviatura', 'string', requires=IS_NOT_EMPTY(), label=T('Abreviatura')) + ) + #t_Sustancia: Tabla de sustancias de la cual se obtiene informacion del listado (catalogo de sustancias) db.define_table( #Nombre de la entidad @@ -50,7 +60,8 @@ # Cantidades (el excedente es calculado dinamicamente como existencia - uso interno) Field('f_existencia', 'double', requires=IS_NOT_EMPTY(), label=T('Existencia')), Field('f_uso_interno', 'double', requires=IS_NOT_EMPTY(), label=T('Uso interno')), - + Field('f_medida', 'reference t_Unidad_de_medida', + requires=IS_IN_DB(db, db.t_Unidad_de_medida.id, '%(f_nombre)s', zero=None), label=T('Unidad de medida'), notnull=True), # Referencias a otras tablas Field('espacio', 'reference espacios_fisicos', requires=IS_IN_DB(db, db.espacios_fisicos.id, '%(nombre)s', zero=None), label=T('Espacio Físico'), notnull=True), diff --git a/models/z.py b/models/z.py index 58e90d5a..3d6bcf34 100644 --- a/models/z.py +++ b/models/z.py @@ -496,6 +496,14 @@ db.auth_membership.insert(user_id=user, group_id=role, dependencia_asociada=dep) +# Unidades de medida +if db(db.t_Unidad_de_medida).isempty(): + db.t_Unidad_de_medida.insert(f_nombre='Mililitros', f_abreviatura='ml') + db.t_Unidad_de_medida.insert(f_nombre='Litros', f_abreviatura='l') + db.t_Unidad_de_medida.insert(f_nombre='Gramos', f_abreviatura='g') + db.t_Unidad_de_medida.insert(f_nombre='Kilogramos', f_abreviatura='kg') + + # Catalogo de sustancias """ if db(db.t_Sustancia).isempty(): diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index 10585f89..b475dc4b 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -18,7 +18,7 @@
-

Listado de Servicios

+

Inventario

@@ -133,6 +133,21 @@

Datos de ingreso

+
+
Unidad de medida*
+
+ +
+
+ +
+
+ +
+
+ +
+
From dd4c04958bc4ff9d6abcb09e193607bacc17f653 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 16:01:26 +0100 Subject: [PATCH 86/91] Add: Se muestran las unidades en la forma para agregar sustancias al inventario de espacios --- controllers/smydp.py | 6 +++- views/smydp/inventario_espacio.html | 55 ++++++++++++++--------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index b00068c4..8667d8b2 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -176,6 +176,9 @@ def inventarios(): # Lista de sustancias en el catalogo sustancias = [] + # Lista de unidades de medida + unidades_de_medida = list(db(db.t_Unidad_de_medida.id > 0).select()) + # Esta variable es enviada a la vista para que cuando el usuario seleccione # un espacio fisico, se pase por GET es_espacio = "True". No quiere decir # que la dependencia seleccionada sea un espacio, sino que la siguiente @@ -379,7 +382,8 @@ def inventarios(): direccion_id=direccion_id, es_tecnico=es_tecnico, inventario=inventario, - sustancias=sustancias) + sustancias=sustancias, + unidades_de_medida=unidades_de_medida) @auth.requires_login(otherwise=URL('modulos', 'login')) diff --git a/views/smydp/inventario_espacio.html b/views/smydp/inventario_espacio.html index b475dc4b..d3c2f580 100644 --- a/views/smydp/inventario_espacio.html +++ b/views/smydp/inventario_espacio.html @@ -118,39 +118,36 @@
- -

+ +

-
Unidad de medida*
+ {{=u.f_nombre}} -
+ {{pass}} +

@@ -167,30 +167,32 @@
Unidad de medida* From 9f6fb5bbb44f3afe7602ce21924b0aa860b629ee Mon Sep 17 00:00:00 2001 From: saar1312 Date: Mon, 2 Apr 2018 21:10:08 +0100 Subject: [PATCH 90/91] Add: Cambiando color de mensajes de validacion en las formas a rojo #B70101 --- static/css/smydp_listado.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/css/smydp_listado.css b/static/css/smydp_listado.css index 2990a5f4..a703c7cd 100644 --- a/static/css/smydp_listado.css +++ b/static/css/smydp_listado.css @@ -89,4 +89,8 @@ th { margin-left: 100px; } -/* Estilos de inventario_espacio.html */ \ No newline at end of file +/* Estilos de inventario_espacio.html */ + +.field-error{ + color:#B70101; +} \ No newline at end of file From 29d8b7858c624d451efec65ae789f521896a2d57 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 3 Apr 2018 01:48:34 +0100 Subject: [PATCH 91/91] Fix: Bug por el metodo POST al agregar una sustancia solucionado. --- controllers/servicios.py | 2 +- controllers/smydp.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/controllers/servicios.py b/controllers/servicios.py index 38b36070..17342359 100755 --- a/controllers/servicios.py +++ b/controllers/servicios.py @@ -1,4 +1,4 @@ -#----------------------------------------------------------------------------- + # # Controladores de las funcionalidades del modulo de Servicios # diff --git a/controllers/smydp.py b/controllers/smydp.py index 742c5b16..11b34e82 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -85,20 +85,24 @@ def __get_inventario(espacio_id=None, dep_id=None): # Registra una nueva sustancia en el espacio fisico indicado. Si la sustancia ya # existe en el inventario, genera un mensaje con flash y no anade de nuevo la # sustancia. -def __agregar_sustancia(espacio_id, sustancia_id, total, excedente, unidad_id): +def __agregar_sustancia(espacio, sustancia_id, total, excedente, unidad_id): # Si ya existe la sustancia en el inventario - if db((db.t_Inventario.espacio == espacio_id) & + if db((db.t_Inventario.espacio == espacio.id) & (db.t_Inventario.sustancia == sustancia_id)).select(): - print "Ya existe la sustancia {0} en el espacio {1}".format(sustancia_id, espacio_id) + sust = db(db.t_Sustancia.id == sustancia_id).select()[0] + + #response.flash = "La sustancia \"{0}\" ya ha sido ingresada anteriormente \ + # en el espacio \"{1}\".".format(sust.f_nombre, espacio.nombre) return False db.t_Inventario.insert(f_existencia=total, f_uso_interno=float(total)-float(excedente), f_medida=unidad_id, - espacio=espacio_id, + espacio=espacio.id, sustancia=sustancia_id) + return redirect(URL(args=request.args, vars=request.get_vars, host=True)) # Dado el id de una depencia y conociendo si es un espacio fisico o una dependencia # comun, determina si el usuario tiene privilegios suficientes para obtener informacion @@ -343,7 +347,7 @@ def inventarios(): # Si se esta agregando una nueva sustancia, se registra en la DB if request.vars.sustancia: - __agregar_sustancia(espacio_id, + __agregar_sustancia(espacio, request.vars.sustancia, request.vars.total, request.vars.excedente,
From 0f1116125e3404b3b9d06da6f7195744cc559c31 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Wed, 28 Feb 2018 05:00:17 +0000 Subject: [PATCH 13/91] Antes de listar como en servicios --- controllers/smydp.py | 36 +++++++++++++++++++++++++++++------- languages/es.py | 2 +- models/smydp.py | 5 ++--- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index de981c3d..45ba9da1 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -7,32 +7,54 @@ @auth.requires_login(otherwise=URL('modulos', 'login')) def index(): - return locals() + return locals() @auth.requires_login(otherwise=URL('modulos', 'login')) def sustancias(): - return locals() + return locals() @auth.requires_login(otherwise=URL('modulos', 'login')) def inventarios(): - return locals() + return locals() @auth.requires_login(otherwise=URL('modulos', 'login')) def desechos(): - return locals() + return locals() #-------------------------------------- Catalogo --------------------------------------- @auth.requires_login(otherwise=URL('modulos', 'login')) def catalogo(): - + columnas = [db.t_Sustancia.f_nombre, + db.t_Sustancia.f_cas, + db.t_Sustancia.f_pureza, + db.t_Sustancia.f_estado, + db.t_Sustancia.f_control, + db.t_Sustancia.f_peligrosidad, + db.t_Sustancia.f_hds ] if(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')): - table = SQLFORM.smartgrid(db.t_Sustancia,onupdate=auth.archive,links_in_grid=False,csv=False,user_signature=True,paginate=10) + table = SQLFORM.smartgrid( + db.t_Sustancia, + fields=columnas, + onupdate=auth.archive, + links_in_grid=False, + csv=False, + user_signature=True, + paginate=10) else: - table = SQLFORM.smartgrid(db.t_Sustancia,editable=False,deletable=False,csv=False,links_in_grid=False,create=False,paginate=10) + table = SQLFORM.smartgrid( + db.t_Sustancia, + fields=columnas, + editable=False, + deletable=False, + csv=False, + links_in_grid=False, + create=False, + paginate=10, + showid=False) return locals() diff --git a/languages/es.py b/languages/es.py index f1ee03b3..d1129b2d 100755 --- a/languages/es.py +++ b/languages/es.py @@ -41,7 +41,7 @@ 'About application': 'Acerca de la aplicación', 'Access Control': 'Control de Acceso', 'Add': 'Añadir', -'Add Record': 'Add Record', +'Add Record': 'Añadir', 'Add record to database': 'Add record to database', 'Add this to the search as an AND term': 'Add this to the search as an AND term', 'Add this to the search as an OR term': 'Add this to the search as an OR term', diff --git a/models/smydp.py b/models/smydp.py index 65c42405..2ed44b2a 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -16,9 +16,8 @@ Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), # Hoja de seguridad (archivo pdf) - Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad')), - format='%(f_nombre)s', - auth.signature) # Agregar los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla + Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad'), format='%(f_nombre)s'), + auth.signature) # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla #db.t_sustancias.id.readable=False #Si se muestra en la forma, descomentar #db.t_sustancias.id.writable=False From be4a115fd4669f274c0d0b607af469305d38068a Mon Sep 17 00:00:00 2001 From: saar1312 Date: Wed, 28 Feb 2018 11:42:14 +0000 Subject: [PATCH 14/91] Catalogo de sustancias casi listo --- models/smydp.py | 59 --------------------- static/css/smydp_catalogo.css | 96 +++++++++++------------------------ views/smydp/catalogo.html | 11 ++++ 3 files changed, 42 insertions(+), 124 deletions(-) diff --git a/models/smydp.py b/models/smydp.py index 2ed44b2a..b44c2317 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -26,62 +26,3 @@ db.t_Sustancia._plural='Catálogo de Sustancias' -""" -if db(db.t_Sustancia).isempty(): - db.t_Sustancia.insert(f_nombre='Acetato de Etilo', f_cas='141-78-6', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) - db.t_Sustancia.insert(f_nombre='Acetona', f_cas='67-64-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) - db.t_Sustancia.insert(f_nombre='Ácido Antranílico', f_cas='118-92-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Comburente']) - db.t_Sustancia.insert(f_nombre='Ácido Clorhídrico', f_cas='7647-01-0', f_pureza='37', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico','Corrosivo']) - db.t_Sustancia.insert(f_nombre='Ácido Fenilacético y sus sales', f_cas='103-82-2', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Comburente']) - db.t_Sustancia.insert(f_nombre='Ácido Nítrico', f_cas='7697-37-2', f_pureza='5', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Tóxico','Irritante']) - db.t_Sustancia.insert(f_nombre='Ácido Pícrico (trinitrofenol)', f_cas='88-89-1', f_pureza='3', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Ácido Sulfúrico', f_cas='7664-93-9', f_pureza='97', f_estado='Líquido', f_control='RL4 y RL7', f_peligrosidad=['Corrosivo','Irritante']) - db.t_Sustancia.insert(f_nombre='Aluminio en polvo', f_cas='7429-90-5', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable']) - db.t_Sustancia.insert(f_nombre='Amoníaco Anhídrico', f_cas='7664-41-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Inflamable']) - db.t_Sustancia.insert(f_nombre='Amoníaco en disolución acuosa', f_cas='001336-21-6', f_pureza='25', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico','Corrosivo']) - db.t_Sustancia.insert(f_nombre='Anhídrico acético', f_cas='108-24-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Nocivo']) - db.t_Sustancia.insert(f_nombre='Azidas (de sodio)', f_cas='26628-22-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) - db.t_Sustancia.insert(f_nombre='Benceno', f_cas='71-43-2', f_pureza='99', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Tóxico','Inflamable']) - db.t_Sustancia.insert(f_nombre='Butanona (metilcetona)', f_cas='78-93-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) - db.t_Sustancia.insert(f_nombre='Carbonato de Sodio', f_cas='497-19-8', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Corrosivo','Irritante']) - db.t_Sustancia.insert(f_nombre='Clorato de Potasio', f_cas='3811-04-9', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Clorato de Sodio', f_cas='7775-09-9', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Cloroformo', f_cas='67-66-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Diclorometano', f_cas='75-09-2', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Nocivo','Inflamable']) - db.t_Sustancia.insert(f_nombre='Dinitrofenol', f_cas='51-28-5', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Nocivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Dinitrotolueno', f_cas='606-20-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Nocivo']) - db.t_Sustancia.insert(f_nombre='Etanol', f_cas='64-17-5', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) - db.t_Sustancia.insert(f_nombre='Eter Etílico', f_cas='60-29-7', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Explosivo','Nocivo']) - db.t_Sustancia.insert(f_nombre='Fósforo blanco', f_cas='7723-14-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable','Nocivo']) - db.t_Sustancia.insert(f_nombre='Fulminato de Mercurio', f_cas='', f_pureza='', f_estado='', f_control='RL7', f_peligrosidad=['N/A']) - db.t_Sustancia.insert(f_nombre='Heptano', f_cas='142-82-5', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) - db.t_Sustancia.insert(f_nombre='Hexano', f_cas='110-54-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable']) - db.t_Sustancia.insert(f_nombre='Hidrogenocarbonato (Bicarbonato) de Sodio', f_cas='144-55-8', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Irritante']) - db.t_Sustancia.insert(f_nombre='Hipoclorito de calcio', f_cas='7778-54-3', f_pureza='68', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Irritante']) - db.t_Sustancia.insert(f_nombre='Hipoclorito de Sodio', f_cas='7681-52-9', f_pureza='', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Metanol', f_cas='67-56-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) - db.t_Sustancia.insert(f_nombre='Nitrato de Amonio (salitre de chile)', f_cas='6484-52-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo']) - db.t_Sustancia.insert(f_nombre='Nitrato de Bismuto', f_cas='7697-37-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrato de Calcio', f_cas='13477-34-4', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrato de Plata', f_cas='7761-88-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrato de Plomo', f_cas='10099-74-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrato de Potasio', f_cas='7757-79-1', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrato de Sodio', f_cas='7631-99-4', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrito de Sodio', f_cas='7632-00-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrobenceno', f_cas='98-95-3', f_pureza='99', f_estado='Líquido', f_control='RL7', f_peligrosidad=['Nocivo','Tóxico']) - db.t_Sustancia.insert(f_nombre='Nitrocelulosa', f_cas='9004-70-0', f_pureza='12', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable']) - db.t_Sustancia.insert(f_nombre='Nitroglicerina', f_cas='55-63-0', f_pureza='1', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo']) - db.t_Sustancia.insert(f_nombre='Perclorato de Potasio', f_cas='7778-74-7', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Tóxico']) - db.t_Sustancia.insert(f_nombre='Perclorato de Sodio', f_cas='7601-89-0', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Comburente','Nocivo']) - db.t_Sustancia.insert(f_nombre='Permanganato de Potasio', f_cas='7722-64-7', f_pureza='99', f_estado='Sólido', f_control='RL4 y RL7', f_peligrosidad=['Comburente','Corrosivo']) - db.t_Sustancia.insert(f_nombre='Sesquicarbonato de Sodio', f_cas='6106-20-3', f_pureza='99', f_estado='Sólido', f_control='RL4', f_peligrosidad=['Corrosivo','Irritante']) - db.t_Sustancia.insert(f_nombre='Sulfato de Amonio', f_cas='7783-20-2', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Corrosivo','Irritante']) - db.t_Sustancia.insert(f_nombre='Sulfato de Magnesio', f_cas='7487-88-9', f_pureza='65', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Irritante']) - db.t_Sustancia.insert(f_nombre='Sulfuro de Potasio', f_cas='1312-73-8', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Inflamable','Corrosivo']) - db.t_Sustancia.insert(f_nombre='Tetrahidrofurano', f_cas='109-99-9', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Irritante']) - db.t_Sustancia.insert(f_nombre='Tolueno', f_cas='108-88-3', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Inflamable','Tóxico']) - db.t_Sustancia.insert(f_nombre='Trinitrotolueno (TNT)', f_cas='118-96-7', f_pureza='99', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Explosivo','Nocivo']) - db.t_Sustancia.insert(f_nombre='Urea', f_cas='57-13-6 ', f_pureza='', f_estado='Sólido', f_control='RL7', f_peligrosidad=['Irritante','Comburente']) - db.t_Sustancia.insert(f_nombre='4-metilpentan-2-ona (Metilisobutilcetona)', f_cas='108-10-1', f_pureza='99', f_estado='Líquido', f_control='RL4', f_peligrosidad=['Tóxico']) - db.t_Sustancia.insert(f_nombre='Fósforos rojos o amorfos', f_cas='7723-14-0', f_pureza='99', f_estado='Sólido', f_control='N/A', f_peligrosidad=['Inflamable','Nocivo']) -""" \ No newline at end of file diff --git a/static/css/smydp_catalogo.css b/static/css/smydp_catalogo.css index 64cfcf28..82725829 100755 --- a/static/css/smydp_catalogo.css +++ b/static/css/smydp_catalogo.css @@ -1,88 +1,54 @@ -select{ - border-top: 0px !important; - border-left: 0px !important; - border-right: 0px !important; - box-shadow: none !important; - border-radius: 0px !important; - border-bottom-width: 2px !important; - background-color: transparent !important; - -} - -th input[type=text]{ - border-top: 0px !important; - border-left: 0px !important; - border-right: 0px !important; - box-shadow: none !important; - border-bottom-width: 2px !important; - border-radius: 0px; - background-color: transparent; - height: 35px !important; - width: 100%; -} - -th { - width: 150px; +.row{ + font-family: "Roboto", Sans-Serif ; } -#datatable_length select { - height: 30px; +.web2py_htmltable { + padding-top: 20px; } -#collapseFiltros { - margin-top: 10px; - margin-bottom: 10px; +table { + border-style: solid; + border-color: #CECECE; + border-width: 1px; } -#columnBotonAgregar { - text-align: right; +thead{ + border-style: solid; + border-color: #CECECE; + border-width: 1px; + font-size: 16px; } -.botonesListado { - background-color: #0300d7; - border-color: #0300d7; - color: white; -} -.botonesListado:hover { - color: white; -} - -#containerAgregar{ - margin-top: -30px; -} - -#listadoContainer { - padding-top: 25px; +th { + text-align: center; + padding: 10px 20px 10px 10px; } -.tablaListado { - border: 1.5px !important; - border-style: solid !important; - border-color: #ddd !important; +td{ + padding: 10px 20px 10px 10px; } -#titulosListado { - background-color: #505050; -} -.camposTabla { - text-align: center; +.web2py_paginator ul{ + padding: 10px 0px 10px 0px; } -.linksNombres { - color: white; +.web2py_paginator li{ + font-weight: bold; + padding: 5px 10px 5px 0px; /* Arreglar esto */ + display: inline; + font-size: 16px; } -.linksNombres:hover { - color: rgba(6, 164, 252, 1); - text-decoration: none; +.web2py_console { + display: inline; } -.filtros { - width: 200px; +.web2py_counter { + padding: 10px 0px; } -#filtroInput { - margin-left: 100px; +.current { + text-decoration: underline; } \ No newline at end of file diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html index 0af0cfaa..d09ce5e6 100644 --- a/views/smydp/catalogo.html +++ b/views/smydp/catalogo.html @@ -6,6 +6,17 @@ {{block center}} + + + + +

{{=table}}

From 791ccd625167ee6d6e871260a27de4047f820e54 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Wed, 28 Feb 2018 12:02:36 +0000 Subject: [PATCH 15/91] Eliminando Breadcrumb por defecto --- static/css/smydp_catalogo.css | 3 ++- views/smydp/catalogo.html | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/static/css/smydp_catalogo.css b/static/css/smydp_catalogo.css index 82725829..c2f7a906 100755 --- a/static/css/smydp_catalogo.css +++ b/static/css/smydp_catalogo.css @@ -51,4 +51,5 @@ td{ .current { text-decoration: underline; -} \ No newline at end of file +} + diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html index d09ce5e6..25806f02 100644 --- a/views/smydp/catalogo.html +++ b/views/smydp/catalogo.html @@ -23,4 +23,9 @@
+ + {{end}} \ No newline at end of file From 19fa628596b7ff847729a68d1a2c968b0b95a5de Mon Sep 17 00:00:00 2001 From: saar1312 Date: Thu, 1 Mar 2018 09:55:28 +0000 Subject: [PATCH 16/91] Agregando breadcrumbs de paginas faltantes --- static/css/smydp_catalogo.css | 2 +- views/smydp/catalogo.html | 5 +++-- views/smydp/index.html | 12 ++++++++++++ views/smydp/inventarios.html | 12 ++++++++++++ views/smydp/sustancias.html | 13 +++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/static/css/smydp_catalogo.css b/static/css/smydp_catalogo.css index c2f7a906..54ef8a19 100755 --- a/static/css/smydp_catalogo.css +++ b/static/css/smydp_catalogo.css @@ -16,7 +16,7 @@ thead{ border-style: solid; border-color: #CECECE; border-width: 1px; - font-size: 16px; + font-size: 14px; } diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html index 25806f02..eeee9448 100644 --- a/views/smydp/catalogo.html +++ b/views/smydp/catalogo.html @@ -10,8 +10,9 @@ diff --git a/views/smydp/index.html b/views/smydp/index.html index 10d71372..b91a5261 100644 --- a/views/smydp/index.html +++ b/views/smydp/index.html @@ -5,6 +5,18 @@ {{end}} {{block center}} + + + + + + +
diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index 54de4939..97c53556 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -6,6 +6,18 @@ {{block center}} + + + + +
diff --git a/views/smydp/sustancias.html b/views/smydp/sustancias.html index ea68212f..0c0896ea 100644 --- a/views/smydp/sustancias.html +++ b/views/smydp/sustancias.html @@ -5,6 +5,19 @@ {{end}} {{block center}} + + + + + + +
From 862749f8ca317be40c544e22787063eb564012fe Mon Sep 17 00:00:00 2001 From: saar1312 Date: Fri, 2 Mar 2018 08:46:17 +0000 Subject: [PATCH 17/91] Fixing link in index view (personal) --- views/personal/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/personal/index.html b/views/personal/index.html index 1b894f5c..c3b35f9a 100644 --- a/views/personal/index.html +++ b/views/personal/index.html @@ -12,7 +12,7 @@ From 78c2e94d793902af72cb030b7a66fc083d1cd444 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Sun, 4 Mar 2018 11:15:45 +0000 Subject: [PATCH 18/91] Previous to deleting the division of the two modules --- controllers/smydp.py | 17 ++++------------- models/smydp.py | 4 ++-- static/css/smydp_catalogo.css | 13 +++++++++++++ views/smydp/catalogo.html | 13 +++++++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/controllers/smydp.py b/controllers/smydp.py index 45ba9da1..186afb9d 100755 --- a/controllers/smydp.py +++ b/controllers/smydp.py @@ -29,26 +29,17 @@ def desechos(): @auth.requires_login(otherwise=URL('modulos', 'login')) def catalogo(): - columnas = [db.t_Sustancia.f_nombre, - db.t_Sustancia.f_cas, - db.t_Sustancia.f_pureza, - db.t_Sustancia.f_estado, - db.t_Sustancia.f_control, - db.t_Sustancia.f_peligrosidad, - db.t_Sustancia.f_hds ] + if(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')): - table = SQLFORM.smartgrid( - db.t_Sustancia, - fields=columnas, + table = SQLFORM.smartgrid( db.t_Sustancia, onupdate=auth.archive, links_in_grid=False, csv=False, user_signature=True, paginate=10) + else: - table = SQLFORM.smartgrid( - db.t_Sustancia, - fields=columnas, + table = SQLFORM.smartgrid( db.t_Sustancia, editable=False, deletable=False, csv=False, diff --git a/models/smydp.py b/models/smydp.py index b44c2317..ff14e7cd 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -19,8 +19,8 @@ Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad'), format='%(f_nombre)s'), auth.signature) # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla -#db.t_sustancias.id.readable=False #Si se muestra en la forma, descomentar -#db.t_sustancias.id.writable=False +db.t_Sustancia.id.readable=False #Si se muestra en la forma, descomentar +db.t_Sustancia.id.writable=False db.t_Sustancia.f_hds.readable=(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')) #-*-* Chequear permisos aqui db.t_Sustancia._singular='Catálogo de Sustancias' db.t_Sustancia._plural='Catálogo de Sustancias' diff --git a/static/css/smydp_catalogo.css b/static/css/smydp_catalogo.css index 54ef8a19..bbb228b4 100755 --- a/static/css/smydp_catalogo.css +++ b/static/css/smydp_catalogo.css @@ -1,3 +1,5 @@ +/** Estilos del index (form principal)**/ + .row{ font-family: "Roboto", Sans-Serif ; } @@ -53,3 +55,14 @@ td{ text-decoration: underline; } +/** Estilos del Create form **/ + +.form-horizontal{ + +} + + +/** Estilos del Update form **/ + + +/** Estilos del View form **/ \ No newline at end of file diff --git a/views/smydp/catalogo.html b/views/smydp/catalogo.html index eeee9448..68957358 100644 --- a/views/smydp/catalogo.html +++ b/views/smydp/catalogo.html @@ -17,12 +17,17 @@ - +{{if table.create_form:}} + {{=table.create_form}} +{{elif table.update_form:}} + {{=table.update_form}} +{{elif table.view_form:}} + {{=table.view_form}} +{{else:}}
-
-

{{=table}}

-
+ {{=table}}
+{{pass}} +{{end}} \ No newline at end of file diff --git a/views/layout.html b/views/layout.html index 52276568..72bb9e8a 100755 --- a/views/layout.html +++ b/views/layout.html @@ -56,7 +56,7 @@ -
{{end}} \ No newline at end of file diff --git a/views/smydp/inventarios.html b/views/smydp/inventarios.html index a043104e..91d13ce3 100644 --- a/views/smydp/inventarios.html +++ b/views/smydp/inventarios.html @@ -56,6 +56,6 @@
{{end}} \ No newline at end of file diff --git a/views/smydp/sustancias.html b/views/smydp/sustancias.html index 26e44245..6b8b21f5 100644 --- a/views/smydp/sustancias.html +++ b/views/smydp/sustancias.html @@ -49,6 +49,6 @@

Inventarios

{{end}} \ No newline at end of file From 4a81689a69b1bf4879b60fa120cb3c29ae5fd93b Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 03:39:05 +0000 Subject: [PATCH 21/91] Arreglando links al nuevo index (ubicado en default/index en vez de modulos/index) --- controllers/default.py | 11 ++++++----- controllers/modulos.py | 13 ++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/controllers/default.py b/controllers/default.py index 30f60ccd..a7f1a3a7 100755 --- a/controllers/default.py +++ b/controllers/default.py @@ -1,17 +1,18 @@ # ------------------------------------------------------------------------- # Controladores Basicos -# - index sera la accion basica de la aplicacion. +# - index sera la accion basica de la aplicacion donde se muestran los modulos de SMyDP, Personal y servicios # # - download y call son ejemplos de aplicaciones basicas de web2py. # ------------------------------------------------------------------------- -def register(): - return redirect(URL('modulos','register')) - -# Pagina principal (Boton de SMDP y otros modulos) +# Pagina principal +@auth.requires_login(otherwise=URL('modulos', 'login')) def index(): return dict() +def register(): + return redirect(URL('modulos','register')) + def recoverpassword(): return dict(form=auth.reset_password()) diff --git a/controllers/modulos.py b/controllers/modulos.py index a1aae39a..528d1f15 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -14,15 +14,13 @@ #------------------------------------- @auth.requires_login(otherwise=URL('modulos', 'login')) -def index(): - """ - @description Pagina principal de elección de módulos SMyDP o Otros Módulos - """ +def sigulab2(): return dict() +# Controlador auxiliar que redirije al controlador real del index 'default/index' @auth.requires_login(otherwise=URL('modulos', 'login')) -def sigulab2(): - return dict() +def index(): + return redirect(URL('default','index')) def authenticate(): """ @@ -56,8 +54,9 @@ def login(): en caso de que el usuario ya fue autenticado. """ if auth.user: - return redirect(URL('index')) + return redirect(URL('default', 'index')) + auth.settings.login_next = URL('default','index') form=auth.login() if request.vars['error'] == 'invalid_data': From 302ffff292737ff3dcb0d995717b7bcdc161525d Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 04:21:02 +0000 Subject: [PATCH 22/91] Agregando tabla 'es_tecnico' que mapea tecnicos a espacios fisicos --- languages/es.py | 1 + models/modelos_base.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/languages/es.py b/languages/es.py index d1129b2d..3a8c60e4 100755 --- a/languages/es.py +++ b/languages/es.py @@ -548,6 +548,7 @@ 'TSV (Excel compatible)': 'TSV (compatible con Excel)', 'TSV (Excel compatible, hidden cols)': 'TSV (compatible con Excel, columnas ocultas)', 'Twitter': 'Twitter', +'Técnico': 'Técnico', 'Ubicación Física': 'Ubicación Física', 'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones', 'unable to create application "%s"': 'no es posible crear la aplicación "%s"', diff --git a/models/modelos_base.py b/models/modelos_base.py index 64841744..d666be16 100755 --- a/models/modelos_base.py +++ b/models/modelos_base.py @@ -166,3 +166,14 @@ ) db.espacios_fisicos._plural = 'Espacio Fisico' db.espacios_fisicos._singular = 'Espacio Fisico' + + +# Tabla que mapea tecnicos con sus respectivos Espacios Fisicos. Ejemplo: TecnicoX "es_tecnico" del espacio fisico Espacio_fisicoY +db.define_table( + 'es_tecnico', + #Atributos; + Field('tecnico', 'reference t_Personal', + requires=IS_IN_DB(db, db.t_Personal.id, '%(f_ci)s', zero=None), label=T('Técnico')), + Field('espacio_fisico', 'reference espacios_fisicos', + requires=IS_IN_DB(db, db.espacios_fisicos.id, '%(codigo)s', zero=None), label=T('Espacio Físico')) + ) \ No newline at end of file From 345147f3322ca59082e8645d30ea5fdd589be046 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 04:37:05 +0000 Subject: [PATCH 23/91] Agregando validador del CAS de sustancias para que sea de la forma n-m-p --- models/smydp.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/models/smydp.py b/models/smydp.py index ff14e7cd..88af253e 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -4,22 +4,23 @@ #t_Sustancia: Tabla de sustancias de la cual se obtiene informacion del listado (catalogo de sustancias) db.define_table( #Nombre de la entidad - 't_Sustancia', + 't_Sustancia', #Atributos; Field('f_nombre', 'string', requires=IS_NOT_EMPTY(), label=T('Nombre')), - Field('f_cas', 'string', requires=IS_NOT_EMPTY(), unique=True, label=T('CAS')), + Field('f_cas', 'string', requires=[ IS_NOT_EMPTY(), + IS_MATCH('^[0-9]+\-[0-9]+\-[0-9]+$', + error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], unique=True, label=T('CAS')), Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), - Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), - widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), - Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), - widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), - Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), - widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), + Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), + Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), + Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), # Hoja de seguridad (archivo pdf) Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad'), format='%(f_nombre)s'), - auth.signature) # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla + # Agrega los campos adicionales created_by, created_on, modified_by, modified_on para los logs de la tabla + auth.signature + ) -db.t_Sustancia.id.readable=False #Si se muestra en la forma, descomentar +db.t_Sustancia.id.readable=False db.t_Sustancia.id.writable=False db.t_Sustancia.f_hds.readable=(auth.has_membership('Gestor de SMyDP') or auth.has_membership('WEBMASTER')) #-*-* Chequear permisos aqui db.t_Sustancia._singular='Catálogo de Sustancias' From 0a5069d7601afc99e547e722f77fd39b0d9b2136 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 04:48:47 +0000 Subject: [PATCH 24/91] Cambiando widget de estado y control de una sustancia --- languages/es.py | 1 + models/smydp.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/languages/es.py b/languages/es.py index 3a8c60e4..119c0beb 100755 --- a/languages/es.py +++ b/languages/es.py @@ -208,6 +208,7 @@ 'Edit This App': 'Edite esta App', 'Editing file': 'Editando archivo', 'Editing file "%s"': 'Editando archivo "%s"', +'El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5': 'El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5', 'Email and SMS': 'Correo electrónico y SMS', 'Email del Responsable de la Solicitud': 'Email del Responsable de la Solicitud', 'Email sent': 'Correo electrónico enviado', diff --git a/models/smydp.py b/models/smydp.py index 88af253e..20d6c024 100644 --- a/models/smydp.py +++ b/models/smydp.py @@ -11,8 +11,8 @@ IS_MATCH('^[0-9]+\-[0-9]+\-[0-9]+$', error_message='El CAS debe contener tres números separados entre sí por guiones. Por ejemplo, 7732-18-5')], unique=True, label=T('CAS')), Field('f_pureza', 'integer', requires=IS_INT_IN_RANGE(0, 101), label=T('Pureza')), - Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Estado')), - Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.checkboxes.widget, label=T('Control')), + Field('f_estado', 'list:string',requires=IS_IN_SET(['Sólido','Líquido','Gaseoso']), widget=SQLFORM.widgets.options.widget, label=T('Estado')), + Field('f_control', 'list:string',requires=IS_IN_SET(['N/A','RL4','RL7', 'RL4 y RL7']), widget=SQLFORM.widgets.options.widget, label=T('Control')), Field('f_peligrosidad', 'list:string',requires=IS_IN_SET(['Inflamable','Tóxico','Tóxico para el ambiente','Corrosivo','Comburente','Nocivo','Explosivo','Irritante'],multiple = True), widget=SQLFORM.widgets.checkboxes.widget, label=T('Peligrosidad')), # Hoja de seguridad (archivo pdf) Field('f_hds','upload',requires=IS_NULL_OR(IS_UPLOAD_FILENAME(extension='pdf')),label=T('Hoja de seguridad'), format='%(f_nombre)s'), From 42b0945d9297b6058bcaf530a3af537a7b995f74 Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 06:46:11 +0000 Subject: [PATCH 25/91] Eliminando por completo controlador index en modulos. Vista principal ahora esta en default/index --- controllers/modulos.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/controllers/modulos.py b/controllers/modulos.py index 528d1f15..fd713a18 100755 --- a/controllers/modulos.py +++ b/controllers/modulos.py @@ -17,10 +17,6 @@ def sigulab2(): return dict() -# Controlador auxiliar que redirije al controlador real del index 'default/index' -@auth.requires_login(otherwise=URL('modulos', 'login')) -def index(): - return redirect(URL('default','index')) def authenticate(): """ @@ -42,7 +38,7 @@ def authenticate(): if not user: return "$('#authdiv').html('Datos de inicio de sesión incorrectos.')" else: - url = URL('index') + url = URL('default','index') return '$(location).attr("href", "' + str(url) + '")' def login(): From fe3d8a7e92c30fdf938624c1c63b2447658a294d Mon Sep 17 00:00:00 2001 From: saar1312 Date: Tue, 6 Mar 2018 08:24:55 +0000 Subject: [PATCH 26/91] Arreglando links a Inicio desde breadcrumbs --- models/modelos_base.py | 9 +++++++-- views/gestion/dependencias.html | 2 +- views/gestion/espacios_fisicos.html | 2 +- views/gestion/usuarios.html | 2 +- views/modulos/editprofile.html | 2 +- views/modulos/register.html | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/models/modelos_base.py b/models/modelos_base.py index d666be16..045260e0 100755 --- a/models/modelos_base.py +++ b/models/modelos_base.py @@ -168,7 +168,8 @@ db.espacios_fisicos._singular = 'Espacio Fisico' -# Tabla que mapea tecnicos con sus respectivos Espacios Fisicos. Ejemplo: TecnicoX "es_tecnico" del espacio fisico Espacio_fisicoY +# Tabla "es_tecnico" que mapea tecnicos con sus respectivos Espacios Fisicos. Ejemplo: TecnicoX "es_tecnico" del espacio +# fisico Espacio_fisicoY db.define_table( 'es_tecnico', #Atributos; @@ -176,4 +177,8 @@ requires=IS_IN_DB(db, db.t_Personal.id, '%(f_ci)s', zero=None), label=T('Técnico')), Field('espacio_fisico', 'reference espacios_fisicos', requires=IS_IN_DB(db, db.espacios_fisicos.id, '%(codigo)s', zero=None), label=T('Espacio Físico')) - ) \ No newline at end of file + ) + +# Tabla "es_encargado" que mapea al personal con las dependencias que tiene a cargo. Esta tabla sera necesaria si, por ejemplo +# una mismo persona puede ser jefa de seccion de varias secciones. Actualmente la tabla "t_Personal" es suficiente si se asume +# que esto no puede pasar. \ No newline at end of file diff --git a/views/gestion/dependencias.html b/views/gestion/dependencias.html index 693621e2..aaeb5d43 100644 --- a/views/gestion/dependencias.html +++ b/views/gestion/dependencias.html @@ -13,7 +13,7 @@