Compare commits
1197 Commits
Author | SHA1 | Date |
---|---|---|
El Mau | 34a981a2dd | |
El Mau | 66549e271b | |
El Mau | 884b10bd79 | |
El Mau | fd050159ba | |
El Mau | 8199667188 | |
El Mau | 05d3f617eb | |
El Mau | 0ec4f0c2c9 | |
El Mau | 29bfb42abc | |
El Mau | 7f129b84b2 | |
El Mau | 13a3c106c6 | |
El Mau | 0c7abf634b | |
El Mau | f0c4423fc8 | |
El Mau | d925587a98 | |
El Mau | 510ebdd1e5 | |
El Mau | d2e92098da | |
El Mau | c1ce206835 | |
El Mau | 1efa280920 | |
El Mau | 6fd8f9e2ea | |
El Mau | e3a44e6400 | |
El Mau | 390ec60fdd | |
El Mau | 957160755a | |
El Mau | 070ee31a1b | |
El Mau | 2620159408 | |
El Mau | 4d9bc4a172 | |
El Mau | 17ed56e9d7 | |
El Mau | 5057ac57ae | |
El Mau | 410a7080da | |
El Mau | edd8d560bd | |
El Mau | bd1699d082 | |
El Mau | 6d4023bb17 | |
Mauricio | beda45690f | |
Mauricio | 8feba167af | |
Mauricio | 4dbb797d99 | |
Mauricio | cd424b71dc | |
Mauricio | ea13d11319 | |
Mauricio | d9c863820a | |
Categulario | 6815d6c64c | |
Mauricio | 402cb7d70c | |
Mauricio | a5f1114774 | |
Mauricio | 2588a5f0b8 | |
Mauricio | eeae157772 | |
Mauricio | 7cad4093d4 | |
Mauricio | 7caf6423e1 | |
Mauricio | 8a3aea41eb | |
Mauricio | bd49356d3f | |
Mauricio | 3b54ef0a36 | |
Mauricio | 497a4be392 | |
Mauricio | 7fc6264322 | |
Mauricio | c5d0e97212 | |
Mauricio | 5bbad9ef58 | |
Mauricio | 8e7aa23d1b | |
Mauricio | f3d8b1dae5 | |
Mauricio | 2c684ae6bd | |
el Mau | febea3f289 | |
el Mau | 5facb96662 | |
el Mau | 6411c2e51e | |
el Mau | eeb128fda6 | |
el Mau | a078e27703 | |
el Mau | 28ef53043f | |
el Mau | e956c243f7 | |
el Mau | 1b33413de2 | |
el Mau | 64541a84b9 | |
el Mau | 834c1faae6 | |
el Mau | affe57bfcd | |
el Mau | 4dc54ade1e | |
el Mau | e72739a5fe | |
el Mau | dd7b9c1680 | |
el Mau | 9823bd967f | |
el Mau | aee467d98f | |
el Mau | 64917527f7 | |
el Mau | 5f56179ebb | |
el Mau | 955a0348f8 | |
el Mau | 0826b0cea2 | |
el Mau | 8b0f9fbc64 | |
el Mau | f3d827364b | |
el Mau | 50cbb3bae8 | |
el Mau | a7c8d80219 | |
el Mau | ca9d7a02e3 | |
el Mau | 31fcb63e51 | |
el Mau | bd7a31ea8a | |
el Mau | 6a6b6ca395 | |
el Mau | 3148c5ba82 | |
el Mau | 5f62ad7750 | |
el Mau | ff44162622 | |
el Mau | a37b3a5c23 | |
el Mau | 4fdea6173b | |
el Mau | 968c2744ec | |
el Mau | c9d85ca2e7 | |
el Mau | 93e64eafd8 | |
el Mau | 1984103ff5 | |
el Mau | e4ba06c0ff | |
el Mau | 38bb267e55 | |
el Mau | 602467c8e9 | |
el Mau | 4020237f68 | |
el Mau | 933c9820e6 | |
el Mau | 51daf0ad5e | |
el Mau | 709c524830 | |
el Mau | 434e15bb5b | |
el Mau | ae5949c529 | |
el Mau | af5fa3c812 | |
el Mau | 6d399fcb39 | |
el Mau | 8003fc42b9 | |
el Mau | 7a0fb2b243 | |
el Mau | 83bebde169 | |
el Mau | 76d5f51d78 | |
el Mau | 5f641c632e | |
el Mau | 85eb7cd58c | |
el Mau | 1c11a1b013 | |
el Mau | 701bb68478 | |
el Mau | f13491d983 | |
el Mau | 4020365616 | |
el Mau | a90f218c76 | |
el Mau | 37995befd8 | |
el Mau | 746c827492 | |
el Mau | 3cea54c07c | |
el Mau | 661eff1dc3 | |
el Mau | cd11456ec3 | |
el Mau | 2526a8f5aa | |
el Mau | 0a13004419 | |
el Mau | 296874a9b1 | |
el Mau | 34b1af1319 | |
el Mau | 5fbf80fb92 | |
el Mau | b56fee5f73 | |
el Mau | c9ca45b60d | |
el Mau | 86e7f50621 | |
el Mau | 2cef108856 | |
el Mau | 260ba62b2e | |
el Mau | 76d15e482b | |
el Mau | 8e2446e8f5 | |
el Mau | 482a0385cd | |
el Mau | 29e02e649d | |
el Mau | 5aece843bf | |
el Mau | d47e059d93 | |
el Mau | 89f79de9b6 | |
el Mau | fbaa85f13a | |
el Mau | bed6039fff | |
el Mau | acbaecbfc5 | |
el Mau | 8dddb7b293 | |
el Mau | 24777f691e | |
el Mau | 1d270aa478 | |
el Mau | 8872af8c50 | |
el Mau | d57ded161c | |
el Mau | 0c8d6d3cea | |
el Mau | f14c1f74d8 | |
el Mau | 210f50a7d7 | |
el Mau | 5418b23200 | |
el Mau | a13c7c0a1d | |
el Mau | a6276a33fb | |
el Mau | e3bd1e8871 | |
el Mau | 2ddb3d6b75 | |
Mauricio Baeza | 4cda9f7f21 | |
Mauricio Baeza | 7c184c9513 | |
Mauricio Baeza | aea8aeaecf | |
Mauricio Baeza | e08e4e038f | |
Mauricio Baeza | 496dcf7162 | |
Mauricio Baeza | f8cd99084a | |
Mauricio Baeza | 1e824bd841 | |
Mauricio Baeza | bc0cd9f3e1 | |
Mauricio Baeza | ae259e461b | |
Mauricio Baeza | 1a507d2eeb | |
Mauricio Baeza | f766f92618 | |
Mauricio Baeza | ad56356a6f | |
El Mau | c6cf33c4c4 | |
El Mau | dbc3910297 | |
El Mau | 6c78a282fe | |
El Mau | f8c2c5e2d6 | |
El Mau | 7d40e79f3c | |
El Mau | a36034a476 | |
El Mau | de2ab5cedd | |
El Mau | b60e2d6a37 | |
El Mau | d9021cca4a | |
El Mau | 7bbef31936 | |
El Mau | 74e7f12088 | |
El Mau | 20c0757f04 | |
El Mau | 3a5fbc609b | |
El Mau | 5e888d2337 | |
El Mau | d97fd4867a | |
El Mau | e58b8f90af | |
El Mau | 50d4a3f4b7 | |
El Mau | 1978edfaf0 | |
El Mau | 7ca87d1811 | |
El Mau | a7bc6d6f6c | |
El Mau | 1991c68b3b | |
El Mau | bebcd29710 | |
El Mau | de856f28ab | |
El Mau | e726cda085 | |
El Mau | eee386a97b | |
El Mau | ae21403c59 | |
El Mau | 110d41cf6e | |
El Mau | bd6fb65a1b | |
El Mau | b68d79d0ca | |
El Mau | 670aca3886 | |
El Mau | 68c0203039 | |
El Mau | b2cdd0efbe | |
El Mau | 51af15f311 | |
El Mau | edf35aa5ce | |
El Mau | b19d087d10 | |
El Mau | 64ef75fbf5 | |
El Mau | d6a8c1e3fa | |
El Mau | a7080bf954 | |
El Mau | 3ddf99075e | |
El Mau | bd6ba5d4d0 | |
El Mau | 6a18934b19 | |
El Mau | 61548c9135 | |
El Mau | fe3f743e32 | |
El Mau | c83e6981ae | |
El Mau | 39b9af125c | |
El Mau | dd606be46b | |
El Mau | 34df8882b3 | |
El Mau | e992103c57 | |
El Mau | 8f74d24b14 | |
El Mau | 480ec57d1e | |
El Mau | a38247727c | |
El Mau | 702aa264d8 | |
El Mau | 0422eece40 | |
El Mau | 12774af7ac | |
El Mau | b16eabd773 | |
El Mau | 1bab1cb23c | |
El Mau | 15a05e38f7 | |
El Mau | a0a8e0ce62 | |
El Mau | 825e23e369 | |
El Mau | 121831a139 | |
El Mau | c09a5749da | |
El Mau | 01ccbcabd5 | |
El Mau | cc0eee1443 | |
El Mau | 7a88c4b97f | |
El Mau | 0e7db2b711 | |
El Mau | 65851182c3 | |
El Mau | 2de98b9b92 | |
El Mau | 5a24bc159d | |
El Mau | f84721716c | |
El Mau | 8b91532b82 | |
El Mau | 0a98338fad | |
El Mau | 7bcf6d6e3c | |
El Mau | dbc8717575 | |
El Mau | 0adcd7f30f | |
El Mau | d237b33020 | |
El Mau | 5b997f7858 | |
El Mau | a609c0c6f5 | |
El Mau | d70cae64b7 | |
El Mau | 9daf07693a | |
El Mau | e40acd28ba | |
El Mau | 88dd9ca04b | |
El Mau | d2f879c224 | |
El Mau | 4922010caf | |
El Mau | ff8bc31f50 | |
El Mau | e795e87461 | |
El Mau | d2c361e174 | |
El Mau | 6b0ca817a3 | |
El Mau | 84fd8f57df | |
El Mau | f105f2a0fa | |
El Mau | ea145c630b | |
El Mau | 88bb6d9411 | |
El Mau | 0498217b65 | |
El Mau | 581e8bbdc5 | |
El Mau | c79e8492d3 | |
El Mau | f9df0d34d0 | |
El Mau | f06022ac69 | |
El Mau | 074cdc475f | |
El Mau | 0f041ed975 | |
El Mau | 6de30c3417 | |
El Mau | 8bbd2ba62b | |
El Mau | 00c58d9b41 | |
El Mau | a3d291c893 | |
El Mau | 86bc032413 | |
El Mau | a91feb15d7 | |
El Mau | 3ffc54f966 | |
El Mau | b3663dfcc6 | |
El Mau | 3cc11430d7 | |
El Mau | 4ae5197ced | |
El Mau | bf601dfcef | |
El Mau | 481594839d | |
El Mau | 7b2467f99a | |
El Mau | 2f22ad4cc8 | |
El Mau | 46d6329754 | |
El Mau | 2a2689a61b | |
El Mau | 76663fdd67 | |
El Mau | 54ab86a089 | |
El Mau | 7fe5251153 | |
El Mau | fe4829c6b8 | |
El Mau | bb90b3f6d7 | |
El Mau | f4779dbb99 | |
El Mau | 47ec5ad360 | |
El Mau | 80957afb84 | |
El Mau | b9af99aad6 | |
El Mau | 43e932e445 | |
El Mau | 8a151d42ad | |
El Mau | db77f6972d | |
El Mau | ef2314880f | |
El Mau | 1a1cb1173e | |
El Mau | fe26744a8f | |
El Mau | 69402e03bb | |
El Mau | 4a84654117 | |
El Mau | 81428c4f8e | |
El Mau | 28ef107949 | |
El Mau | e372f064b4 | |
El Mau | 46efb3693c | |
El Mau | d2bacc3b6b | |
El Mau | 264090f2a6 | |
El Mau | 425cd53df1 | |
El Mau | b7e8bb3cff | |
El Mau | 1df477e0b1 | |
El Mau | 9b09fbbcd1 | |
El Mau | f793cd2240 | |
El Mau | 54f2a574a3 | |
El Mau | 219f7c6712 | |
El Mau | 342f64a18b | |
El Mau | e880256cde | |
El Mau | 3a1cb8d142 | |
El Mau | 42a840f85c | |
Mauricio Baeza | 2e5f4ac27e | |
Mauricio Baeza | 98f091a347 | |
Mauricio Baeza | 82ec2faac5 | |
Mauricio Baeza | 11c0cc4899 | |
Mauricio Baeza | 1c9c829296 | |
Mauricio Baeza | 03f26b65e4 | |
Mauricio Baeza | 00f2b2b126 | |
Mauricio Baeza | c77438216d | |
Mauricio Baeza | b02b2b0e63 | |
Mauricio Baeza | 75788474ba | |
Mauricio Baeza | 866e8c40b9 | |
Mauricio Baeza | c64de2bbb9 | |
Mauricio Baeza | cd35884999 | |
Mauricio Baeza | c4e29e47fa | |
Mauricio Baeza | 00cbe4d557 | |
Mauricio Baeza | a95a6842f9 | |
Mauricio Baeza | 30a4a276dd | |
Mauricio Baeza | 416bc65174 | |
Mauricio Baeza | 3dd88f14d6 | |
Mauricio Baeza | fb24346601 | |
Mauricio Baeza | f792b79655 | |
Mauricio Baeza | 2055a904f6 | |
Mauricio Baeza | 7a1fd8fcaf | |
Mauricio Baeza | cd22a5a24d | |
Mauricio Baeza | 25e86cd28c | |
Mauricio Baeza | 4aad1a94eb | |
Mauricio Baeza | 229be3b415 | |
Mauricio Baeza | bc53171969 | |
Mauricio Baeza | 61a8937eb3 | |
Mauricio Baeza | be75abeb54 | |
Mauricio Baeza | 2c314a3891 | |
Mauricio Baeza | 7fc1d42381 | |
Mauricio Baeza | 0957cf673f | |
Mauricio Baeza | f99adaf109 | |
Mauricio Baeza | 91cfbb0508 | |
Mauricio Baeza | 4f18e1e01f | |
Mauricio Baeza | 7e7b08b1c0 | |
Mauricio Baeza | 4006322f30 | |
Mauricio Baeza | 935483f7ee | |
Mauricio Baeza | 80b766783d | |
Mauricio Baeza | 8822687308 | |
Mauricio Baeza | 0512e0f6dd | |
Mauricio Baeza | 93f0d09f4d | |
Mauricio Baeza | 870d95cb5a | |
Mauricio Baeza | 9fa35d5592 | |
Mauricio Baeza | 2bfe86973a | |
Mauricio Baeza | 896be35e3b | |
Mauricio Baeza | f2af10c2df | |
Mauricio Baeza | 8f7aaac563 | |
Mauricio Baeza | 8a615144a6 | |
Mauricio Baeza | 227204abec | |
Mauricio Baeza | 637c69b9c7 | |
Mauricio Baeza | 4f3bdbda95 | |
Mauricio Baeza | 34c467d26e | |
Mauricio Baeza | d61672dac4 | |
Mauricio Baeza | 1aa6540ac1 | |
Mauricio Baeza | 1b87591f62 | |
Mauricio Baeza | 986020a4a3 | |
Mauricio Baeza | 3514944f5d | |
Mauricio Baeza | 9be913c47d | |
Mauricio Baeza | b9d87f0343 | |
Mauricio Baeza | 585632882d | |
Mauricio Baeza | 920ff62e98 | |
Mauricio Baeza | dc61d3b010 | |
Mauricio Baeza | 62a0a82699 | |
Mauricio Baeza | 702ac88b38 | |
Mauricio Baeza | 535cc9d527 | |
Mauricio Baeza | cf35cd08cd | |
Mauricio Baeza | e9eeab8c2c | |
Mauricio Baeza | a518278b55 | |
Mauricio Baeza | 0442019ea5 | |
Mauricio Baeza | fa94e36e7f | |
Mauricio Baeza | 348be949ac | |
Mauricio Baeza | 565f36be3a | |
Mauricio Baeza | 7062151e79 | |
Mauricio Baeza | 5f1edc76ca | |
Mauricio Baeza | 5729a1f83e | |
Mauricio Baeza | 1a9087b13a | |
Mauricio Baeza | a2670cb92c | |
Mauricio Baeza | a8667a5d4f | |
Mauricio Baeza | 952dcba7ae | |
Mauricio Baeza | 676ff29b57 | |
Mauricio Baeza | 12a24c1117 | |
Mauricio Baeza | e59941db34 | |
Mauricio Baeza | 0e881eb17a | |
Mauricio Baeza | fa01e6cf01 | |
Mauricio Baeza | 51e2464141 | |
Mauricio Baeza | 3e43cc3b46 | |
Mauricio Baeza | b5bdcbbeb3 | |
Mauricio Baeza | 4f71dd0de3 | |
Mauricio Baeza | 720c9f0cb1 | |
Mauricio Baeza | 66d740e8d1 | |
Mauricio Baeza | 892906c46f | |
Mauricio Baeza | aa68225571 | |
Mauricio Baeza | 4f40bc3bfa | |
Mauricio Baeza | b03fbebe09 | |
Mauricio Baeza | 3cdbe14287 | |
Mauricio Baeza | 0bbf0b438f | |
Mauricio Baeza | c98cdd7fff | |
Mauricio Baeza | f0b5fa5ae9 | |
Mauricio Baeza | 537cecbb0b | |
Mauricio Baeza | 7f44f7f26d | |
Mauricio Baeza | c1e1c5ad7c | |
Mauricio Baeza | 3c574425eb | |
Mauricio Baeza | 5b8cd0ecb2 | |
Mauricio Baeza | 05a51741b6 | |
Mauricio Baeza | b3e2671359 | |
Mauricio Baeza | 5c047ee9d5 | |
Mauricio Baeza | b680d728a7 | |
Mauricio Baeza | 431422361b | |
Mauricio Baeza | 85e58c2728 | |
Mauricio Baeza | 739ac08205 | |
Mauricio Baeza | 64adba1588 | |
Mauricio Baeza | de06f706a6 | |
Mauricio Baeza | 6785dfebf7 | |
Mauricio Baeza | aaccece897 | |
Mauricio Baeza | 94f5df0723 | |
Mauricio Baeza | f813fb4dd8 | |
Mauricio Baeza | 49d5838822 | |
Mauricio Baeza | 51b4386b24 | |
Mauricio Baeza | 38f3c125cd | |
Mauricio Baeza | e678083eea | |
Mauricio Baeza | b612991476 | |
Mauricio Baeza | 32679fced3 | |
Mauricio Baeza | 8e4bf56846 | |
Mauricio Baeza | 0084197906 | |
Mauricio Baeza | ace4ef21a7 | |
Mauricio Baeza | 17fa99e45b | |
Mauricio Baeza | e547ce0113 | |
Mauricio Baeza | 858fd829aa | |
Mauricio Baeza | 788a1723b4 | |
Mauricio Baeza | 4b9df44dac | |
Mauricio Baeza | cca598310b | |
Mauricio Baeza | 39071be43b | |
Mauricio Baeza | e633f8e2bf | |
Mauricio Baeza | 21fd903943 | |
Mauricio Baeza | fec1c8523a | |
Mauricio Baeza | 0a04ec6c26 | |
Mauricio Baeza | a7945dba58 | |
Mauricio Baeza | 348a7f6ecb | |
Mauricio Baeza | cf189b08fa | |
Mauricio Baeza | 9423aeef6c | |
Mauricio Baeza | 90eec635ce | |
Mauricio Baeza | 8f15961d20 | |
Mauricio Baeza | 8a8f05384b | |
Mauricio Baeza | a54ad8d760 | |
Mauricio Baeza | 0389c0734f | |
Mauricio Baeza | cb04910a84 | |
Mauricio Baeza | 38c9c676af | |
Mauricio Baeza | e0d1f40a11 | |
Mauricio Baeza | d8ecae2c8f | |
Mauricio Baeza | 85c5a37798 | |
Mauricio Baeza | 56e52782f4 | |
Mauricio Baeza | aae856bb74 | |
Mauricio Baeza | 95399798f8 | |
Mauricio Baeza | 75e4f2e1c0 | |
Mauricio Baeza | f02b6782be | |
Mauricio Baeza | bd7508fe6b | |
Mauricio Baeza | 1f3e51861d | |
Mauricio Baeza | 3a51a50c8e | |
Mauricio Baeza | 1c6f9cd5f7 | |
Mauricio Baeza | b6c5c72df8 | |
Mauricio Baeza | 8d815bf570 | |
Mauricio Baeza | afced92aff | |
Mauricio Baeza | 443b916056 | |
Mauricio Baeza | 1d18d97b90 | |
Mauricio Baeza | 43808efc91 | |
Mauricio Baeza | 3ef195ed48 | |
Mauricio Baeza | 980a7aafdb | |
Mauricio Baeza | 1e95b180e8 | |
Mauricio Baeza | 267a96ebbc | |
Mauricio Baeza | 5e8d4d5fd9 | |
Mauricio Baeza | 8a293110ab | |
Mauricio Baeza | 4fcd7e18c0 | |
Mauricio Baeza | ed23a3531c | |
Mauricio Baeza | 82af00fedf | |
Mauricio Baeza | 763f3c21fb | |
Mauricio Baeza | 6b4eb36795 | |
Mauricio Baeza | 2877a68b92 | |
Mauricio Baeza | cca836bb6a | |
Mauricio Baeza | 26e4ce3d13 | |
Mauricio Baeza | 3166723cdc | |
Mauricio Baeza | a202f12a17 | |
Mauricio Baeza | bf3ed47fac | |
Mauricio Baeza | b2f3cdd66e | |
Mauricio Baeza | a17345c0fd | |
Mauricio Baeza | 7d7ca4eeba | |
Mauricio Baeza | d509bfb8be | |
Mauricio Baeza | 0a006f4508 | |
Mauricio Baeza | 71bd536cb1 | |
Mauricio Baeza | 068c57c018 | |
Mauricio Baeza | e94cda3577 | |
Mauricio Baeza | f102cb7c01 | |
Mauricio Baeza | 92e6a317ad | |
Mauricio Baeza | 77b35f8322 | |
Mauricio Baeza | 3f0daec6ad | |
Mauricio Baeza | a641024a86 | |
Mauricio Baeza | f9a73dfd66 | |
Mauricio Baeza | 2cc6e7046a | |
Mauricio Baeza | fe09860922 | |
Mauricio Baeza | aeb045e76a | |
Mauricio Baeza | 1c55fbd7c7 | |
Mauricio Baeza | e1b7e525df | |
Mauricio Baeza | 6f3d9cc3fa | |
Mauricio Baeza | cff2294601 | |
Mauricio Baeza | ce0e960534 | |
Mauricio Baeza | af6b13fa67 | |
Mauricio Baeza | df901090a2 | |
Mauricio Baeza | a87c78fc6b | |
Mauricio Baeza | abbb4cc608 | |
Mauricio Baeza | a67d174782 | |
Mauricio Baeza | 63ae4a5127 | |
Mauricio Baeza | 4574ff744f | |
Mauricio Baeza | 163e0f50c9 | |
Mauricio Baeza | 692477f41a | |
Mauricio Baeza | ae351b6148 | |
Mauricio Baeza | 519a61e132 | |
Mauricio Baeza | d7260a8a95 | |
Mauricio Baeza | 485dc4154e | |
Mauricio Baeza | 4bff2703a4 | |
Mauricio Baeza | 2ee2b8be43 | |
Mauricio Baeza | 6cef8fe669 | |
Mauricio Baeza | aad48639ee | |
Mauricio Baeza | 27a29d331c | |
Mauricio Baeza | 7a709f056c | |
Mauricio Baeza | 49f1c24df5 | |
Mauricio Baeza | 4a38410e8f | |
Mauricio Baeza | 2cacb786b6 | |
Mauricio Baeza | 7f33252fa1 | |
Mauricio Baeza | 79cea5b092 | |
Mauricio Baeza | 9ea396b133 | |
Mauricio Baeza | 4c2ea774b4 | |
Mauricio Baeza | da41bb272e | |
Mauricio Baeza | 8d7b42e368 | |
Mauricio Baeza | e292ba88b8 | |
Mauricio Baeza | 7e73541c96 | |
Mauricio Baeza | a0e1f83c25 | |
Mauricio Baeza | 8a4021ce49 | |
Mauricio Baeza | a4997be78d | |
Mauricio Baeza | 95d3345418 | |
Mauricio Baeza | f761ab7a5a | |
Mauricio Baeza | 5cdbb0aaa7 | |
Mauricio Baeza | c9f9ea526f | |
Mauricio Baeza | 06170cb054 | |
Mauricio Baeza | 43684b7fe9 | |
Mauricio Baeza | d48122608b | |
Mauricio Baeza | 3d300146f1 | |
Mauricio Baeza | 5ed281fd9d | |
Mauricio Baeza | dbf3a342bf | |
Mauricio Baeza | 43e643cccd | |
Mauricio Baeza | 454de7bf1e | |
Mauricio Baeza | 997dfe90ba | |
Mauricio Baeza | 812e510660 | |
Mauricio Baeza | 538a9f39ce | |
Mauricio Baeza | cf0c4b8622 | |
Mauricio Baeza | 7864e236db | |
Mauricio Baeza | 00bdd2b1a2 | |
Mauricio Baeza | 0d52e9b570 | |
Mauricio Baeza | 7dc65a2a2b | |
Mauricio Baeza | ff0ee73a73 | |
Mauricio Baeza | 2d045af037 | |
Mauricio Baeza | 4660e1d4e0 | |
Mauricio Baeza | 68ed8ee0db | |
Mauricio Baeza | 47ed1cb72e | |
Mauricio Baeza | dc8aeaebba | |
Mauricio Baeza | d2dc80a0c9 | |
Mauricio Baeza | e83281bdee | |
Mauricio Baeza | 0bddc189b4 | |
Mauricio Baeza | c2c8a10dec | |
Mauricio Baeza | 1dddbac0f2 | |
Mauricio Baeza | bbaf709e0e | |
Mauricio Baeza | c42bc817b7 | |
Mauricio Baeza | ba91d28fbd | |
Mauricio Baeza | 2765958a23 | |
Mauricio Baeza | c319ee454e | |
Mauricio Baeza | 9f919d77bc | |
Mauricio Baeza | 2090aa743d | |
Mauricio Baeza | af5d526bad | |
Mauricio Baeza | 4eb4cc8fa5 | |
Mauricio Baeza | 4007923f84 | |
Mauricio Baeza | 4a5bf615c4 | |
Mauricio Baeza | 63fc8e9a78 | |
Mauricio Baeza | 4f34599a6f | |
Mauricio Baeza | 5ac614e079 | |
Mauricio Baeza | 0465b684f0 | |
Mauricio Baeza | d70c35b4de | |
Mauricio Baeza | 3cc85e2644 | |
Mauricio Baeza | ae4c4b9355 | |
Mauricio Baeza | e7666432cb | |
Mauricio Baeza | 425f2ee079 | |
Mauricio Baeza | a6edbaa56f | |
Mauricio Baeza | db435a9b3d | |
Mauricio Baeza | aee9a83dd2 | |
Mauricio Baeza | acd8604e92 | |
Mauricio Baeza | eab8c3bb94 | |
Mauricio Baeza | a15ddd3544 | |
Mauricio Baeza | 23055b9af5 | |
Mauricio Baeza | 71d773f999 | |
Mauricio Baeza | 65587eb207 | |
Mauricio Baeza | d795069b38 | |
Mauricio Baeza | 17a9b00cb5 | |
Mauricio Baeza | 2e98d69685 | |
Mauricio Baeza | 0b73efaf9b | |
Mauricio Baeza | a7d0339660 | |
Mauricio Baeza | 135d469f3e | |
Mauricio Baeza | 43a50b833f | |
Mauricio Baeza | 44cf4089f7 | |
Mauricio Baeza | accd49d101 | |
Mauricio Baeza | 65d68db2d7 | |
Mauricio Baeza | 73fa31abc8 | |
Mauricio Baeza | 278bd06b72 | |
Mauricio Baeza | 12d26e01f9 | |
Mauricio Baeza | 6d3625caf7 | |
Mauricio Baeza | 760d33a389 | |
Mauricio Baeza | 18b1880772 | |
Mauricio Baeza | 933068069c | |
Mauricio Baeza | 66111d9080 | |
Mauricio Baeza | 525394dbed | |
Mauricio Baeza | 127ceceada | |
Mauricio Baeza | a05b370c33 | |
Mauricio Baeza | 8efe19fd24 | |
Mauricio Baeza | c8371a272f | |
Mauricio Baeza | 25cf581fcb | |
Mauricio Baeza | b6b5aa3447 | |
Mauricio Baeza | 0379fd6a6a | |
Mauricio Baeza | 30fab23c0d | |
Mauricio Baeza | b8f5dbd421 | |
Mauricio Baeza | 63b9d6729b | |
Mauricio Baeza | 5e6d86cb6b | |
Mauricio Baeza | b0de7655cc | |
Mauricio Baeza | 12297b9479 | |
Mauricio Baeza | dea511d161 | |
Mauricio Baeza | faa07f937f | |
Mauricio Baeza | 9081d54865 | |
Mauricio Baeza | ca4810bd3d | |
Mauricio Baeza | aece36905d | |
Mauricio Baeza | 1ee3f81dcc | |
Mauricio Baeza | 0ec7989c75 | |
Mauricio Baeza | e5a389a9dd | |
Mauricio Baeza | dd0585853a | |
Mauricio Baeza | 3dd73c1467 | |
Mauricio Baeza | f0ab9246e0 | |
Mauricio Baeza | 80b87348f0 | |
Mauricio Baeza | 8de2b20dcf | |
Mauricio Baeza | 6c0fc15053 | |
Mauricio Baeza | e8f27904d9 | |
Mauricio Baeza | d1b94cab57 | |
Mauricio Baeza | 31c6261183 | |
Mauricio Baeza | 118fa41d9b | |
Mauricio Baeza | b202827ee0 | |
Mauricio Baeza | fd75da65fc | |
Mauricio Baeza | 9dc2c72de7 | |
Mauricio Baeza | fdbfbb2bc0 | |
Mauricio Baeza | 6a724ac845 | |
Mauricio Baeza | 282f31497f | |
Mauricio Baeza | 54c01de410 | |
Mauricio Baeza | 6339e11c37 | |
Mauricio Baeza | 7896d66448 | |
Mauricio Baeza | 0f02411de6 | |
Mauricio Baeza | c438e7dc1d | |
Mauricio Baeza | 4608246b7d | |
Mauricio Baeza | ea18996111 | |
Mauricio Baeza | 7c00839b1f | |
Mauricio Baeza | 94240f2356 | |
Mauricio Baeza | 4ab3b22f29 | |
Mauricio Baeza | 88085bfa06 | |
Mauricio Baeza | 3163fef0d5 | |
Mauricio Baeza | cb6e4e21cf | |
Mauricio Baeza | 32ec443a19 | |
Mauricio Baeza | c85af83275 | |
Mauricio Baeza | 64caf4f415 | |
Mauricio Baeza | 064a65c0ae | |
Mauricio Baeza | 13836add29 | |
Mauricio Baeza | 0bf0769ad7 | |
Mauricio Baeza | f3309429e6 | |
Mauricio Baeza | 3ce31258e2 | |
Mauricio Baeza | f9e4bced15 | |
Mauricio Baeza | a04f92fab8 | |
Mauricio Baeza | c3d92ff45e | |
Mauricio Baeza | a8405a98fb | |
Mauricio Baeza | 3424f7f78a | |
Mauricio Baeza | dc1f48cc0b | |
Mauricio Baeza | 8c874dd8dd | |
Mauricio Baeza | de40cb0453 | |
Mauricio Baeza | 0caea7b0ce | |
Mauricio Baeza | da84fbafb6 | |
Mauricio Baeza | 43d4032b98 | |
Mauricio Baeza | cf5517d1ab | |
Mauricio Baeza | 32926740be | |
Mauricio Baeza | 7348b1bbba | |
Mauricio Baeza | 57dce9670b | |
Mauricio Baeza | 31627cca95 | |
Mauricio Baeza | 03ac074c66 | |
Mauricio Baeza | a83d628a75 | |
Mauricio Baeza | 1f043746dd | |
Mauricio Baeza | 95fa7aff14 | |
Mauricio Baeza | 66b5ceab1f | |
Mauricio Baeza | 5b15166c7a | |
Mauricio Baeza | 790e8ed7d6 | |
Mauricio Baeza | 0a48580f0c | |
Mauricio Baeza | 3869d4b48b | |
Mauricio Baeza | 2f797af8b2 | |
Mauricio Baeza | 001673cdb4 | |
Mauricio Baeza | e2da894d8b | |
Mauricio Baeza | 3e3c4be720 | |
Mauricio Baeza | aac5c04a3f | |
Mauricio Baeza | facba9b629 | |
Mauricio Baeza | 42d6e74dcd | |
Mauricio Baeza | 348f2d4443 | |
Mauricio Baeza | 27e131c057 | |
Mauricio Baeza | 313af2cce1 | |
Mauricio Baeza | afb3621a29 | |
Mauricio Baeza | 7308ec86ae | |
Mauricio Baeza | 175269cd3a | |
Mauricio Baeza | 3ef8807ee9 | |
Mauricio Baeza | ef076a9085 | |
Mauricio Baeza | 2d45a8258f | |
Mauricio Baeza | 900176a13b | |
Mauricio Baeza | 853a29de84 | |
Mauricio Baeza | 7bc4f4631d | |
Mauricio Baeza | 8acc4fe6bc | |
Mauricio Baeza | cc56139665 | |
Mauricio Baeza | 99abfd5859 | |
Mauricio Baeza | dc68b54f08 | |
Mauricio Baeza | 01ed2d9090 | |
Mauricio Baeza | 765e449d8f | |
Mauricio Baeza | b90e0a26ba | |
Mauricio Baeza | cee51df84a | |
Mauricio Baeza | 9ae0d7d924 | |
Mauricio Baeza | ff125d4623 | |
Mauricio Baeza | 07d51db625 | |
Mauricio Baeza | 952782f430 | |
Mauricio Baeza | a903f967b2 | |
Mauricio Baeza | eedd253e6a | |
Mauricio Baeza | 9605a96e7b | |
Mauricio Baeza | ac339e0ea8 | |
Mauricio Baeza | 362bec1fc3 | |
Mauricio Baeza | 9d2b79b53b | |
Mauricio Baeza | 73eb2f0b8c | |
Mauricio Baeza | 8e75a6cc16 | |
Mauricio Baeza | fd334eade4 | |
Mauricio Baeza | cf1eeac217 | |
Mauricio Baeza | 7bbfcd6cae | |
Mauricio Baeza | c45d95d762 | |
Mauricio Baeza | 6381975518 | |
Mauricio Baeza | 9f6e9e36fe | |
Mauricio Baeza | edd1be81ed | |
Mauricio Baeza | cb7b7b0a1c | |
Mauricio Baeza | a1a17732e8 | |
Mauricio Baeza | e7a4d38681 | |
Mauricio Baeza | ac4df43835 | |
Mauricio Baeza | 9a0f74eb52 | |
Mauricio Baeza | ddb3588995 | |
Mauricio Baeza | cf73669e3a | |
Mauricio Baeza | c38631daba | |
Mauricio Baeza | 3db6775f57 | |
Mauricio Baeza | 75f2d9d662 | |
Mauricio Baeza | 535958f3c1 | |
Mauricio Baeza | 8a03dba323 | |
Mauricio Baeza | d6079a6a43 | |
Mauricio Baeza | 874bf11447 | |
Mauricio Baeza | 9d3818e4ce | |
Mauricio Baeza | 8db62db775 | |
Mauricio Baeza | bb3f6d3aed | |
Mauricio Baeza | cdd97416ab | |
Mauricio Baeza | ebc544c8d8 | |
Mauricio Baeza | 5c3fb3e30f | |
Mauricio Baeza | 3c76d3a55f | |
Mauricio Baeza | 59d7e9d29d | |
Mauricio Baeza | 6847222ed6 | |
Mauricio Baeza | 89098eb21a | |
Mauricio Baeza | fc55005b1a | |
Mauricio Baeza | 0ee99296a6 | |
Mauricio Baeza | f3435b7b0c | |
Mauricio Baeza | e1424e2e70 | |
Mauricio Baeza | 316eb14e8c | |
Mauricio Baeza | 5bfcc4ca07 | |
Mauricio Baeza | 7185517a29 | |
Mauricio Baeza | b2148e1789 | |
Mauricio Baeza | d622975a89 | |
Mauricio Baeza | badf1b0f5f | |
Mauricio Baeza | d3419b5878 | |
Mauricio Baeza | f90539df82 | |
Mauricio Baeza | 1c65205bea | |
Mauricio Baeza | 3c5c597b81 | |
Mauricio Baeza | 4bd7e335d8 | |
Mauricio Baeza | acb3d3f40c | |
Mauricio Baeza | 8118ac306c | |
Mauricio Baeza | 09ccffdc62 | |
Mauricio Baeza | 17f6bdef98 | |
Mauricio Baeza | 0207b9fa78 | |
Mauricio Baeza | 34cb6a4a16 | |
Mauricio Baeza | 785cb32773 | |
Mauricio Baeza | c13a0a9628 | |
Mauricio Baeza | 77ff862400 | |
Mauricio Baeza | f55a78060d | |
Mauricio Baeza | 781623a64a | |
Mauricio Baeza | 1f40c42ba0 | |
Mauricio Baeza | 2272a4b6c7 | |
Mauricio Baeza | da730801d6 | |
Mauricio Baeza | 3df8e353dd | |
Mauricio Baeza | 13d82f1df8 | |
Mauricio Baeza | 87e37c58f8 | |
Mauricio Baeza | 47b56bab90 | |
Mauricio Baeza | dcfc80edc8 | |
Mauricio Baeza | f3a5aa4c06 | |
Mauricio Baeza | 3376505ea1 | |
Mauricio Baeza | abc1ae154b | |
Mauricio Baeza | 21eafd9e4a | |
Mauricio Baeza | f28ab95b50 | |
Mauricio Baeza | f9f80a52e7 | |
Mauricio Baeza | 4bd5a71008 | |
Mauricio Baeza | 2b7a51db97 | |
Mauricio Baeza | b56907e74e | |
Mauricio Baeza | 363f8bfce3 | |
Mauricio Baeza | b7b96611a6 | |
Mauricio Baeza | 5c05417999 | |
Mauricio Baeza | 06c32e56a8 | |
Mauricio Baeza | e67a1756a8 | |
Mauricio Baeza | e33e3379d7 | |
Mauricio Baeza | 7d386eca62 | |
Mauricio Baeza | 5466726898 | |
Mauricio Baeza | 069136d4c5 | |
Mauricio Baeza | 2141f84402 | |
Mauricio Baeza | 049f812459 | |
Mauricio Baeza | 0e909628dc | |
Mauricio Baeza | 7a573b8eda | |
Mauricio Baeza | 85ff55a2db | |
Mauricio Baeza | c21d14fe35 | |
Mauricio Baeza | b4f7749c6b | |
Mauricio Baeza | 1cfea6978b | |
Mauricio Baeza | 6a66b15f56 | |
Mauricio Baeza | 776c90a467 | |
Mauricio Baeza | cd8bd1ceeb | |
Mauricio Baeza | b4cab5aa2f | |
Mauricio Baeza | 1155b96eeb | |
Mauricio Baeza | d2f4d7c49d | |
Mauricio Baeza | 6202f9d424 | |
Mauricio Baeza | 6b24d7819d | |
Mauricio Baeza | 33994b6970 | |
Mauricio Baeza | 9c6659193c | |
Mauricio Baeza | 133aed9c85 | |
Mauricio Baeza | 012331b523 | |
Mauricio Baeza | 9785c7a72c | |
Mauricio Baeza | 64f5dd9170 | |
Mauricio Baeza | 8e4f43136c | |
Mauricio Baeza | e1b975f0f9 | |
Mauricio Baeza | 8aba4efc12 | |
Mauricio Baeza | b73d0d6284 | |
Mauricio Baeza | a01a085916 | |
Mauricio Baeza | 83dff5bc5f | |
Mauricio Baeza | 8bbbd9cdfb | |
Mauricio Baeza | ac481862d9 | |
Mauricio Baeza | de4499f238 | |
Mauricio Baeza | 14f17a6188 | |
Mauricio Baeza | 506cbde15b | |
Mauricio Baeza | 7e91476e47 | |
Mauricio Baeza | 4e3aa6f8a2 | |
Mauricio Baeza | e728d948d0 | |
Mauricio Baeza | e1ab743c29 | |
Mauricio Baeza | 5a791eec7c | |
Mauricio Baeza | 2c6e70a4b9 | |
Mauricio Baeza | 6687473931 | |
Mauricio Baeza | 675855c73b | |
Mauricio Baeza | 8da034885e | |
Mauricio Baeza | 7455c7de35 | |
Mauricio Baeza | 4cc5231ea9 | |
Mauricio Baeza | 0ce48a5977 | |
Mauricio Baeza | e326490e7f | |
Mauricio Baeza | 4ff9a03664 | |
Mauricio Baeza | e6d616a8ec | |
Mauricio Baeza | 8ef8fdb714 | |
Mauricio Baeza | 45acb380b6 | |
Mauricio Baeza | 5259fe9c80 | |
Mauricio Baeza | 33b5966a86 | |
Mauricio Baeza | 39a64f1437 | |
Mauricio Baeza | 1b710e729a | |
Mauricio Baeza | 853d8f7881 | |
Mauricio Baeza | 648c85095f | |
Mauricio Baeza | 35475694aa | |
Mauricio Baeza | 8889375a11 | |
Mauricio Baeza | 88b7fb0dc3 | |
Mauricio Baeza | c1cb34ba3e | |
Mauricio Baeza | 49563020e4 | |
Mauricio Baeza | deeeabd376 | |
Mauricio Baeza | a0db6d1f13 | |
Mauricio Baeza | d10a7c1641 | |
Mauricio Baeza | 99e843db15 | |
Mauricio Baeza | 2495997dad | |
Mauricio Baeza | 67ae4d0319 | |
Mauricio Baeza | cbc3ac0791 | |
Mauricio Baeza | 43cc6e0cc6 | |
Mauricio Baeza | 5cfbb70c4c | |
Mauricio Baeza | 3804378611 | |
Mauricio Baeza | d44d0ea263 | |
Mauricio Baeza | 71a292796c | |
Mauricio Baeza | edcd1ae04e | |
Mauricio Baeza | 046a61a2f2 | |
Mauricio Baeza | a946a1aa9a | |
Mauricio Baeza | a1a37d17ed | |
Mauricio Baeza | f4863db8ea | |
Mauricio Baeza | 2c5603d81b | |
Mauricio Baeza | 9fcd8c0503 | |
Mauricio Baeza | a1cc42f02e | |
Mauricio Baeza | 6a32760b05 | |
Mauricio Baeza | a9a0f32504 | |
Mauricio Baeza | 7873a4376c | |
Mauricio Baeza | 095e2e9dad | |
Mauricio Baeza | 65a3bc931f | |
Mauricio Baeza | 05a6357b7b | |
Mauricio Baeza | c1c50d5102 | |
Mauricio Baeza | 82c8f31043 | |
Mauricio Baeza | aa66bc47dc | |
Mauricio Baeza | 1cd87c81e2 | |
Mauricio Baeza | 1cc7d1f1b8 | |
Mauricio Baeza | 06430aa922 | |
Mauricio Baeza | 3f835d4d5c | |
Mauricio Baeza | bae8af881e | |
Mauricio Baeza | 4fc525246a | |
Mauricio Baeza | e63fb7b5c4 | |
Mauricio Baeza | cc10de702b | |
Mauricio Baeza | bb7486be94 | |
Mauricio Baeza | 8f7c1c3a31 | |
Mauricio Baeza | d7d6b6efda | |
Mauricio Baeza | f856d432b2 | |
Mauricio Baeza | af0b2b6c56 | |
Mauricio Baeza | 741d0c506f | |
Mauricio Baeza | 6df74dfc05 | |
Mauricio Baeza | 6125623c5f | |
Mauricio Baeza | fe949de513 | |
Mauricio Baeza | 51ae946b79 | |
Mauricio Baeza | 95f0a0b490 | |
Mauricio Baeza | 5aaa6c1d20 | |
Mauricio Baeza | 564d784a63 | |
Mauricio Baeza | fe37e92766 | |
Mauricio Baeza | 02d59dfc6d | |
Mauricio Baeza | 31bfc9e955 | |
Mauricio Baeza | 99ae0181c1 | |
Mauricio Baeza | e196a5fac9 | |
Mauricio Baeza | ab31399670 | |
Mauricio Baeza | 1fe6a6b904 | |
Mauricio Baeza | d470b44339 | |
Mauricio Baeza | 3a9d3c2c58 | |
Mauricio Baeza | 772d5d0af0 | |
Mauricio Baeza | f5aa8b7936 | |
Mauricio Baeza | 1867c4aa03 | |
Mauricio Baeza | 58f167d7f0 | |
Mauricio Baeza | 98c58a9003 | |
Mauricio Baeza | 52151fcd2b | |
Mauricio Baeza | 03fecfb1e2 | |
Mauricio Baeza | 137f38c773 | |
Mauricio Baeza | 069a4cdfa1 | |
Mauricio Baeza | fa4a55db19 | |
Mauricio Baeza | 752e0f27ad | |
Mauricio Baeza | 4e98593e61 | |
Mauricio Baeza | da0afdbe77 | |
Mauricio Baeza | 04fda8b9a2 | |
Mauricio Baeza | 595e00fb13 | |
Mauricio Baeza | 8642769580 | |
Mauricio Baeza | 81b34094ee | |
Mauricio Baeza | bde6943e73 | |
Mauricio Baeza | 234335a37f | |
Mauricio Baeza | e2643c9984 | |
Mauricio Baeza | 1cd9b541a3 | |
Mauricio Baeza | ead466e90c | |
Mauricio Baeza | 3029f84874 | |
Mauricio Baeza | 59de554b2b | |
Mauricio Baeza | bee911504b | |
Mauricio Baeza | 6f9b7df71e | |
Mauricio Baeza | 98e6cc389a | |
Mauricio Baeza | c09494546b | |
Mauricio Baeza | f8932d369d | |
Mauricio Baeza | 7cfa0f3834 | |
Mauricio Baeza | b48d6bd1f5 | |
Mauricio Baeza | 87884d0438 | |
Mauricio Baeza | 8048a07852 | |
Mauricio Baeza | a7d694e1dc | |
Mauricio Baeza | 5fa6ce9394 | |
Mauricio Baeza | 2a141c22f1 | |
Mauricio Baeza | 4e428ab1b7 | |
Mauricio Baeza | aa6d317c85 | |
Mauricio Baeza | 4221db615c | |
Mauricio Baeza | 8c8c3afd30 | |
Mauricio Baeza | 19c0ec91af | |
Mauricio Baeza | 21bf7451cc | |
Mauricio Baeza | 6de21e75bd | |
Mauricio Baeza | f5b34eec5b | |
Mauricio Baeza | 5f6ccf1a77 | |
Mauricio Baeza | d88caeb8c6 | |
Mauricio Baeza | ca9fe39f5e | |
Mauricio Baeza | 4a0fed1630 | |
Mauricio Baeza | 0d02c8bd3e | |
Mauricio Baeza | 0662a046c2 | |
Mauricio Baeza | 012936cc67 | |
Mauricio Baeza | 35806fcfcb | |
Mauricio Baeza | 0bb7eca83e | |
Mauricio Baeza | 24ce672dfa | |
Mauricio Baeza | 49595b6ab0 | |
Mauricio Baeza | 8993362277 | |
Mauricio Baeza | 7b4563ed17 | |
Mauricio Baeza | 7e08bfb5a5 | |
Mauricio Baeza | 233482c16c | |
Mauricio Baeza | 9e7e7a6a3d | |
Mauricio Baeza | af26b9d62f | |
Mauricio Baeza | 0993bee9ed | |
Mauricio Baeza | b401fa21a5 | |
Mauricio Baeza | 4632779331 | |
Mauricio Baeza | aeff1a3691 | |
Mauricio Baeza | 1d35ce7324 | |
Mauricio Baeza | 9742550c27 | |
Mauricio Baeza | 5c72ff459d | |
Mauricio Baeza | ba4c3d9dbd | |
Mauricio Baeza | ffda7867a4 | |
Mauricio Baeza | d1158bc285 | |
Mauricio Baeza | 5a104b4a57 | |
Mauricio Baeza | ef08e750bb | |
Mauricio Baeza | 1de2ff7255 | |
Mauricio Baeza | 14b4421eda | |
Mauricio Baeza | afd6c71066 | |
Mauricio Baeza | 130180ba14 | |
Mauricio Baeza | 2944ddc6f1 | |
Mauricio Baeza | 2a92b3df58 | |
Mauricio Baeza | 05c540495e | |
Mauricio Baeza | caee632ebb | |
Mauricio Baeza | 1c3c75af13 | |
Mauricio Baeza | fad45cb502 | |
Mauricio Baeza | 75d990d741 | |
Mauricio Baeza | 3e323678d7 | |
Mauricio Baeza | 9376fee407 | |
Mauricio Baeza | e39e4c5585 | |
Mauricio Baeza | 448eeb653c | |
Mauricio Baeza | 5ab7df2fd8 | |
Mauricio Baeza | 2cc0c9fc44 | |
Mauricio Baeza | 00988fca52 | |
Mauricio Baeza | 7b1e015020 | |
Mauricio Baeza | dd2ff53e6a | |
Mauricio Baeza | 72a5c72ed3 | |
Mauricio Baeza | aa9eea9dd5 | |
Mauricio Baeza | 82079423c9 | |
Mauricio Baeza | 524db01ac9 | |
Mauricio Baeza | ee8c437532 | |
Mauricio Baeza | 42d041c715 | |
Mauricio Baeza | 3626303bc7 | |
Mauricio Baeza | 67584b2f67 | |
Mauricio Baeza | 02d843ac3f | |
Mauricio Baeza | 8032c867c0 | |
Mauricio Baeza | e1a683ae23 | |
Mauricio Baeza | 71884e9984 | |
Mauricio Baeza | 7463a692b4 | |
Mauricio Baeza | c314268b35 | |
Mauricio Baeza | 4c85851b45 | |
Mauricio Baeza | d3afe55eef | |
Mauricio Baeza | c027f7a136 | |
Mauricio Baeza | 1c8fff1d37 | |
Mauricio Baeza | 5413f80c5a | |
Mauricio Baeza | c10039a561 | |
Mauricio Baeza | ac3168e7b0 | |
Mauricio Baeza | 3c1060252f | |
Mauricio Baeza | 37c3b00362 | |
Mauricio Baeza | c58c0ed395 | |
Mauricio Baeza | ce53a65c66 | |
Mauricio Baeza | 93e91ec367 | |
Mauricio Baeza | ea8f88ef1d | |
Mauricio Baeza | b2f7cc4341 | |
Mauricio Baeza | ac28ab43f8 | |
Mauricio Baeza | 7861974761 | |
Mauricio Baeza | d4e9d1701a | |
Mauricio Baeza | 12bac7d8a6 | |
Mauricio Baeza | c7e4febb0c | |
Mauricio Baeza | 94750e8cac | |
Mauricio Baeza | 4699c429fa | |
Mauricio Baeza | 160f8c3453 | |
Mauricio Baeza | 28146ed47a | |
Mauricio Baeza | b777e1774f | |
Mauricio Baeza | 937329bd9c | |
Mauricio Baeza | c7bd84f9bf | |
Mauricio Baeza | db4018661c | |
Mauricio Baeza | ff0a2f27b1 | |
Mauricio Baeza | d5027988dd | |
Mauricio Baeza | c47b242520 | |
Mauricio Baeza | f430947708 | |
Mauricio Baeza | 9b4d0bffd7 | |
Mauricio Baeza | ccdfacb476 | |
Mauricio Baeza | 3ef40892cc | |
Mauricio Baeza | cab7878288 | |
Mauricio Baeza | 50ed11ed7f | |
Mauricio Baeza | 19c0708d15 | |
Mauricio Baeza | 3a10c146d2 | |
Mauricio Baeza | 9796ffb6f3 | |
Mauricio Baeza | 2229f5c63f | |
Mauricio Baeza | 3e6dc1eda2 | |
Mauricio Baeza | eaa762a7ff | |
Mauricio Baeza | c5da06ec31 | |
Mauricio Baeza | 3949a89824 | |
Mauricio Baeza | 25a331fa09 | |
Mauricio Baeza | eed9b1d29c | |
Mauricio Baeza | db6743745b | |
Mauricio Baeza | 1997db32b0 | |
Mauricio Baeza | f0ec3c0344 | |
Mauricio Baeza | bc46bf992a | |
Mauricio Baeza | 48670592f3 | |
Mauricio Baeza | 4db008dd00 | |
Mauricio Baeza | ce79d8a77c | |
Mauricio Baeza | 7bdcdab7da | |
Mauricio Baeza | 9e150a103e | |
Mauricio Baeza | 493f78fda5 | |
Mauricio Baeza | 8fecfb8f56 | |
Mauricio Baeza | 57fad9ff09 | |
Mauricio Baeza | 677572c0d3 | |
Mauricio Baeza | 9221143b4a | |
Mauricio Baeza | da95cc6bc0 | |
Mauricio Baeza | e8df72b0fc | |
Mauricio Baeza | ed1f5a470f | |
Mauricio Baeza | 9057c39247 | |
Mauricio Baeza | 4fc6908a8d | |
Mauricio Baeza | 3a88d82957 | |
Mauricio Baeza | 980bb710ce | |
Mauricio Baeza | 13053b24e3 | |
Mauricio Baeza | 5d1d0c8c79 | |
Mauricio Baeza | 4d0d387e19 | |
Mauricio Baeza | 53652804c7 | |
Mauricio Baeza | 5acb893cf8 | |
Mauricio Baeza | 29ecedda82 | |
Mauricio Baeza | 4755223c12 | |
Mauricio Baeza | a0c8b2e336 | |
Mauricio Baeza | 9720bece80 | |
Mauricio Baeza | 589792c05f | |
Mauricio Baeza | 92ff62d9f0 | |
Mauricio Baeza | c02f5dc25f | |
Mauricio Baeza | 0f82665722 | |
Mauricio Baeza | d58ff69597 | |
Mauricio Baeza | 858eafd6ab | |
Mauricio Baeza | b01f3e92a9 | |
Mauricio Baeza | b973fecaf3 | |
Mauricio Baeza | efec0c1396 | |
Mauricio Baeza | 402f54f9c6 | |
Mauricio Baeza | 37aea443d6 | |
Mauricio Baeza | f2c9de3660 | |
Mauricio Baeza | f99a0da8d9 | |
Mauricio Baeza | 50a8c277bf | |
Mauricio Baeza | 6644eef0ab | |
Mauricio Baeza | de675a0de1 | |
Mauricio Baeza | 38f2b5a610 | |
Mauricio Baeza | bb14b54402 | |
Mauricio Baeza | 37af9178f9 | |
Mauricio Baeza | 815548845c | |
Mauricio Baeza | 9c4aebf3d8 | |
Mauricio Baeza | 596f826c3d | |
Mauricio Baeza | ef27dd8672 | |
Mauricio Baeza | 551d2c0eff | |
Mauricio Baeza | 78c9d07057 | |
Mauricio Baeza | bd73871cb0 | |
Mauricio Baeza | 85de4e5d90 | |
Mauricio Baeza | d4af8c7771 | |
Mauricio Baeza | 498a496cd9 | |
Mauricio Baeza | 88c42a2b1b | |
Mauricio Baeza | f8afdcc59a | |
Mauricio Baeza | 842d8610cc | |
Mauricio Baeza | 0c575d9376 | |
Mauricio Baeza | 7b495c4bbd | |
Mauricio Baeza | 0f9c03c68b | |
Mauricio Baeza | 9a4a35f03d | |
Mauricio Baeza | a9c1f1090c | |
Mauricio Baeza | d80cfd983d | |
Mauricio Baeza | 15a31d41f6 | |
Mauricio Baeza | c9ab9c39a1 | |
Mauricio Baeza | 6db103caba | |
Mauricio Baeza | 3d89724290 | |
Mauricio Baeza | 18a6678b19 | |
Mauricio Baeza | 191774f0e3 | |
Mauricio Baeza | b59c9ae000 | |
Mauricio Baeza | 5a3421f296 | |
Mauricio Baeza | 7a3e12d30c | |
Mauricio Baeza | 4502cc8dff | |
Mauricio Baeza | 8de2d61fa4 | |
Mauricio Baeza | ac3fa342d6 | |
Mauricio Baeza | c790208706 | |
Mauricio Baeza | 143d9c2f0e | |
Mauricio Baeza | 5c84f590c4 | |
Mauricio Baeza | 95db2cbda7 | |
Mauricio Baeza | 739a4a88b2 | |
Mauricio Baeza | 95503188d9 | |
Mauricio Baeza | 848c507e47 | |
Mauricio Baeza | 671f9698cf | |
Mauricio Baeza | b9dde26062 | |
Mauricio Baeza | 5efc3a9ce7 | |
Mauricio Baeza | a30bb4fcd3 |
|
@ -2,6 +2,7 @@
|
|||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
Pipfile*
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
@ -12,12 +13,26 @@ source/fixtures
|
|||
source/media
|
||||
|
||||
# Sphinx documentation
|
||||
docs/
|
||||
*.ods
|
||||
*.xlsx
|
||||
|
||||
bk/
|
||||
source/docs/
|
||||
site/
|
||||
vedev/
|
||||
|
||||
# Virtualenv
|
||||
.env/
|
||||
virtual/
|
||||
env
|
||||
|
||||
docs/build
|
||||
cache/
|
||||
credenciales.conf
|
||||
*.sqlite
|
||||
*.sql
|
||||
*.service
|
||||
*.orig
|
||||
rfc.db
|
||||
Dockerfile
|
||||
chuletas/
|
||||
|
||||
|
|
826
CHANGELOG.md
|
@ -1,3 +1,829 @@
|
|||
v 2.3.2 [10-Abr-2024]
|
||||
- Fix: En las mercancias en la Carta Porte al generar el PDF.
|
||||
|
||||
|
||||
v 2.3.1 [02-Abr-2024]
|
||||
- Fix: En la cantidad de la mercancia en la Carta Porte.
|
||||
|
||||
|
||||
v 2.3.0 [01-Abr-2024]
|
||||
- Mejora: Soporte para complemento Carta Porte 3.0
|
||||
- **IMPORTANTE**: Aunque no lo uses, esto afecta al JS de facturación, por
|
||||
lo que tienes que forzar el refresco (CTRL+F5) si tienes algún problema.
|
||||
|
||||
|
||||
v 2.2.0 [24-Ene-2024]
|
||||
- Mejora: Soporte para complemento Comercio Exterior 2.0
|
||||
- **IMPORTANTE**: Aunque no lo uses, esto afecta al JS de facturación, por
|
||||
lo que tienes que forzar el refresco (CTRL+F5) si tienes algún problema.
|
||||
|
||||
|
||||
v 2.1.0 [26-Dic-2023]
|
||||
- Mejora: Se agrega filtro por día en facturas.
|
||||
|
||||
|
||||
v 2.0.9 [20-Dic-2023]
|
||||
- Fix: Issue 98 y 107
|
||||
|
||||
|
||||
v 2.0.8 [30-Oct-2023]
|
||||
---------------------
|
||||
- Fix: Permitir generar CFDI de egreso para facturas globales sin datos globales.
|
||||
- Fix: Permitir cambiar la zona horaria para cuando se usa en servidor.
|
||||
|
||||
Es necesario hacer una migración:
|
||||
```
|
||||
cd /opt/empresa-libre
|
||||
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
|
||||
v 2.0.7 [06-Ju1-2023]
|
||||
---------------------
|
||||
- Fix: En tasa de retención de un Resico a una Persona Moral.
|
||||
|
||||
|
||||
v 2.0.6 [14-Jun-2023]
|
||||
---------------------
|
||||
- Fix: Al generar complementos de pago con facturas con retención de impuestos.
|
||||
|
||||
|
||||
v 2.0.5 [05-Jun-2023]
|
||||
---------------------
|
||||
- Fix: Al generar complementos de pago con facturas con varios impuestos.
|
||||
- Fix: ticket #103, hay que usar {receptor.correo_facturas} y {receptor.telefonos}
|
||||
|
||||
|
||||
v 2.0.2 [01-Abr-2023]
|
||||
---------------------
|
||||
- Fix: Obtener la clave del sat al facturar por lote.
|
||||
|
||||
|
||||
v 2.0.1 [29-Mar-2023]
|
||||
---------------------
|
||||
- Fix ticket #97
|
||||
|
||||
Es necesario hacer una migración:
|
||||
```
|
||||
cd /opt/empresa-libre
|
||||
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
|
||||
v 2.0.0 [08-Ene-2023]
|
||||
----------------------
|
||||
- Liberamos para todos la versión CFDI 4.0
|
||||
- **IMPORTANTE** NO intentes timbrar si **antes** no has validado en nuestro demo que puedes timbrar tus CFDIs habituales.
|
||||
|
||||
* IMPORTANTE:
|
||||
|
||||
Es necesario hacer una migración:
|
||||
|
||||
```
|
||||
cd /opt/empresa-libre
|
||||
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
Y reiniciar todo. IMPORTANTE: dependiendo desde que versión actualices, tal vez debas de hacer algún prodecimiento extra. Siempre revisa este historial.
|
||||
|
||||
|
||||
v 2.0.0 [31-Mar-2022]
|
||||
----------------------
|
||||
- Primera versión de timbrado con CFDI4
|
||||
- **IMPORTANTE** NO intentes timbrar si **antes** no has validado en nuestro demo que puedes timbrar tus CFDIs habituales.
|
||||
|
||||
|
||||
v 1.47.0 [28-Mar-2022]
|
||||
----------------------
|
||||
- Mejora: Soporte basico para complemento Comercio Exterior.
|
||||
|
||||
|
||||
v 1.46.5 [10-Mar-2022]
|
||||
----------------------
|
||||
- Error: Al timbrar nómina con Comercio Digital
|
||||
|
||||
|
||||
v 1.46.4 [18-Feb-2022]
|
||||
----------------------
|
||||
- Error: Issue #54
|
||||
|
||||
|
||||
v 1.46.3 [15-Feb-2022]
|
||||
----------------------
|
||||
- Error: Issue #53
|
||||
|
||||
|
||||
v 1.46.2 [31-Ene-2022]
|
||||
----------------------
|
||||
- Error: Al generar Carta Porte sin remolque.
|
||||
- Error: Al cancelar con Finkok.
|
||||
|
||||
|
||||
v 1.46.1 [29-Ene-2022]
|
||||
----------------------
|
||||
- Error: Issue #49
|
||||
- Mejora: Agregar validación para distancia en origen de Carta Porte.
|
||||
|
||||
|
||||
v 1.46.0 [27-Ene-2022]
|
||||
----------------------
|
||||
- Mejora: Issue #45
|
||||
- Mejora: Agregar tipos de persimos SCT para Carta Porte
|
||||
- Mejora: Buscar estado y municipio por CP en Carta Porte
|
||||
|
||||
|
||||
v 1.45.4 [25-Ene-2022]
|
||||
----------------------
|
||||
- Error: Al timbrar carta porte.
|
||||
- Error: Al cancelar con Comercio Digital.
|
||||
- Error: Issue #42
|
||||
- Mejora: Issue #44
|
||||
|
||||
* IMPORTANTE: Es necesario subir de nuevo tus certificados de sello, **solo** si timbras con Comercio Digital.
|
||||
|
||||
|
||||
v 1.45.3 [23-Ene-2022]
|
||||
----------------------
|
||||
- Error: El enviar por correo CFDI de pago. Ticket #40
|
||||
|
||||
|
||||
v 1.45.2 [21-Ene-2022]
|
||||
----------------------
|
||||
- Error: Al cancelar un CFDI
|
||||
|
||||
|
||||
v 1.45.1 [20-Ene-2022]
|
||||
----------------------
|
||||
- Error: Al enviar correos con la nueva configuración
|
||||
|
||||
|
||||
* IMPORTANTE: Revisa tu configuración de correo para verificar que todo funcione.
|
||||
|
||||
|
||||
v 1.45.0 [20-Ene-2022]
|
||||
----------------------
|
||||
- Importar Carta Porte desde archivo JSON
|
||||
|
||||
|
||||
v 1.44.2 [19-Ene-2022]
|
||||
----------------------
|
||||
- Agregar opción STARTTLS que requieren algunos servidores de correo
|
||||
|
||||
* IMPORTANTE: Revisa tu configuración de correo para verificar si tienes que usar esta opción.
|
||||
|
||||
|
||||
v 1.44.1 [19-Ene-2022]
|
||||
----------------------
|
||||
- Correciones en generación de Carta Porte v2.0
|
||||
- Plantilla para representación impresa de Carta Porte v2.0
|
||||
|
||||
|
||||
v 1.44.0 [10-Ene-2022]
|
||||
----------------------
|
||||
- Soporte para Carta Porte v2 con CFDI 3.3
|
||||
- Soporte para el nuevo esquema de cancelación del SAT
|
||||
|
||||
* IMPORTANTE:
|
||||
|
||||
Es necesario hacer una migración:
|
||||
|
||||
```
|
||||
cd /opt/empresa-libre
|
||||
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
|
||||
v 1.43.0 [12-Dic-2021]
|
||||
----------------------
|
||||
- Soporte para entradas de almacen.
|
||||
- Soporte para multi almacen.
|
||||
- Soporte para regenerar un ticket.
|
||||
- Soporte para movimientos entre almacenes
|
||||
- Consulta en SAT para estatus de nómina
|
||||
|
||||
* IMPORTANTE:
|
||||
|
||||
Instalar nuevo requerimiento:
|
||||
|
||||
```
|
||||
pip install segno
|
||||
```
|
||||
|
||||
Es necesario hacer una migración:
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
v 1.42.2 [14-Sep-2021]
|
||||
----------------------
|
||||
- Los productos pueden no llevar ningún impuesto.
|
||||
|
||||
|
||||
v 1.42.1 [01-Jun-2021]
|
||||
----------------------
|
||||
- Error - Ticket #5
|
||||
|
||||
|
||||
v 1.42.0 [24-May-2021]
|
||||
----------------------
|
||||
- Opción para que solo un admin pueda cancelar.
|
||||
|
||||
|
||||
v 1.41.4 [13-Abr-2021]
|
||||
----------------------
|
||||
- Error - Ticket #4
|
||||
|
||||
|
||||
v 1.41.3 [12-Feb-2021]
|
||||
----------------------
|
||||
- Error - Ticket #3
|
||||
|
||||
|
||||
v 1.41.2 [12-Feb-2021]
|
||||
----------------------
|
||||
- Error - Ticket #2
|
||||
|
||||
|
||||
v 1.41.1 [11-Feb-2021]
|
||||
----------------------
|
||||
- Error - Ticket #1
|
||||
|
||||
|
||||
v 1.41.0 [10-Feb-2021]
|
||||
----------------------
|
||||
- Importar clientes desde archivo CSV
|
||||
|
||||
|
||||
v 1.40.1 [09-Feb-2021]
|
||||
----------------------
|
||||
- Fix #422
|
||||
|
||||
|
||||
v 1.40.0 [05-ene-2021]
|
||||
----------------------
|
||||
- Error: Al parsear XML en Python 3.9+
|
||||
- Mejora: Agregar versión de Empresa Libre a plantilla.
|
||||
- Mejora: Sellado en memoria
|
||||
- Mejora: Se agrega un segundo PAC y se refactoriza el timbrado.
|
||||
|
||||
* **IMPORTANTE**
|
||||
|
||||
Es necesario seguir una serie de pasos **obligatorios** para migrar a esta
|
||||
versión, **no continues hasta seguir paso a paso** estas instrucciones.
|
||||
**Antes** de comenzar ten a la mano tus certificados de sello para timbrar, es
|
||||
necesario subirlos de nuevo. **NO actualices si no tienes tus certificados**
|
||||
con su respectiva contraseña, te quedarás sin poder timbrar.
|
||||
|
||||
Estas instrucciones solamente aplican para la maquina virtual con Ubuntu Server,
|
||||
la ultima y única versión sobre la que se dará soporte.
|
||||
|
||||
1. Entra a la parte administrativa y toma de tus credenciales de timbrado en el
|
||||
menú "Emisor" ficha "Otros Datos", usuario y token de timbrado.
|
||||
1. Agregar nuevos requerimientos `sudo apt install pkgconf libxml2-dev libxmlsec1-dev libxmlsec1-openssl`
|
||||
1. Agregar nuevo requerimiento `pip install --user xmlsec`
|
||||
1. Entrar a la carpeta del sistema: `/opt/empresa-libre`
|
||||
1. Actualizar `git pull origin master`
|
||||
1. Entrar a `source/app/controllers/pacs/comerciodigital` y copiar `conf.py.example` a `conf.py`
|
||||
1. Entrar a `source/app/controllers/pacs/finkok` y copiar `conf.py.example` a `conf.py`
|
||||
1. Agregar la variable `TOKEN = ''` al archivo `source/app/conf.py` mira el archivo de ejemplo en el mismo directorio.
|
||||
1. Reiniciar el servicio: `sudo systemctl restart empresalibre`
|
||||
1. Si no ves los cambios descritos a continuación, fuerza el refresco de tu navegador, generalmente con **CTRL+F5**
|
||||
1. Sube de nuevo tus certificados en el menú "Emisor" ficha "Certificado".
|
||||
1. Ve al menú "Opciones", ficha "Otros".
|
||||
1. Selecciona tu PAC, si tu usuario es un correo electrónico, invariablemente
|
||||
debes seleccionar Finkok. Si tienes duda ponte en contacto con nosotros.
|
||||
1. Establece las credenciales del punto 1.
|
||||
1. Guarda los datos.
|
||||
|
||||
|
||||
v 1.39.1 [17-sep-2020]
|
||||
----------------------
|
||||
- Error: Esquema para complemento IEDU
|
||||
|
||||
|
||||
v 1.39.0 [25-ago-2020]
|
||||
----------------------
|
||||
- Mejora: Consulta de las facturas de pago en el SAT
|
||||
- Mejora: Mostrar totales en nómina
|
||||
- Mejora: Mostrar totales por cantidad al facturar
|
||||
- Mejora: Validar líneas con importe cero antes de facturar
|
||||
- Error: Validaciones de namespace en CFDI de nómina por parte del PAC
|
||||
|
||||
|
||||
v 1.38.1 [30-mar-2020]
|
||||
----------------------
|
||||
- Error: En nómina al timbrar asimilados
|
||||
|
||||
|
||||
v 1.38.0 [08-mar-2020]
|
||||
----------------------
|
||||
- Mejora: Factura global por ticket o nota
|
||||
- Error: Al generar algunos PDFs
|
||||
|
||||
|
||||
v 1.37.0 [02-mar-2020]
|
||||
----------------------
|
||||
- Mejora: Soporte para complemento Leyendas Fiscales
|
||||
|
||||
* IMPORTANTE:
|
||||
|
||||
Es necesario hacer una migración, y agregar los campos necesarios para mostrar
|
||||
las leyendas, mira la carpeta pública con la plantilla de ejemplo.
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m -r RFC
|
||||
```
|
||||
|
||||
|
||||
v 1.36.0 [25-feb-2020]
|
||||
----------------------
|
||||
- Mejora: Permitir ver a usuarios todos los documentos
|
||||
|
||||
|
||||
v 1.35.0 [24-feb-2020]
|
||||
----------------------
|
||||
- Mejora: Filtrado de documentos por sucursal
|
||||
|
||||
|
||||
v 1.34.1 [09-feb-2020]
|
||||
----------------------
|
||||
- Error: Al timbrar nómina de asimilados
|
||||
|
||||
|
||||
v 1.34.0 [29-ene-2020]
|
||||
----------------------
|
||||
- Error: Al timbrar nómina
|
||||
|
||||
|
||||
v 1.33.2 [27-ene-2020]
|
||||
----------------------
|
||||
- Se actualizan métodos de pago en catálogos del SAT
|
||||
|
||||
* IMPORTANTE:
|
||||
Es necesario actualizar los catálogos del SAT
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -us
|
||||
```
|
||||
|
||||
|
||||
v 1.33.0 [22-ene-2020]
|
||||
----------------------
|
||||
- Mejora: Cambio del mensaje para cuando se intenta dar de alta un cliente ya existente.
|
||||
- Mejora: Solo los admins pueden ver la nómina.
|
||||
- Se agrega un segundo PAC
|
||||
- Se actualizan los catálogos del SAT
|
||||
|
||||
* IMPORTANTE:
|
||||
Es necesario actualizar los catálogos del SAT
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -us
|
||||
```
|
||||
|
||||
|
||||
v 1.32.0 [05-ene-2020]
|
||||
----------------------
|
||||
- Mejora: Recuperar facturas no aceptadas para cancelación por el receptor
|
||||
|
||||
|
||||
v 1.31.2 [28-oct-2019]
|
||||
----------------------
|
||||
- Error: Al generar PDF con tags en las series
|
||||
|
||||
|
||||
v 1.31.1 [28-ago-2019]
|
||||
----------------------
|
||||
- Error: Al agregar nuevo impuesto #369
|
||||
|
||||
|
||||
v 1.31.0 [23-abr-2019]
|
||||
----------------------
|
||||
- Error: Validar cantidad o valor unitario cero en tickets
|
||||
- Mejora: Envío de nómina por correo al empleado
|
||||
|
||||
|
||||
v 1.30.0 [24-mar-2019]
|
||||
----------------------
|
||||
- Mejora: Se actualizan los catálogos de Nómina
|
||||
|
||||
* IMPORTANTE:
|
||||
Es necesario realizar una migración, después de actualizar.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
|
||||
v 1.29.0 [08-mar-2019]
|
||||
----------------------
|
||||
- Error: Al mostrar detalle en facturas importadas #343
|
||||
- Mejora: Editar la descripción de un movimiento bancario.
|
||||
|
||||
|
||||
v 1.28.2 [04-mar-2019]
|
||||
----------------------
|
||||
- Error: Al enviar facturas de pago
|
||||
|
||||
|
||||
v 1.28.1 [04-mar-2019]
|
||||
----------------------
|
||||
- Error: Al buscar facturas por fechas
|
||||
|
||||
|
||||
v 1.28.0 [17-feb-2019]
|
||||
----------------------
|
||||
- Mejora: Manejo de empaques para mensajeria
|
||||
- Mejora: Usar concepto personalizado en deducciones de nómina 004 Otros
|
||||
- Mejora: Búsqueda en notas
|
||||
- Mejora: Soporte para el complemento de Divisas
|
||||
- Mejora: Descarga de nómina en lote
|
||||
|
||||
* IMPORTANTE:
|
||||
Es necesario realizar una migración, después de actualizar.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
Es necesario agregar un nuevo requerimiento.
|
||||
|
||||
```
|
||||
sudo pip install cryptography
|
||||
```
|
||||
|
||||
**IMPORTANTE** Si envias tus facturas por correo directamente, es necesario
|
||||
volver a capturar la contraseña de tu servidor de correo y guardar los datos
|
||||
nuevamente.
|
||||
|
||||
|
||||
v 1.27.1 [23-ene-2019]
|
||||
----------------------
|
||||
- Error: Al cancelar nómina
|
||||
|
||||
|
||||
v 1.27.0 [17-ene-2019]
|
||||
----------------------
|
||||
- Mejora: Permitir capturar folio manualmente
|
||||
|
||||
|
||||
v 1.26.1 [16-ene-2019]
|
||||
----------------------
|
||||
- Error: Guardar logos de emisor
|
||||
|
||||
|
||||
v 1.26.0 [15-ene-2019]
|
||||
----------------------
|
||||
- Mejora: Generar PDF desde plantilla JSON
|
||||
|
||||
|
||||
v 1.25.0 [07-nov-2018]
|
||||
----------------------
|
||||
- Fix: Al importar días de pago en nómina
|
||||
- Fix: Al importar descripción en factura en lote
|
||||
|
||||
|
||||
v 1.24.0 [06-nov-2018]
|
||||
----------------------
|
||||
- Fix: Consulta estatus SAT
|
||||
|
||||
|
||||
v 1.23.0 [30-oct-2018]
|
||||
----------------------
|
||||
- Mejora: Permitir importar CFDI 3.2
|
||||
|
||||
|
||||
v 1.22.0 [25-oct-2018]
|
||||
----------------------
|
||||
- Mejora: Permitir cambiar descripción al facturar en lote
|
||||
|
||||
|
||||
v 1.21.2 [23-oct-2018]
|
||||
----------------------
|
||||
- Error unicode
|
||||
|
||||
|
||||
v 1.21.1 [14-oct-2018]
|
||||
----------------------
|
||||
- Error #307
|
||||
|
||||
|
||||
v 1.21.0 [12-oct-2018]
|
||||
----------------------
|
||||
- Error #287
|
||||
- Mejora: Complemento de pago con datos de cuentas
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar.
|
||||
|
||||
|
||||
v 1.20.0 [08-oct-2018]
|
||||
----------------------
|
||||
- Error #295
|
||||
- Mejora: Cuentas de banco para clientes
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar.
|
||||
|
||||
|
||||
v 1.19.1 [03-oct-2018]
|
||||
----------------------
|
||||
- Error #291
|
||||
- Error al generar PDF de factura de pago con relacionados sin serie
|
||||
- Error al relacionar facturas versión 3.2
|
||||
|
||||
v 1.19.0 [28-sep-2018]
|
||||
----------------------
|
||||
- Mejora #280
|
||||
- Mejora #288
|
||||
- Error #290
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
|
||||
v 1.18.0 [27-sep-2018]
|
||||
----------------------
|
||||
- Fix #282 Factura de pago en otras monedas
|
||||
|
||||
|
||||
v 1.17.0 [25-sep-2018]
|
||||
----------------------
|
||||
- Fix - Al generar factura de pago con documentos relacionados en otras monedas
|
||||
- Fix - Al generar factura de pago sin serie en documentos relacionados
|
||||
- Fix #278
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
|
||||
v 1.16.1 [18-sep-2018]
|
||||
----------------------
|
||||
- Error https://gitlab.com/mauriciobaeza/empresa-libre/issues/268
|
||||
- IMPORTANTE: Actualizar si usas cuatro decimales en impuestos
|
||||
|
||||
|
||||
v 1.16.0 [16-sep-2018]
|
||||
----------------------
|
||||
- Se puede editar el saldo de un cliente
|
||||
- Se muestra la cantidad de facturas de pago en los movimientos
|
||||
|
||||
|
||||
v 1.15.0 [12-sep-2018]
|
||||
----------------------
|
||||
- Se pueden mover las facturas con doble clic en los movimientos de banco.
|
||||
- Fix - Al sumar las facturas en los depósitos
|
||||
- Fix - Al importar los pedimentos en facturas por lotes
|
||||
- Fix - Al guardar los datos del emisor
|
||||
|
||||
|
||||
v 1.14.0 [10-sep-2018]
|
||||
----------------------
|
||||
- Personalizar plantilla para factura de pago
|
||||
- Fix - Mostrar serie y folio capturado para factura de pago
|
||||
- Fix - Agregar nueva cuenta de banco
|
||||
|
||||
|
||||
v 1.13.0 [10-sep-2018]
|
||||
----------------------
|
||||
- Cancelar factura de pago
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
|
||||
v 1.12.0 [31-ago-2018]
|
||||
----------------------
|
||||
- Soporte para facturas (complemento) de pago.
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bk
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
v 1.11.1 [21-ago-2018]
|
||||
----------------------
|
||||
- Fix - Quitar columna en tabla facturaspagos.
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
|
||||
v 1.11.0 [25-jul-2018]
|
||||
----------------------
|
||||
- Se cambia la forma de consultar los folios restantes. Es indispensable actualizar a esta versión para ver tus timbres restantes.
|
||||
|
||||
|
||||
v 1.10.0 [10-jul-2018]
|
||||
----------------------
|
||||
- Ahora se pueden manejar precios con cuatro decimales.
|
||||
|
||||
|
||||
v 1.9.3 [08-jul-2018]
|
||||
---------------------
|
||||
- Fix: Al refacturar conceptos con descuento
|
||||
|
||||
|
||||
v 1.9.2 [05-jul-2018]
|
||||
---------------------
|
||||
- Fix: Al generar el reporte de facturas en PDF
|
||||
|
||||
|
||||
v 1.9.1 [25-jun-2018]
|
||||
---------------------
|
||||
- Fix: Al mostrar el título de la aplicación
|
||||
- Se agrega el registro de acción al borrar una factura
|
||||
|
||||
|
||||
v 1.9.0 [18-jun-2018]
|
||||
---------------------
|
||||
- Se agrega la vista del detalle de facturas
|
||||
- Fix: Al timbrar nómina
|
||||
|
||||
|
||||
v 1.8.1 [14-jun-2018]
|
||||
---------------------
|
||||
- Fix: Se agrega una barra de desplazamiento al buscar productos o clientes
|
||||
- Se cambia el servidor de consulta de timbres
|
||||
|
||||
|
||||
v 1.8.0 [03-jun-2018]
|
||||
---------------------
|
||||
- Se permiten 4 decimales en Tipo de cambio
|
||||
- Se agrega el campo {total_cantidades} al generar el PDF
|
||||
- Se agrega opción para generar respaldos de la BD en MV
|
||||
- Fix: Al generar con complemento EDU
|
||||
|
||||
|
||||
v 1.7.0 [23-may-2018]
|
||||
---------------------
|
||||
- Se agrega soporte para truncar impuestos locales, para las estulticias de los "ingenieros" de las dependencias de gobierno
|
||||
|
||||
|
||||
v 1.6.1 [09-abr-2018]
|
||||
---------------------
|
||||
- Fix: Nómina con separación
|
||||
|
||||
|
||||
v 1.6.0 [18-feb-2018]
|
||||
---------------------
|
||||
- Facturacion a extranjeros
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
v 1.5.0 [30-ene-2018]
|
||||
---------------------
|
||||
- Timbrado de Nómina
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
v 1.4.0 [01-ene-2018]
|
||||
---------------------
|
||||
- Impresión de tickets
|
||||
|
||||
v 1.3.0 [27-Dic-2017]
|
||||
---------------------
|
||||
- Punto de venta
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
v 1.2.0 [18-Dic-2017]
|
||||
---------------------
|
||||
* IMPORTANTE: Es necesario actualizar la base de datos, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -bd
|
||||
```
|
||||
|
||||
v 0.1.0 [26-Oct-2017]
|
||||
---------------------
|
||||
- Generar y timbrar con CFDI 3.3
|
||||
|
|
|
@ -13,9 +13,3 @@
|
|||
* Propon nuevas funcionalidades
|
||||
* Difunde Empresa Libre
|
||||
|
||||
|
||||
### Prioridades
|
||||
|
||||
1. Darle continuidad a la facturación de los clientes
|
||||
2. Cubrir todas las funcionalidades que cubre ahora Factura Libre
|
||||
3. Agregar nuevas funcionalidades
|
||||
|
|
39
README.md
|
@ -10,22 +10,51 @@ Este proyecto está en continuo desarrollo, contratar un esquema de soporte,
|
|||
nos ayuda a continuar su desarrollo. Ponte en contacto con nosotros para
|
||||
contratar: administracion ARROBA empresalibre.net
|
||||
|
||||
#### Ahora también puede aportar con criptomonedas:
|
||||
|
||||
### Requerimientos:
|
||||
G1: `A5DdXxCKPw3QKWVdDVs7CzkNugNUW1sHu5zDJFWxCU2h`
|
||||
BCH: `qztd3l00xle5tffdqvh2snvadkuau2ml0uqm4n875d`
|
||||
|
||||
## Requerimientos:
|
||||
|
||||
* Servidor web, recomendado Nginx
|
||||
* uwsgi
|
||||
* python3
|
||||
* python 3.8
|
||||
* xsltproc
|
||||
* openssl
|
||||
* xmlsec
|
||||
|
||||
* Ubuntu 20.04
|
||||
|
||||
```
|
||||
apt install pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl xsltproc
|
||||
```
|
||||
|
||||
Debería de funcionar con cualquier combinación servidor-wsgi que soporte
|
||||
aplicaciones Python.
|
||||
|
||||
El sistema tiene soporte para tres bases de datos: SQLite, MySQL y PostgreSQL
|
||||
(recomendado), debes de instalar el servidor de la base de datos y sus drivers
|
||||
respectivos, excepto SQLite que es nativo en Python.
|
||||
El sistema tiene soporte solo para PostgreSQL, debes de instalar el servidor de
|
||||
la base de datos y su driver respectivo.
|
||||
|
||||
## Configuración para desarrollo local
|
||||
|
||||
* Crea un entorno virtual con python 3.8 y actívalo. Por ejemplo con virtualenv:
|
||||
|
||||
virtualenv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
* Instala las dependencias
|
||||
|
||||
pip install -r requirements.txt
|
||||
|
||||
* Copia y ajusta algunos archivos necesarios.
|
||||
- `source/app/conf.py`
|
||||
- `source/app/controllers/pacs/comerciodigital/conf.py.example`
|
||||
- `source/app/controllers/pacs/finkok/conf.py.example`
|
||||
* Finalmente ejecutamos la aplicación. Para esto vamos a necesitar un servidor
|
||||
wsgi como uwsgi:
|
||||
|
||||
pip install uwsgi
|
||||
cd source/app
|
||||
uwsgi main_debug.ini
|
||||
* Ahora puedes ver la aplicación en http://localhost:8000
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[ ] Permitir más de un remolque en la Carta Porte
|
||||
[ ] Campos de captura de Comercio Exterior
|
||||
[ ] Representación impresa de Comercio Exterior
|
|
@ -1,14 +1,17 @@
|
|||
falcon
|
||||
falcon==1.4.1
|
||||
falcon-multipart
|
||||
Beaker
|
||||
Mako
|
||||
peewee
|
||||
Click
|
||||
peewee==2.10.2
|
||||
logbook
|
||||
bcrypt
|
||||
python-dateutil
|
||||
zeep
|
||||
chardet
|
||||
pyqrcode
|
||||
pypng
|
||||
reportlab
|
||||
psycopg2-binary
|
||||
cryptography==3.4.8
|
||||
xmlsec
|
||||
segno
|
||||
|
||||
# python-escpos
|
||||
|
|
|
@ -2,7 +2,20 @@
|
|||
|
||||
|
||||
DEBUG = False
|
||||
MV = True
|
||||
MV = False
|
||||
|
||||
# ~ Es la contraseña predeterminada de los usuarios admin y superadmin al crear
|
||||
# ~ una nueva base de datos, personaliza por la que quieras.
|
||||
DEFAULT_PASSWORD = 'salgueiro3.3'
|
||||
|
||||
TITLE_APP = 'Empresa Libre'
|
||||
|
||||
#~ Establece una ruta accesible para el servidor web
|
||||
LOG_PATH = '/srv/empresa/logs/empresalibre.log'
|
||||
LOG_PATH = '/var/log/empresalibre/empresa-libre.log'
|
||||
|
||||
# ~ Establece un token personalizado para encriptar las claves
|
||||
# ~ from secrets import token_hex
|
||||
# ~ token_hex(32)
|
||||
# ~ IMPORTANTE: Cada vez que cambies este valor, debes de subir de nuevo
|
||||
# ~ tus certificados
|
||||
TOKEN = ''
|
||||
|
|
|
@ -1,25 +1,47 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
from xml.etree import ElementTree as ET
|
||||
from xml.dom.minidom import parseString
|
||||
|
||||
from dateutil import parser
|
||||
from logbook import Logger
|
||||
|
||||
#~ from settings import DEBUG
|
||||
|
||||
|
||||
log = Logger('XML')
|
||||
CFDI_ACTUAL = 'cfdi33'
|
||||
CFDI_ACTUAL = 'cfdi40'
|
||||
NOMINA_ACTUAL = 'nomina12'
|
||||
PUBLIC = 'PUBLICO EN GENERAL'
|
||||
CFDI_EGRESO = 'E'
|
||||
|
||||
DEFAULT = {
|
||||
'exportacion': '01',
|
||||
}
|
||||
|
||||
|
||||
SAT = {
|
||||
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'cfdi32': {
|
||||
'version': '3.2',
|
||||
'cfdi40': {
|
||||
'version': '4.0',
|
||||
'prefix': 'cfdi',
|
||||
'xmlns': 'http://www.sat.gob.mx/cfd/3',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd',
|
||||
'xmlns': 'http://www.sat.gob.mx/cfd/4',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd',
|
||||
},
|
||||
'cfdi33': {
|
||||
'version': '3.3',
|
||||
|
@ -27,17 +49,23 @@ SAT = {
|
|||
'xmlns': 'http://www.sat.gob.mx/cfd/3',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd',
|
||||
},
|
||||
'cfdi32': {
|
||||
'version': '3.2',
|
||||
'prefix': 'cfdi',
|
||||
'xmlns': 'http://www.sat.gob.mx/cfd/3',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd',
|
||||
},
|
||||
'nomina11': {
|
||||
'version': '1.1',
|
||||
'prefix': 'nomina',
|
||||
'xmlns': 'http://www.sat.gob.mx/nomina',
|
||||
'schema': 'http://www.sat.gob.mx/nomina http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina11.xsd',
|
||||
'schema': ' http://www.sat.gob.mx/nomina http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina11.xsd',
|
||||
},
|
||||
'nomina12': {
|
||||
'nomina': {
|
||||
'version': '1.2',
|
||||
'prefix': 'nomina',
|
||||
'prefix': 'nomina12',
|
||||
'xmlns': 'http://www.sat.gob.mx/nomina12',
|
||||
'schema': 'http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd',
|
||||
'schema': ' http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd',
|
||||
},
|
||||
'locales': {
|
||||
'version': '1.0',
|
||||
|
@ -58,6 +86,42 @@ SAT = {
|
|||
'xmlns': 'http://www.sat.gob.mx/ine',
|
||||
'schema': ' http://www.sat.gob.mx/ine http://www.sat.gob.mx/sitio_internet/cfd/ine/ine11.xsd',
|
||||
},
|
||||
'edu': {
|
||||
'version': '1.0',
|
||||
'prefix': 'iedu',
|
||||
'xmlns': 'http://www.sat.gob.mx/iedu',
|
||||
'schema': ' http://www.sat.gob.mx/iedu http://www.sat.gob.mx/sitio_internet/cfd/iedu/iedu.xsd',
|
||||
},
|
||||
'pagos': {
|
||||
'version': '2.0',
|
||||
'prefix': 'pago20',
|
||||
'xmlns': 'http://www.sat.gob.mx/Pagos20',
|
||||
'schema': ' http://www.sat.gob.mx/Pagos20 http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos20.xsd',
|
||||
},
|
||||
'divisas': {
|
||||
'version': '1.0',
|
||||
'prefix': 'divisas',
|
||||
'xmlns': 'http://www.sat.gob.mx/divisas',
|
||||
'schema': ' http://www.sat.gob.mx/divisas http://www.sat.gob.mx/sitio_internet/cfd/divisas/divisas.xsd',
|
||||
},
|
||||
'leyendas': {
|
||||
'version': '1.0',
|
||||
'prefix': 'leyendasFisc',
|
||||
'xmlns': 'http://www.sat.gob.mx/leyendasFiscales',
|
||||
'schema': ' http://www.sat.gob.mx/leyendasFiscales http://www.sat.gob.mx/sitio_internet/cfd/leyendasFiscales/leyendasFisc.xsd',
|
||||
},
|
||||
'cartaporte': {
|
||||
'version': '3.0',
|
||||
'prefix': 'cartaporte30',
|
||||
'xmlns': 'http://www.sat.gob.mx/CartaPorte30',
|
||||
'schema': ' http://www.sat.gob.mx/CartaPorte30 http://www.sat.gob.mx/sitio_internet/cfd/CartaPorte/CartaPorte30.xsd',
|
||||
},
|
||||
'comercioe': {
|
||||
'version': '2.0',
|
||||
'prefix': 'cce20',
|
||||
'xmlns': 'http://www.sat.gob.mx/ComercioExterior20',
|
||||
'schema': ' http://www.sat.gob.mx/ComercioExterior20 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,6 +136,15 @@ class CFDI(object):
|
|||
self._impuestos_locales = False
|
||||
self._donativo = False
|
||||
self._ine = False
|
||||
self._edu = False
|
||||
self._pagos = False
|
||||
self._is_nomina = False
|
||||
self._leyendas = False
|
||||
self._carta_porte = False
|
||||
self._comercio_exterior = False
|
||||
self._divisas = ''
|
||||
self._tipo_de_comprobante = ''
|
||||
self._exportacion = DEFAULT['exportacion']
|
||||
self.error = ''
|
||||
|
||||
def _now(self):
|
||||
|
@ -82,6 +155,8 @@ class CFDI(object):
|
|||
return ''
|
||||
|
||||
self._comprobante(datos['comprobante'])
|
||||
if 'global' in datos:
|
||||
self._informacion_global(datos['global'])
|
||||
self._relacionados(datos['relacionados'])
|
||||
self._emisor(datos['emisor'])
|
||||
self._receptor(datos['receptor'])
|
||||
|
@ -93,13 +168,14 @@ class CFDI(object):
|
|||
|
||||
if 'nomina' in datos:
|
||||
self._nomina(datos['nomina'])
|
||||
#~ if 'complementos' in datos:
|
||||
#~ self._complementos(datos['complementos'])
|
||||
|
||||
return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8'))
|
||||
xml = self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8'))
|
||||
|
||||
def add_sello(self, sello):
|
||||
return xml
|
||||
|
||||
def add_sello(self, sello, cert_txt):
|
||||
self._cfdi.attrib['Sello'] = sello
|
||||
self._cfdi.attrib['Certificado'] = cert_txt
|
||||
return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8'))
|
||||
|
||||
def _to_pretty_xml(self, source):
|
||||
|
@ -108,35 +184,35 @@ class CFDI(object):
|
|||
return xml
|
||||
|
||||
def _validate(self, datos):
|
||||
if datos['impuestos']['total_locales_trasladados'] or \
|
||||
datos['impuestos']['total_locales_retenciones']:
|
||||
self._impuestos_locales = True
|
||||
if datos['impuestos']:
|
||||
if datos['impuestos']['total_locales_trasladados'] or \
|
||||
datos['impuestos']['total_locales_retenciones']:
|
||||
self._impuestos_locales = True
|
||||
|
||||
if datos['donativo']:
|
||||
self._donativo = True
|
||||
|
||||
if 'ine' in datos['complementos']:
|
||||
self._ine = True
|
||||
self._edu = datos.get('edu', False)
|
||||
|
||||
if datos['complementos']:
|
||||
if 'ine' in datos['complementos']:
|
||||
self._ine = True
|
||||
self._pagos = bool(datos['complementos'].get('pagos', False))
|
||||
self._leyendas = bool(datos['complementos'].get('leyendas', False))
|
||||
self._carta_porte = bool(datos['complementos'].get('cartaporte', False))
|
||||
self._comercio_exterior = bool(datos['complementos'].get('comercioe', False))
|
||||
if self._comercio_exterior:
|
||||
self._exportacion = datos['complementos']['comercioe'].pop('Exportacion')
|
||||
|
||||
self._divisas = datos['comprobante'].pop('divisas', '')
|
||||
|
||||
if 'nomina' in datos:
|
||||
self._is_nomina = True
|
||||
return self._validate_nomina(datos)
|
||||
|
||||
return True
|
||||
|
||||
def _validate_nomina(self, datos):
|
||||
comprobante = datos['comprobante']
|
||||
|
||||
validators = (
|
||||
('MetodoDePago', 'NA'),
|
||||
('TipoCambio', '1'),
|
||||
('Moneda', 'MXN'),
|
||||
('TipoDeComprobante', 'egreso'),
|
||||
)
|
||||
for f, v in validators:
|
||||
if f in comprobante:
|
||||
if v != comprobante[f]:
|
||||
msg = 'El atributo: {}, debe ser: {}'.format(f, v)
|
||||
self.error = msg
|
||||
return False
|
||||
return True
|
||||
|
||||
def _comprobante(self, datos):
|
||||
|
@ -160,10 +236,54 @@ class CFDI(object):
|
|||
if self._ine:
|
||||
name = 'xmlns:{}'.format(SAT['ine']['prefix'])
|
||||
attributes[name] = SAT['ine']['xmlns']
|
||||
schema_donativo = SAT['ine']['schema']
|
||||
schema_ine = SAT['ine']['schema']
|
||||
|
||||
schema_edu = ''
|
||||
if self._edu:
|
||||
name = 'xmlns:{}'.format(SAT['edu']['prefix'])
|
||||
attributes[name] = SAT['edu']['xmlns']
|
||||
schema_edu = SAT['edu']['schema']
|
||||
|
||||
schema_divisas = ''
|
||||
if self._divisas:
|
||||
name = 'xmlns:{}'.format(SAT['divisas']['prefix'])
|
||||
attributes[name] = SAT['divisas']['xmlns']
|
||||
schema_divisas = SAT['divisas']['schema']
|
||||
|
||||
schema_nomina = ''
|
||||
if self._is_nomina:
|
||||
name = 'xmlns:{}'.format(SAT['nomina']['prefix'])
|
||||
attributes[name] = SAT['nomina']['xmlns']
|
||||
schema_nomina = SAT['nomina']['schema']
|
||||
|
||||
schema_pagos = ''
|
||||
if self._pagos:
|
||||
name = 'xmlns:{}'.format(SAT['pagos']['prefix'])
|
||||
attributes[name] = SAT['pagos']['xmlns']
|
||||
schema_pagos = SAT['pagos']['schema']
|
||||
|
||||
schema_leyendas = ''
|
||||
if self._leyendas:
|
||||
name = 'xmlns:{}'.format(SAT['leyendas']['prefix'])
|
||||
attributes[name] = SAT['leyendas']['xmlns']
|
||||
schema_leyendas = SAT['leyendas']['schema']
|
||||
|
||||
schema_carta_porte = ''
|
||||
if self._carta_porte:
|
||||
name = 'xmlns:{}'.format(SAT['cartaporte']['prefix'])
|
||||
attributes[name] = SAT['cartaporte']['xmlns']
|
||||
schema_carta_porte = SAT['cartaporte']['schema']
|
||||
|
||||
schema_comercioe = ''
|
||||
if self._comercio_exterior:
|
||||
name = 'xmlns:{}'.format(SAT['comercioe']['prefix'])
|
||||
attributes[name] = SAT['comercioe']['xmlns']
|
||||
schema_carta_porte = SAT['comercioe']['schema']
|
||||
|
||||
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
|
||||
schema_locales + schema_donativo +schema_ine
|
||||
schema_locales + schema_donativo + schema_ine + schema_edu + \
|
||||
schema_divisas + schema_nomina + schema_pagos + schema_leyendas + \
|
||||
schema_carta_porte + schema_comercioe
|
||||
attributes.update(datos)
|
||||
|
||||
if not 'Version' in attributes:
|
||||
|
@ -171,9 +291,23 @@ class CFDI(object):
|
|||
if not 'Fecha' in attributes:
|
||||
attributes['Fecha'] = self._now()
|
||||
|
||||
# ~ cfdi4
|
||||
if not 'Exportacion' in attributes:
|
||||
attributes['Exportacion'] = self._exportacion
|
||||
|
||||
self._tipo_de_comprobante = attributes['TipoDeComprobante']
|
||||
|
||||
self._cfdi = ET.Element('{}:Comprobante'.format(self._pre), attributes)
|
||||
return
|
||||
|
||||
def _informacion_global(self, datos):
|
||||
if not datos:
|
||||
return
|
||||
|
||||
node_name = '{}:InformacionGlobal'.format(self._pre)
|
||||
node = ET.SubElement(self._cfdi, node_name, datos)
|
||||
return
|
||||
|
||||
def _relacionados(self, datos):
|
||||
if not datos or not datos['tipo'] or not datos['cfdis']:
|
||||
return
|
||||
|
@ -193,16 +327,26 @@ class CFDI(object):
|
|||
return
|
||||
|
||||
def _receptor(self, datos):
|
||||
receptor_name = datos['Nombre'].upper()
|
||||
if receptor_name == PUBLIC and self._tipo_de_comprobante == CFDI_EGRESO:
|
||||
receptor_name = datos['Nombre']
|
||||
datos['Nombre'] = receptor_name
|
||||
node_name = '{}:Receptor'.format(self._pre)
|
||||
emisor = ET.SubElement(self._cfdi, node_name, datos)
|
||||
return
|
||||
|
||||
def _conceptos(self, datos):
|
||||
from xml.sax.saxutils import escape, unescape
|
||||
|
||||
conceptos = ET.SubElement(self._cfdi, '{}:Conceptos'.format(self._pre))
|
||||
# ~ for row in reversed(datos):
|
||||
for row in datos:
|
||||
complemento = {}
|
||||
if 'complemento' in row:
|
||||
complemento = row.pop('complemento')
|
||||
cuenta_predial = row.pop('CuentaPredial', '')
|
||||
pedimento = row.pop('Pedimento', '')
|
||||
student = row.pop('student', '')
|
||||
|
||||
taxes = {}
|
||||
if 'impuestos' in row:
|
||||
|
@ -226,36 +370,26 @@ class CFDI(object):
|
|||
ET.SubElement(
|
||||
retenciones, '{}:Retencion'.format(self._pre), retencion)
|
||||
|
||||
if 'InformacionAduanera' in row:
|
||||
for field in fields:
|
||||
if field in row['InformacionAduanera']:
|
||||
attributes[field] = row['InformacionAduanera'][field]
|
||||
if attributes:
|
||||
node_name = '{}:InformacionAduanera'.format(self._pre)
|
||||
ET.SubElement(concepto, node_name, attributes)
|
||||
if pedimento:
|
||||
attributes = {'NumeroPedimento': pedimento}
|
||||
node_name = '{}:InformacionAduanera'.format(self._pre)
|
||||
ET.SubElement(concepto, node_name, attributes)
|
||||
|
||||
if 'CuentaPredial' in row:
|
||||
attributes = {'numero': row['CuentaPredial']}
|
||||
if cuenta_predial:
|
||||
attributes = {'Numero': cuenta_predial}
|
||||
node_name = '{}:CuentaPredial'.format(self._pre)
|
||||
ET.SubElement(concepto, node_name, attributes)
|
||||
|
||||
if 'autRVOE' in row:
|
||||
fields = (
|
||||
'version',
|
||||
'nombreAlumno',
|
||||
'CURP',
|
||||
'nivelEducativo',
|
||||
'autRVOE',
|
||||
)
|
||||
for field in fields:
|
||||
if field in row['autRVOE']:
|
||||
attributes[field] = row['autRVOE'][field]
|
||||
if student:
|
||||
node_name = '{}:ComplementoConcepto'.format(self._pre)
|
||||
complemento = ET.SubElement(concepto, node_name)
|
||||
ET.SubElement(complemento, 'iedu:instEducativas', attributes)
|
||||
ET.SubElement(complemento, 'iedu:instEducativas', student)
|
||||
return
|
||||
|
||||
def _impuestos(self, datos):
|
||||
if self._is_nomina or not datos:
|
||||
return
|
||||
|
||||
if not datos:
|
||||
node_name = '{}:Impuestos'.format(self._pre)
|
||||
ET.SubElement(self._cfdi, node_name)
|
||||
|
@ -266,6 +400,10 @@ class CFDI(object):
|
|||
for field in fields:
|
||||
if field in datos:
|
||||
attributes[field] = datos[field]
|
||||
|
||||
if not attributes:
|
||||
return
|
||||
|
||||
node_name = '{}:Impuestos'.format(self._pre)
|
||||
impuestos = ET.SubElement(self._cfdi, node_name, attributes)
|
||||
|
||||
|
@ -281,38 +419,62 @@ class CFDI(object):
|
|||
return
|
||||
|
||||
def _nomina(self, datos):
|
||||
sat_nomina = SAT[NOMINA_ACTUAL]
|
||||
pre = sat_nomina['prefix']
|
||||
complemento = ET.SubElement(self._cfdi, '{}:Complemento'.format(self._pre))
|
||||
pre = SAT['nomina']['prefix']
|
||||
|
||||
emisor = datos.pop('Emisor', None)
|
||||
receptor = datos.pop('Receptor', None)
|
||||
percepciones = datos.pop('Percepciones', None)
|
||||
deducciones = datos.pop('Deducciones', None)
|
||||
if self._complemento is None:
|
||||
self._complemento = ET.SubElement(
|
||||
self._cfdi, '{}:Complemento'.format(self._pre))
|
||||
|
||||
attributes = {}
|
||||
attributes['xmlns:{}'.format(pre)] = sat_nomina['xmlns']
|
||||
attributes['xsi:schemaLocation'] = sat_nomina['schema']
|
||||
attributes.update(datos)
|
||||
emisor = datos.pop('emisor', None)
|
||||
receptor = datos.pop('receptor', None)
|
||||
percepciones = datos.pop('percepciones', None)
|
||||
deducciones = datos.pop('deducciones', None)
|
||||
otros_pagos = datos.pop('otros_pagos', ())
|
||||
incapacidades = datos.pop('incapacidades', ())
|
||||
|
||||
if not 'Version' in attributes:
|
||||
attributes['Version'] = sat_nomina['version']
|
||||
nomina = ET.SubElement(
|
||||
self._complemento, '{}:Nomina'.format(pre), datos['nomina'])
|
||||
|
||||
nomina = ET.SubElement(complemento, '{}:Nomina'.format(pre), attributes)
|
||||
if emisor:
|
||||
ET.SubElement(nomina, '{}:Emisor'.format(pre), emisor)
|
||||
|
||||
if receptor:
|
||||
ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor)
|
||||
node = ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor)
|
||||
|
||||
if percepciones:
|
||||
detalle = percepciones.pop('detalle', None)
|
||||
percepciones = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones)
|
||||
for row in detalle:
|
||||
ET.SubElement(percepciones, '{}:Percepcion'.format(pre), row)
|
||||
details = percepciones.pop('details', None)
|
||||
hours_extra = percepciones.pop('hours_extra', None)
|
||||
separacion = percepciones.pop('separacion', None)
|
||||
if details:
|
||||
node = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones)
|
||||
for row in details:
|
||||
nodep = ET.SubElement(node, '{}:Percepcion'.format(pre), row)
|
||||
if row['TipoPercepcion'] == '019' and hours_extra:
|
||||
for he in hours_extra:
|
||||
ET.SubElement(nodep, '{}:HorasExtra'.format(pre), he)
|
||||
hours_extra = None
|
||||
if separacion:
|
||||
ET.SubElement(node, '{}:SeparacionIndemnizacion'.format(pre), separacion)
|
||||
|
||||
if deducciones:
|
||||
detalle = deducciones.pop('detalle', None)
|
||||
deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones)
|
||||
for row in detalle:
|
||||
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row)
|
||||
details = deducciones.pop('details', None)
|
||||
if details:
|
||||
deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones)
|
||||
for row in details:
|
||||
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row)
|
||||
|
||||
if otros_pagos:
|
||||
node = ET.SubElement(nomina, '{}:OtrosPagos'.format(pre))
|
||||
for row in otros_pagos:
|
||||
subsidio = row.pop('subsidio', None)
|
||||
subnode = ET.SubElement(node, '{}:OtroPago'.format(pre), row)
|
||||
if subsidio:
|
||||
ET.SubElement(subnode, '{}:SubsidioAlEmpleo'.format(pre), subsidio)
|
||||
|
||||
if incapacidades:
|
||||
node = ET.SubElement(nomina, '{}:Incapacidades'.format(pre))
|
||||
for row in incapacidades:
|
||||
ET.SubElement(node, '{}:Incapacidad'.format(pre), row)
|
||||
return
|
||||
|
||||
def _locales(self, datos):
|
||||
|
@ -325,7 +487,11 @@ class CFDI(object):
|
|||
|
||||
attributes = {}
|
||||
attributes['version'] = SAT['locales']['version']
|
||||
if not datos['total_locales_trasladados']:
|
||||
datos['total_locales_trasladados'] = '0.00'
|
||||
attributes['TotaldeTraslados'] = datos['total_locales_trasladados']
|
||||
if not datos['total_locales_retenciones']:
|
||||
datos['total_locales_retenciones'] = '0.00'
|
||||
attributes['TotaldeRetenciones'] = datos['total_locales_retenciones']
|
||||
|
||||
node = ET.SubElement(
|
||||
|
@ -354,6 +520,47 @@ class CFDI(object):
|
|||
|
||||
return
|
||||
|
||||
def _complemento_comercio_exterior(self, datos):
|
||||
prefix = SAT['comercioe']['prefix']
|
||||
|
||||
emisor = datos.pop('emisor')
|
||||
propietarios = datos.pop('propietarios', {})
|
||||
receptor = datos.pop('receptor')
|
||||
destinatario = datos.pop('destinatario', {})
|
||||
mercancias = datos.pop('mercancias')
|
||||
|
||||
attr = {'Version': SAT['comercioe']['version']}
|
||||
attr.update(datos)
|
||||
ce = ET.SubElement(
|
||||
self._complemento, f'{prefix}:ComercioExterior', attr)
|
||||
|
||||
attributes = {}
|
||||
if 'Curp' in emisor:
|
||||
attributes = {'Curp': emisor.pop('Curp')}
|
||||
node = ET.SubElement(ce, '{}:Emisor'.format(prefix), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(prefix), emisor)
|
||||
|
||||
attributes = {}
|
||||
if 'NumRegIdTrib' in receptor:
|
||||
attributes = {'NumRegIdTrib': receptor.pop('NumRegIdTrib')}
|
||||
node = ET.SubElement(ce, '{}:Receptor'.format(prefix), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(prefix), receptor)
|
||||
|
||||
node = ET.SubElement(ce, '{}:Mercancias'.format(prefix))
|
||||
fields = ('Marca', 'Modelo', 'SubModelo', 'NumeroSerie')
|
||||
for row in mercancias:
|
||||
detalle = {}
|
||||
for f in fields:
|
||||
if f in row and row[f]:
|
||||
detalle[f] = row[f]
|
||||
row.pop(f)
|
||||
concepto = ET.SubElement(node, '{}:Mercancia'.format(prefix), row)
|
||||
if detalle:
|
||||
ET.SubElement(
|
||||
concepto, '{}:DescripcionesEspecificas'.format(prefix), detalle)
|
||||
|
||||
return
|
||||
|
||||
def _complementos(self, datos):
|
||||
if not datos:
|
||||
return
|
||||
|
@ -362,62 +569,126 @@ class CFDI(object):
|
|||
self._complemento = ET.SubElement(
|
||||
self._cfdi, '{}:Complemento'.format(self._pre))
|
||||
|
||||
if self._carta_porte:
|
||||
datos = datos['cartaporte']
|
||||
ubicaciones = datos.pop('ubicaciones')
|
||||
mercancias = datos.pop('mercancias', ())
|
||||
tiposfigura = datos.pop('tiposfigura', ())
|
||||
|
||||
autotransporte = datos.pop('autotransporte', {})
|
||||
identificacion = autotransporte.pop('identificacion')
|
||||
seguros = autotransporte.pop('seguros')
|
||||
remolques = autotransporte.pop('remolques')
|
||||
|
||||
atributos = {'Version': SAT['cartaporte']['version']}
|
||||
atributos.update(datos)
|
||||
|
||||
prefix = SAT['cartaporte']['prefix']
|
||||
node_carta = ET.SubElement(self._complemento, f'{prefix}:CartaPorte', atributos)
|
||||
|
||||
node = ET.SubElement(node_carta, f'{prefix}:Ubicaciones')
|
||||
for ubicacion in ubicaciones:
|
||||
domicilio = ubicacion.pop('domicilio', {})
|
||||
dt = parser.parse(ubicacion['FechaHoraSalidaLlegada'])
|
||||
ubicacion['FechaHoraSalidaLlegada'] = dt.isoformat()[:19]
|
||||
sub_node = ET.SubElement(node, f'{prefix}:Ubicacion', ubicacion)
|
||||
if domicilio:
|
||||
ET.SubElement(sub_node, f'{prefix}:Domicilio', domicilio)
|
||||
|
||||
attr = mercancias
|
||||
mercancias = attr.pop('mercancias')
|
||||
|
||||
node = ET.SubElement(node_carta, f'{prefix}:Mercancias', attr)
|
||||
for mercancia in mercancias:
|
||||
ET.SubElement(node, f'{prefix}:Mercancia', mercancia)
|
||||
|
||||
sub_node = ET.SubElement(node, f'{prefix}:Autotransporte', autotransporte)
|
||||
ET.SubElement(sub_node, f'{prefix}:IdentificacionVehicular', identificacion)
|
||||
ET.SubElement(sub_node, f'{prefix}:Seguros', seguros)
|
||||
if remolques:
|
||||
node_remolques = ET.SubElement(sub_node, f'{prefix}:Remolques')
|
||||
for remolque in remolques:
|
||||
ET.SubElement(node_remolques, f'{prefix}:Remolque', remolque)
|
||||
|
||||
if tiposfigura:
|
||||
sub_node = ET.SubElement(node_carta, f'{prefix}:FiguraTransporte')
|
||||
for figura in tiposfigura:
|
||||
ET.SubElement(sub_node, f'{prefix}:TiposFigura', figura)
|
||||
|
||||
if self._divisas:
|
||||
atributos = {
|
||||
'version': SAT['divisas']['version'],
|
||||
'tipoOperacion': self._divisas,
|
||||
}
|
||||
ET.SubElement(self._complemento, 'divisas:Divisas', atributos)
|
||||
|
||||
if 'ine' in datos:
|
||||
atributos = {'Version': SAT['ine']['version']}
|
||||
ine_key_entidad = datos['ine'].pop('ClaveEntidad', '')
|
||||
ine_ambito = datos['ine'].pop('Ambito', '')
|
||||
if ine_key_entidad:
|
||||
ine_id_conta = datos['ine'].pop('IdContabilidad', '')
|
||||
atributos.update(datos['ine'])
|
||||
ET.SubElement(self._complemento, 'ine:INE', atributos)
|
||||
node_ine = ET.SubElement(self._complemento, 'ine:INE', atributos)
|
||||
if ine_key_entidad:
|
||||
attr = {'ClaveEntidad': ine_key_entidad}
|
||||
if ine_ambito:
|
||||
attr['Ambito'] = ine_ambito
|
||||
node_entidad = ET.SubElement(node_ine, 'ine:Entidad', attr)
|
||||
attr = {'IdContabilidad': ine_id_conta}
|
||||
ET.SubElement(node_entidad, 'ine:Contabilidad', attr)
|
||||
|
||||
if 'ce' in datos:
|
||||
pre = 'cce11'
|
||||
datos = datos.pop('ce')
|
||||
emisor = datos.pop('emisor')
|
||||
propietario = datos.pop('propietario')
|
||||
receptor = datos.pop('receptor')
|
||||
destinatario = datos.pop('destinatario')
|
||||
conceptos = datos.pop('conceptos')
|
||||
if 'pagos' in datos:
|
||||
datos = datos.pop('pagos')
|
||||
totales = datos.pop('totales')
|
||||
relacionados = datos.pop('relacionados')
|
||||
taxes_pay = datos.pop('taxes_pay')
|
||||
pre = SAT['pagos']['prefix']
|
||||
|
||||
attributes = {}
|
||||
attributes['xmlns:{}'.format(pre)] = \
|
||||
'http://www.sat.gob.mx/ComercioExterior11'
|
||||
attributes['xsi:schemaLocation'] = \
|
||||
'http://www.sat.gob.mx/ComercioExterior11 ' \
|
||||
'http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd'
|
||||
attributes.update(datos)
|
||||
ce = ET.SubElement(
|
||||
complemento, '{}:ComercioExterior'.format(pre), attributes)
|
||||
attributes = {'Version': SAT['pagos']['version']}
|
||||
pagos = ET.SubElement(
|
||||
self._complemento, '{}:Pagos'.format(pre), attributes)
|
||||
|
||||
attributes = {}
|
||||
if 'Curp' in emisor:
|
||||
attributes = {'Curp': emisor.pop('Curp')}
|
||||
node = ET.SubElement(ce, '{}:Emisor'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), emisor)
|
||||
ET.SubElement(pagos, '{}:Totales'.format(pre), totales)
|
||||
|
||||
if propietario:
|
||||
ET.SubElement(ce, '{}:Propietario'.format(pre), propietario)
|
||||
node_pago = ET.SubElement(pagos, '{}:Pago'.format(pre), datos)
|
||||
for row in relacionados:
|
||||
taxes = row.pop('taxes')
|
||||
node = ET.SubElement(node_pago, f'{pre}:DoctoRelacionado', row)
|
||||
nodex_tax = None
|
||||
if taxes['traslados'] or taxes['retenciones']:
|
||||
node_tax = ET.SubElement(node, f'{pre}:ImpuestosDR')
|
||||
if taxes['retenciones']:
|
||||
node = ET.SubElement(node_tax, f'{pre}:RetencionesDR')
|
||||
for tax in taxes['retenciones']:
|
||||
ET.SubElement(node, f'{pre}:RetencionDR', tax)
|
||||
if taxes['traslados']:
|
||||
node = ET.SubElement(node_tax, f'{pre}:TrasladosDR')
|
||||
for tax in taxes['traslados']:
|
||||
ET.SubElement(node, f'{pre}:TrasladoDR', tax)
|
||||
|
||||
attributes = {}
|
||||
if 'NumRegIdTrib' in receptor:
|
||||
attributes = {'NumRegIdTrib': receptor.pop('NumRegIdTrib')}
|
||||
node = ET.SubElement(ce, '{}:Receptor'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), receptor)
|
||||
if taxes_pay['traslados'] or taxes_pay['retenciones']:
|
||||
node_tax = ET.SubElement(node_pago, f'{pre}:ImpuestosP')
|
||||
if taxes_pay['retenciones']:
|
||||
node = ET.SubElement(node_tax, f'{pre}:RetencionesP')
|
||||
for key, importe in taxes_pay['retenciones'].items():
|
||||
attr = {'ImpuestoP': key, 'ImporteP': importe}
|
||||
ET.SubElement(node, f'{pre}:RetencionP', attr)
|
||||
if taxes_pay['traslados']:
|
||||
node = ET.SubElement(node_tax, f'{pre}:TrasladosP')
|
||||
for key, tax in taxes_pay['traslados'].items():
|
||||
ET.SubElement(node, f'{pre}:TrasladoP', tax)
|
||||
|
||||
attributes = {}
|
||||
if 'NumRegIdTrib' in destinatario:
|
||||
attributes = {'NumRegIdTrib': destinatario.pop('NumRegIdTrib')}
|
||||
if 'Nombre' in destinatario:
|
||||
attributes.update({'Nombre': destinatario.pop('Nombre')})
|
||||
node = ET.SubElement(ce, '{}:Destinatario'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), destinatario)
|
||||
if 'leyendas' in datos:
|
||||
pre = SAT['leyendas']['prefix']
|
||||
attributes = {'version': SAT['leyendas']['version']}
|
||||
node_leyend = ET.SubElement(
|
||||
self._complemento, '{}:LeyendasFiscales'.format(pre), attributes)
|
||||
for leyend in datos['leyendas']:
|
||||
ET.SubElement(node_leyend, '{}:Leyenda'.format(pre), leyend)
|
||||
|
||||
if self._comercio_exterior:
|
||||
datos = datos.pop('comercioe')
|
||||
self._complemento_comercio_exterior(datos)
|
||||
|
||||
node = ET.SubElement(ce, '{}:Mercancias'.format(pre))
|
||||
fields = ('Marca', 'Modelo', 'SubModelo', 'NumeroSerie')
|
||||
for row in conceptos:
|
||||
detalle = {}
|
||||
for f in fields:
|
||||
if f in row:
|
||||
detalle[f] = row.pop(f)
|
||||
concepto = ET.SubElement(node, '{}:Mercancia'.format(pre), row)
|
||||
if detalle:
|
||||
ET.SubElement(
|
||||
concepto, '{}:DescripcionesEspecificas'.format(pre), detalle)
|
||||
return
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
|
||||
DEBUG = True
|
||||
|
||||
#~ Ecodex
|
||||
ID_INTEGRADOR = ''
|
||||
|
||||
#~ Finkok
|
||||
FINKOK= {
|
||||
'USER': '',
|
||||
'PASS': '',
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
|
||||
from .conf import DEBUG, ID_INTEGRADOR, FINKOK
|
||||
|
||||
DEBUG = DEBUG
|
||||
TIMEOUT = 10
|
||||
|
||||
#~ PACs que han proporcionado un entorno de pruebas libre y abierto
|
||||
#~ ecodex, finkok
|
||||
PAC = 'finkok'
|
||||
|
||||
|
||||
def ecodex(debug):
|
||||
NEW_SERVER = True
|
||||
auth = {'ID': ID_INTEGRADOR}
|
||||
if debug:
|
||||
#~ No cambies este ID de pruebas
|
||||
auth = {'ID': '2b3a8764-d586-4543-9b7e-82834443f219'}
|
||||
|
||||
base_url = 'https://servicios.ecodex.com.mx:4043/Servicio{}.svc?wsdl'
|
||||
if NEW_SERVER:
|
||||
base_url = 'https://serviciosnominas.ecodex.com.mx:4043/Servicio{}.svc?wsdl'
|
||||
base_api = 'https://api.ecodex.com.mx/{}'
|
||||
if debug:
|
||||
base_url = 'https://wsdev.ecodex.com.mx:2045/Servicio{}.svc?wsdl'
|
||||
base_api = 'https://pruebasapi.ecodex.com.mx/{}'
|
||||
url = {
|
||||
'seguridad': base_url.format('Seguridad'),
|
||||
'clients': base_url.format('Clientes'),
|
||||
'timbra': base_url.format('Timbrado'),
|
||||
'token': base_api.format('token?version=2'),
|
||||
'docs': base_api.format('api/documentos'),
|
||||
'hash': base_api.format('api/Documentos/{}'),
|
||||
'codes': {
|
||||
'HASH': 'DUPLICIDAD EN HASH',
|
||||
}
|
||||
}
|
||||
return auth, url
|
||||
|
||||
|
||||
#~ IMPORTANTE: Si quieres hacer pruebas, con tu propio correo de usuario y
|
||||
#~ contraseña, ponte en contacto con Finkok para que te asignen tus datos de
|
||||
#~ acceso, consulta su documentación para ver las diferentes opciones de acceso.
|
||||
#~ Si solo estas haciendo pruebas de timbrado y ancelación, con estos datos debería
|
||||
#~ ser suficiente.
|
||||
def finkok(debug):
|
||||
USER = FINKOK['USER']
|
||||
PASS = FINKOK['PASS']
|
||||
TOKEN = ''
|
||||
auth = {
|
||||
'USER': '',
|
||||
'PASS': TOKEN or PASS,
|
||||
'RESELLER': {'USER': USER, 'PASS': PASS}
|
||||
}
|
||||
if debug:
|
||||
USER = 'pruebas-finkok@correolibre.net'
|
||||
PASS = ''
|
||||
TOKEN = '5c9a88da105bff9a8c430cb713f6d35269f51674bdc5963c1501b7316366'
|
||||
auth = {
|
||||
'USER': USER,
|
||||
'PASS': TOKEN or PASS,
|
||||
'RESELLER': {
|
||||
'USER': '',
|
||||
'PASS': ''
|
||||
}
|
||||
}
|
||||
|
||||
base_url = 'https://facturacion.finkok.com/servicios/soap/{}.wsdl'
|
||||
if debug:
|
||||
base_url = 'http://demo-facturacion.finkok.com/servicios/soap/{}.wsdl'
|
||||
url = {
|
||||
'timbra': base_url.format('stamp'),
|
||||
'quick_stamp': False,
|
||||
'cancel': base_url.format('cancel'),
|
||||
'client': base_url.format('registration'),
|
||||
'util': base_url.format('utilities'),
|
||||
'codes': {
|
||||
'200': 'Comprobante timbrado satisfactoriamente',
|
||||
'307': 'Comprobante timbrado previamente',
|
||||
'205': 'No Encontrado',
|
||||
}
|
||||
}
|
||||
return auth, url
|
||||
|
||||
|
||||
AUTH, URL = globals()[PAC](DEBUG)
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#~ import falcon
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import smtplib
|
||||
import ssl
|
||||
import collections
|
||||
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
from collections import OrderedDict
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.base import MIMEBase
|
||||
|
@ -12,6 +16,12 @@ from email.mime.text import MIMEText
|
|||
from email import encoders
|
||||
from email.utils import formatdate
|
||||
|
||||
import requests
|
||||
try:
|
||||
from escpos import printer
|
||||
except ImportError:
|
||||
printer = None
|
||||
|
||||
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
|
@ -22,6 +32,9 @@ from reportlab.platypus import Paragraph, Table, TableStyle, Spacer
|
|||
from reportlab.pdfgen import canvas
|
||||
|
||||
|
||||
CANCEL = False
|
||||
|
||||
|
||||
#~ https://github.com/kennethreitz/requests/blob/v1.2.3/requests/structures.py#L37
|
||||
class CaseInsensitiveDict(collections.MutableMapping):
|
||||
"""A case-insensitive ``dict``-like object.
|
||||
|
@ -101,12 +114,20 @@ class NumLet(object):
|
|||
def letras(self):
|
||||
return self._letras.upper()
|
||||
|
||||
#~ def _letters(self, numero, moneda='peso', texto_inicial='-(',
|
||||
#~ texto_final='/100 m.n.)-', fraccion_letras=False, fraccion=''):
|
||||
def _letters(self, numero, moneda='peso'):
|
||||
def _letters(self, numero, currency='MXN'):
|
||||
# ~ print (currency)
|
||||
monedas = {
|
||||
'MXN': 'peso',
|
||||
'USD': 'dólar',
|
||||
'EUR': 'euro',
|
||||
}
|
||||
moneda = monedas.get(currency, currency)
|
||||
tf = {
|
||||
'MXN': 'm.n.',
|
||||
}
|
||||
|
||||
texto_inicial = '-('
|
||||
texto_final = '/100 m.n.)-'
|
||||
texto_final = '/100 {})-'.format(tf.get(currency, currency))
|
||||
fraccion_letras = False
|
||||
fraccion = ''
|
||||
|
||||
|
@ -248,10 +269,18 @@ class SendMail(object):
|
|||
|
||||
def _login(self):
|
||||
try:
|
||||
if self._config['ssl']:
|
||||
if self._config['ssl'] and self._config['starttls']:
|
||||
self._server = smtplib.SMTP(
|
||||
self._config['servidor'],
|
||||
self._config['puerto'], timeout=10)
|
||||
self._server.ehlo()
|
||||
self._server.starttls()
|
||||
self._server.ehlo()
|
||||
elif self._config['ssl']:
|
||||
self._server = smtplib.SMTP_SSL(
|
||||
self._config['servidor'],
|
||||
self._config['puerto'], timeout=10)
|
||||
self._server.ehlo()
|
||||
else:
|
||||
self._server = smtplib.SMTP(
|
||||
self._config['servidor'],
|
||||
|
@ -262,6 +291,7 @@ class SendMail(object):
|
|||
if '535' in str(e):
|
||||
self._error = 'Nombre de usuario o contraseña inválidos'
|
||||
return False
|
||||
# ~ print (e)
|
||||
if '534' in str(e) and 'gmail' in self._config['servidor']:
|
||||
self._error = 'Necesitas activar el acceso a otras ' \
|
||||
'aplicaciones en tu cuenta de GMail'
|
||||
|
@ -282,10 +312,15 @@ class SendMail(object):
|
|||
message['CC'] = options['copia']
|
||||
message['Subject'] = options['asunto']
|
||||
message['Date'] = formatdate(localtime=True)
|
||||
if options['confirmar']:
|
||||
message['Disposition-Notification-To'] = message['From']
|
||||
message.attach(MIMEText(options['mensaje'], 'html'))
|
||||
for f in options['files']:
|
||||
part = MIMEBase('application', 'octet-stream')
|
||||
part.set_payload(f[0])
|
||||
if isinstance(f[0], str):
|
||||
part.set_payload(f[0].encode('utf-8'))
|
||||
else:
|
||||
part.set_payload(f[0])
|
||||
encoders.encode_base64(part)
|
||||
part.add_header(
|
||||
'Content-Disposition',
|
||||
|
@ -309,6 +344,7 @@ class SendMail(object):
|
|||
|
||||
class NumberedCanvas(canvas.Canvas):
|
||||
X = 20.59 * cm
|
||||
XC = 21.6 * cm / 2 + 1.5 * cm
|
||||
Y = 1.5 * cm
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -326,19 +362,33 @@ class NumberedCanvas(canvas.Canvas):
|
|||
for state in self._saved_page_states:
|
||||
self.__dict__.update(state)
|
||||
self.draw_page_number(page_count)
|
||||
self.draw_cancel()
|
||||
canvas.Canvas.showPage(self)
|
||||
canvas.Canvas.save(self)
|
||||
return
|
||||
|
||||
def draw_page_number(self, page_count):
|
||||
self.setFont('Helvetica', 8)
|
||||
self.setFillColor(colors.darkred)
|
||||
text = 'Página {} de {}'.format(self._pageNumber, page_count)
|
||||
# ~ self.setFillColor(colors.darkred)
|
||||
text = f'Página {self._pageNumber} de {page_count}'
|
||||
self.drawRightString(self.X, self.Y, text)
|
||||
text = 'Factura elaborada con software libre: www.empresalibre.net'
|
||||
|
||||
text = 'Este documento es una representación impresa de un CFDI'
|
||||
self.drawCentredString(self.XC, self.Y, text)
|
||||
|
||||
text = 'Factura elaborada con software libre'
|
||||
self.drawString(1.5 * cm, 1.5 * cm, text)
|
||||
return
|
||||
|
||||
def draw_cancel(self):
|
||||
global CANCEL
|
||||
if CANCEL:
|
||||
self.rotate(45)
|
||||
self.setFont('Helvetica', 100)
|
||||
self.setFillColor(colors.red)
|
||||
text = 'Cancelada'
|
||||
self.drawCentredString(20 * cm, 3 * cm, text)
|
||||
return
|
||||
|
||||
class TemplateInvoice(BaseDocTemplate):
|
||||
|
||||
|
@ -387,6 +437,9 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
def _emisor(self, styles, data):
|
||||
logo_path = data.pop('logo', '')
|
||||
logo_style = styles.pop('logo', {})
|
||||
logo_path2 = data.pop('logo2', '')
|
||||
logo_style2 = styles.pop('logo2', {})
|
||||
sucursales = styles.pop('sucursales', {})
|
||||
|
||||
for k, v in styles.items():
|
||||
self._set_text(styles[k], data.get(k, ''))
|
||||
|
@ -397,6 +450,28 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
for k in keys:
|
||||
rect[k] = rect[k] * cm
|
||||
self.canv.drawImage(logo_path, **rect)
|
||||
|
||||
if logo_path2 and logo_style2:
|
||||
rect = logo_style2['rectangulo']
|
||||
keys = ('x', 'y', 'width', 'height')
|
||||
for k in keys:
|
||||
rect[k] = rect[k] * cm
|
||||
self.canv.drawImage(logo_path2, **rect)
|
||||
|
||||
if sucursales:
|
||||
for k, sucursal in sucursales.items():
|
||||
values = sucursal.pop('textos')
|
||||
x = sucursal['rectangulo']['x']
|
||||
y = sucursal['rectangulo']['y']
|
||||
w = sucursal['rectangulo']['width']
|
||||
h = sucursal['rectangulo']['height']
|
||||
for v in values:
|
||||
self._set_text(sucursal, v)
|
||||
y -= h
|
||||
sucursal['rectangulo']['x'] = x
|
||||
sucursal['rectangulo']['y'] = y
|
||||
sucursal['rectangulo']['width'] = w
|
||||
sucursal['rectangulo']['height'] = h
|
||||
return
|
||||
|
||||
def _receptor(self, styles, data):
|
||||
|
@ -418,6 +493,7 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
|
||||
def _comprobante1(self, styles, data):
|
||||
title = styles.pop('titulo', {})
|
||||
self.canv.setTitle(f"Factura {data.get('seriefolio', '')}")
|
||||
|
||||
for k, v in styles.items():
|
||||
self._set_text(styles[k], data.get(k, ''))
|
||||
|
@ -449,6 +525,12 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
fields = ('valorunitario', 'importe')
|
||||
if field in fields:
|
||||
return self._currency(value)
|
||||
|
||||
if field == 'descripcion':
|
||||
html = '<font color="black" size=7>{}</font>'
|
||||
style_bt = getSampleStyleSheet()['BodyText']
|
||||
return Paragraph(html.format(value), style_bt)
|
||||
|
||||
return value
|
||||
|
||||
def _conceptos(self, conceptos):
|
||||
|
@ -484,8 +566,8 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
('GRID', (0, 0), (-1, -1), 0.05 * cm, colors.white),
|
||||
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
|
||||
('FONTSIZE', (0, 0), (-1, -1), 8),
|
||||
('BACKGROUND', (1, 0), (-1, -1), colors.linen),
|
||||
('TEXTCOLOR', (1, 0), (-1, -1), colors.darkred),
|
||||
('BACKGROUND', (1, 0), (-1, -1), colors.lightgrey),
|
||||
('TEXTCOLOR', (1, 0), (-1, -1), colors.black),
|
||||
('FACE', (1, 0), (-1, -1), 'Helvetica-Bold'),
|
||||
]
|
||||
table = Table(rows, colWidths=widths, spaceBefore=0.25*cm)
|
||||
|
@ -493,7 +575,7 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
return table
|
||||
|
||||
def _comprobante2(self, styles, data):
|
||||
leyenda = styles.pop('leyenda', {})
|
||||
leyendas = styles.pop('leyendas', {})
|
||||
|
||||
ls = []
|
||||
for k, v in styles.items():
|
||||
|
@ -501,17 +583,27 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
if 'spaceBefore' in v['estilo']:
|
||||
v['estilo']['spaceBefore'] = v['estilo']['spaceBefore'] * cm
|
||||
ps = ParagraphStyle(**v['estilo'])
|
||||
p = Paragraph(data[k], ps)
|
||||
p = Paragraph(escape(data[k]), ps)
|
||||
ls.append(p)
|
||||
elif k=='formametodopago':
|
||||
ps = ParagraphStyle(**v['estilo'])
|
||||
v = f"{data['formadepago']} - {data['metododepago']}"
|
||||
p = Paragraph(v, ps)
|
||||
ls.append(p)
|
||||
elif k=='monedatipocambio':
|
||||
ps = ParagraphStyle(**v['estilo'])
|
||||
v = f"{data['moneda']} - {data['tipocambio']}"
|
||||
p = Paragraph(v, ps)
|
||||
ls.append(p)
|
||||
|
||||
cbb = Image(data['path_cbb'])
|
||||
cbb = Image(data['cbb'])
|
||||
cbb.drawHeight = 4 * cm
|
||||
cbb.drawWidth = 4 * cm
|
||||
|
||||
style_bt = getSampleStyleSheet()['BodyText']
|
||||
style_bt.leading = 8
|
||||
html_t = '<b><font size=6>{}</font></b>'
|
||||
html = '<font color="darkred" size=5>{}</font>'
|
||||
html = '<font color="black" size=5>{}</font>'
|
||||
msg = 'Cadena original del complemento de certificación digital del SAT'
|
||||
rows = [
|
||||
(cbb, Paragraph(html_t.format('Sello Digital del CFDI'), style_bt)),
|
||||
|
@ -527,13 +619,13 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
('FONTSIZE', (0, 0), (-1, -1), 6),
|
||||
('SPAN', (0, 0), (0, -1)),
|
||||
('FACE', (1, 0), (1, 0), 'Helvetica-Bold'),
|
||||
('BACKGROUND', (1, 1), (1, 1), colors.linen),
|
||||
('BACKGROUND', (1, 1), (1, 1), colors.lightgrey),
|
||||
('TEXTCOLOR', (1, 1), (1, 1), colors.darkred),
|
||||
('FACE', (1, 2), (1, 2), 'Helvetica-Bold'),
|
||||
('BACKGROUND', (1, 3), (1, 3), colors.linen),
|
||||
('BACKGROUND', (1, 3), (1, 3), colors.lightgrey),
|
||||
('TEXTCOLOR', (1, 3), (1, 3), colors.darkred),
|
||||
('FACE', (1, 4), (1, 4), 'Helvetica-Bold'),
|
||||
('BACKGROUND', (1, 5), (1, 5), colors.linen),
|
||||
('BACKGROUND', (1, 5), (1, 5), colors.lightgrey),
|
||||
('TEXTCOLOR', (1, 5), (1, 5), colors.darkred),
|
||||
('ALIGN', (0, 0), (0, 0), 'CENTER'),
|
||||
('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
|
||||
|
@ -542,14 +634,14 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
table.setStyle(TableStyle(table_styles))
|
||||
ls.append(table)
|
||||
|
||||
if leyenda:
|
||||
if 'spaceBefore' in leyenda['estilo']:
|
||||
leyenda['estilo']['spaceBefore'] = \
|
||||
leyenda['estilo']['spaceBefore'] * cm
|
||||
msg = 'Este documento es una representación impresa de un CFDI'
|
||||
ps = ParagraphStyle(**leyenda['estilo'])
|
||||
p = Paragraph(msg, ps)
|
||||
ls.append(p)
|
||||
if leyendas:
|
||||
if 'spaceBefore' in leyendas['estilo']:
|
||||
leyendas['estilo']['spaceBefore'] = \
|
||||
leyendas['estilo']['spaceBefore'] * cm
|
||||
for t in leyendas['textos']:
|
||||
ps = ParagraphStyle(**leyendas['estilo'])
|
||||
p = Paragraph(t, ps)
|
||||
ls.append(p)
|
||||
|
||||
return ls
|
||||
|
||||
|
@ -565,8 +657,10 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
return self._data
|
||||
@data.setter
|
||||
def data(self, values):
|
||||
#~ print (values)
|
||||
global CANCEL
|
||||
# ~ print (values)
|
||||
self._data = values
|
||||
CANCEL = self._data['cancelada']
|
||||
|
||||
rows = self._conceptos(self._data['conceptos'])
|
||||
widths = [2 * cm, 9 * cm, 1.5 * cm, 2 * cm, 2 * cm, 3 * cm]
|
||||
|
@ -576,13 +670,13 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
|
||||
('FACE', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.darkred),
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
||||
('FONTSIZE', (0, 1), (-1, -1), 7),
|
||||
('VALIGN', (0, 1), (-1, -1), 'TOP'),
|
||||
('ALIGN', (0, 1), (0, -1), 'CENTER'),
|
||||
('ALIGN', (2, 1), (2, -1), 'CENTER'),
|
||||
('ALIGN', (3, 1), (5, -1), 'RIGHT'),
|
||||
('LINEBELOW', (0, 1), (-1, -1), 0.05 * cm, colors.darkred),
|
||||
('LINEBELOW', (0, 1), (-1, -1), 0.05 * cm, colors.grey),
|
||||
('LINEBEFORE', (0, 1), (-1, -1), 0.05 * cm, colors.white),
|
||||
]
|
||||
table_conceptos = Table(rows, colWidths=widths, repeatRows=1)
|
||||
|
@ -592,7 +686,7 @@ class TemplateInvoice(BaseDocTemplate):
|
|||
comprobante = self._comprobante2(
|
||||
self._custom_styles['comprobante'], self.data['comprobante'])
|
||||
|
||||
self._rows = [Spacer(0, 6*cm), table_conceptos, totales] + comprobante
|
||||
self._rows = [Spacer(0, 5.7 * cm), table_conceptos, totales] + comprobante
|
||||
|
||||
def render(self):
|
||||
frame = Frame(self.leftMargin, self.bottomMargin,
|
||||
|
@ -724,3 +818,303 @@ class ReportTemplate(BaseDocTemplate):
|
|||
return
|
||||
|
||||
|
||||
class SeaFileAPI(object):
|
||||
FILE_DOES_NOT_EXIST = 441
|
||||
|
||||
def __init__(self, url, username, password):
|
||||
self._url = url
|
||||
self._headers = self._get_auth(username, password)
|
||||
|
||||
@property
|
||||
def is_connect(self):
|
||||
return bool(self._headers)
|
||||
|
||||
def _open(self, path):
|
||||
return open(path, 'rb')
|
||||
|
||||
def _get_auth(self, username, password):
|
||||
url = self._url + 'auth-token/'
|
||||
data = {
|
||||
'username': username,
|
||||
'password': password,
|
||||
}
|
||||
resp = requests.post(url, data=data)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Token Error: {}'.format(resp.status_code)
|
||||
print (msg)
|
||||
return {}
|
||||
|
||||
headers = {'Authorization': 'Token {}'.format(resp.json()['token'])}
|
||||
return headers
|
||||
|
||||
def _get_upload_link(self, repo_id):
|
||||
if not self._headers:
|
||||
return ''
|
||||
|
||||
url = '{}repos/{}/upload-link/'.format(self._url, repo_id)
|
||||
resp = requests.get(url, headers=self._headers)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Error: {}'.format(resp.status_code)
|
||||
print (msg)
|
||||
return ''
|
||||
|
||||
return resp.json()
|
||||
|
||||
def _get_update_link(self, repo_id):
|
||||
if not self._headers:
|
||||
return ''
|
||||
|
||||
url = '{}repos/{}/update-link/'.format(self._url, repo_id)
|
||||
data = {'p': '/'}
|
||||
resp = requests.get(url, data=data, headers=self._headers)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Error: {}'.format(resp.status_code)
|
||||
print (msg)
|
||||
return ''
|
||||
|
||||
return resp.json()
|
||||
|
||||
def _decrypt(self, repo_id, password):
|
||||
if not self._headers:
|
||||
return False
|
||||
|
||||
url = '{}repos/{}/'.format(self._url, repo_id)
|
||||
data = {'password': password}
|
||||
resp = requests.post(url, data=data, headers=self._headers)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Error: {}'.format(resp.status_code)
|
||||
print (msg)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def upload_file(self, path_file, repo_id, relative_path, password=''):
|
||||
if not self._headers:
|
||||
return False
|
||||
|
||||
if password:
|
||||
if not self._decrypt(repo_id, password):
|
||||
return False
|
||||
|
||||
upload_link = self._get_upload_link(repo_id)
|
||||
if isinstance(path_file, tuple):
|
||||
obj_file = path_file[0]
|
||||
filename = path_file[1]
|
||||
else:
|
||||
obj_file = self._open(path_file)
|
||||
_, filename = self._info_path(path_file)
|
||||
|
||||
data = {
|
||||
# ~ 'filename': filename,
|
||||
'parent_dir': relative_path,
|
||||
'relative_path': '',
|
||||
}
|
||||
files = {'file': (filename, obj_file)}
|
||||
|
||||
resp = requests.post(
|
||||
upload_link, data=data, files=files, headers=self._headers)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Upload Code: {}\n{}'.format(resp.status_code, resp.text)
|
||||
print (msg)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _info_path(self, path):
|
||||
path, filename = os.path.split(path)
|
||||
return path, filename
|
||||
|
||||
def list_directory(self, repo_id):
|
||||
if not self._headers:
|
||||
return False
|
||||
|
||||
url = '{}repos/{}/dir/'.format(self._url, repo_id)
|
||||
params = {'p': '/', 't': 'd', 'recursive': '1'}
|
||||
try:
|
||||
resp = requests.get(url, params=params, headers=self._headers)
|
||||
return resp.json()
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
def create_dir(self, repo_id, name):
|
||||
url = '{}repos/{}/dir/'.format(self._url, repo_id)
|
||||
data = {'operation': 'mkdir'}
|
||||
params = {'p': name}
|
||||
resp = requests.post(url, data=data, headers=self._headers, params=params)
|
||||
if resp.status_code != requests.codes.created:
|
||||
msg = 'Create Dir Error: {}'.format(resp.status_code)
|
||||
print (msg)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _validate_directory(self, repo_id, target_file):
|
||||
if target_file == '/':
|
||||
return True
|
||||
|
||||
names = target_file.split('/')[:-1]
|
||||
directories = self.list_directory(repo_id)
|
||||
|
||||
if isinstance(directories, bool):
|
||||
return False
|
||||
|
||||
exists = False
|
||||
parent_dir = '/'
|
||||
name_dir = ''
|
||||
for name in names:
|
||||
name_dir += '/' + name
|
||||
for directory in directories:
|
||||
if name == directory['name'] and parent_dir == directory['parent_dir']:
|
||||
exists = True
|
||||
break
|
||||
if exists:
|
||||
exists = False
|
||||
else:
|
||||
self.create_dir(repo_id, name_dir)
|
||||
if parent_dir == '/':
|
||||
parent_dir += name
|
||||
else:
|
||||
parent_dir += '/' + name
|
||||
|
||||
return True
|
||||
|
||||
def update_file(self, path_file, repo_id, target_file, password, create=True):
|
||||
if not self._headers:
|
||||
return False
|
||||
|
||||
if not self._validate_directory(repo_id, target_file):
|
||||
return False
|
||||
|
||||
if password:
|
||||
if not self._decrypt(repo_id, password):
|
||||
return False
|
||||
|
||||
update_link = self._get_update_link(repo_id)
|
||||
if isinstance(path_file, tuple):
|
||||
obj_file = path_file[0]
|
||||
filename = path_file[1]
|
||||
else:
|
||||
obj_file = self._open(path_file)
|
||||
_, filename = self._info_path(path_file)
|
||||
|
||||
files = {
|
||||
'file': (filename, obj_file),
|
||||
'filename': (None, filename),
|
||||
'target_file': (None, '{}{}'.format(target_file, filename))
|
||||
}
|
||||
|
||||
resp = requests.post(update_link, files=files, headers=self._headers)
|
||||
if resp.status_code != requests.codes.ok:
|
||||
msg = 'Update Code: {}\n{}'.format(resp.status_code, resp.text)
|
||||
print (msg)
|
||||
if resp.status_code == self.FILE_DOES_NOT_EXIST and create:
|
||||
relative_path = '/'
|
||||
if target_file != '/':
|
||||
relative_path += target_file
|
||||
return self.upload_file(path_file, repo_id, relative_path, password)
|
||||
else:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def ping(self):
|
||||
url = self._url + 'ping/'
|
||||
resp = requests.get(url)
|
||||
return resp.json()
|
||||
|
||||
|
||||
def auth_ping(self):
|
||||
url = self._url + 'auth/ping/'
|
||||
resp = requests.get(url, headers=self._headers)
|
||||
return resp.json()
|
||||
|
||||
|
||||
class PrintTicket(object):
|
||||
LINE = '------------------------------------------------\n'
|
||||
TITLES = 'CANT. U ARTICULO P.U. TOTAL\n'
|
||||
LEYENDA = 'GRACIAS POR SU COMPRA\n\nGuarde este ticket para cualquier ' \
|
||||
'aclaración.\nComprobante simplificado de operación con\npúblico en ' \
|
||||
'general de acuerdo al Art. 37\nFracc II inc. v del Reglamento del\n' \
|
||||
'Código Fiscal de la Federación.\n\n'
|
||||
|
||||
def __init__(self, info):
|
||||
self.p = self._init_printer(info)
|
||||
|
||||
def _init_printer(self, info):
|
||||
try:
|
||||
if info['ip']:
|
||||
p = printer.Network(info['ip'])
|
||||
else:
|
||||
p = printer.Usb(*info['usb'])
|
||||
p.codepage = 'cp850'
|
||||
return p
|
||||
except Exception as e:
|
||||
print (e)
|
||||
return
|
||||
|
||||
def _set(self, *data):
|
||||
self.p.set(*data)
|
||||
return
|
||||
|
||||
def _t(self, text):
|
||||
self.p.text(text)
|
||||
return
|
||||
|
||||
def _l(self):
|
||||
self._t(self.LINE)
|
||||
return
|
||||
|
||||
def printer(self, data):
|
||||
if self.p is None:
|
||||
return False
|
||||
|
||||
self._emisor(data['emisor'])
|
||||
self._receptor(data['receptor'])
|
||||
self._ticket(data['ticket'])
|
||||
self._products(data['products'])
|
||||
self._footer(data['ticket'])
|
||||
self.p.cut()
|
||||
return True
|
||||
|
||||
def _emisor(self, data):
|
||||
self._set('center', 'B', 'B', 2, 2)
|
||||
self._t(data['name'])
|
||||
self._set('center', 'B', 'B', 2)
|
||||
self._t(data['rfc'])
|
||||
self._set('center', 'A')
|
||||
self._t(data['regimen'])
|
||||
self._t(data['address'])
|
||||
return
|
||||
|
||||
def _receptor(self, data):
|
||||
self._set('center', 'B', 'B', 2)
|
||||
self._t(data['name'])
|
||||
return
|
||||
|
||||
def _ticket(self, data):
|
||||
self._set('left', 'B', 'B', 2)
|
||||
self._t(data['title'])
|
||||
self._set('left', 'A')
|
||||
self._t(data['date'])
|
||||
return
|
||||
|
||||
def _products(self, data):
|
||||
self._l()
|
||||
self._t(self.TITLES)
|
||||
self._l()
|
||||
for p in data:
|
||||
self._t(p)
|
||||
self._l()
|
||||
self._t('Total artículos: {}\n'.format(len(data)))
|
||||
self._l()
|
||||
return
|
||||
|
||||
def _footer(self, data):
|
||||
self._set('right', 'B', 'B', 2)
|
||||
self._t(data['total'])
|
||||
self._set('center', 'A')
|
||||
self._t(data['letters'])
|
||||
self._t(self.LEYENDA)
|
||||
self._set('center', 'A', 'B')
|
||||
self._t('empresalibre.net')
|
||||
return
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import falcon
|
||||
from middleware import get_template
|
||||
from urllib.parse import unquote
|
||||
|
||||
|
||||
class AppEmpresas(object):
|
||||
|
@ -12,13 +13,25 @@ class AppEmpresas(object):
|
|||
|
||||
@falcon.after(get_template)
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.empresas(values)
|
||||
opt = values.pop('opt', '1')
|
||||
if opt == '1':
|
||||
req.context['result'] = self._db.empresa_agregar(values)
|
||||
elif opt == '2':
|
||||
req.context['result'] = self._db.respaldar_dbs()
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.empresa_borrar(values):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppLogin(object):
|
||||
template = 'login.html'
|
||||
|
@ -32,8 +45,10 @@ class AppLogin(object):
|
|||
|
||||
def on_post(self, req, resp):
|
||||
session = req.env['beaker.session']
|
||||
session.invalidate()
|
||||
values = req.params
|
||||
values['rfc'] = values['rfc'].upper()
|
||||
values['ip'] = req.remote_addr
|
||||
result, user = self._db.authenticate(values)
|
||||
if result['login']:
|
||||
session.save()
|
||||
|
@ -79,21 +94,64 @@ class AppMain(object):
|
|||
|
||||
|
||||
class AppValues(object):
|
||||
TABLES = ('allusuarios', 'usuario', 'usuarioupdate', 'editusuario',
|
||||
'addusuario')
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def _valid_user(self, table, user):
|
||||
if table in self.TABLES:
|
||||
if user.es_admin or user.es_superusuario:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def on_get(self, req, resp, table):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
|
||||
if table == 'product':
|
||||
original = values['name']
|
||||
try:
|
||||
values['name'] = unquote(req.query_string.split('=')[1])
|
||||
except Exception as e:
|
||||
values['name'] = original
|
||||
|
||||
if req.path in ('/values/titlelogin', '/values/empresas'):
|
||||
req.context['result'] = self._db.get_values(table, values, session)
|
||||
resp.status = falcon.HTTP_200
|
||||
return
|
||||
|
||||
if not 'userobj' in session and req.path != '/values/empresas':
|
||||
session.invalidate()
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
if table == 'admin':
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = session['userobj'].es_admin
|
||||
req.context['result'] = session['userobj'].es_superusuario \
|
||||
or session['userobj'].es_admin
|
||||
else:
|
||||
req.context['result'] = self._db.get_values(table, values)
|
||||
if not self._valid_user(table, session['userobj']):
|
||||
resp.status = falcon.HTTP_403
|
||||
return
|
||||
|
||||
req.context['result'] = self._db.get_values(table, values, session)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp, table):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
|
||||
if table == 'usuario' and (session['userobj'].id == int(values['id'])):
|
||||
resp.status = falcon.HTTP_204
|
||||
return
|
||||
|
||||
if not self._valid_user(table, session['userobj']):
|
||||
resp.status = falcon.HTTP_403
|
||||
return
|
||||
|
||||
if self._db.delete(table, values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
|
@ -104,18 +162,33 @@ class AppValues(object):
|
|||
if file_object is None:
|
||||
session = req.env['beaker.session']
|
||||
values = req.params
|
||||
|
||||
if not self._valid_user(table, session['userobj']):
|
||||
resp.status = falcon.HTTP_403
|
||||
return
|
||||
|
||||
if table == 'correo':
|
||||
req.context['result'] = self._db.validate_email(values)
|
||||
elif table == 'sendmail':
|
||||
req.context['result'] = self._db.send_email(values, session)
|
||||
elif table == 'enviarprefac':
|
||||
req.context['result'] = self._db.enviar_prefac(values)
|
||||
elif table == 'addmoneda':
|
||||
req.context['result'] = self._db.add_moneda(values)
|
||||
elif table == 'addunidad':
|
||||
req.context['result'] = self._db.add_unidad(values)
|
||||
elif table == 'addimpuesto':
|
||||
req.context['result'] = self._db.add_impuesto(values)
|
||||
elif table == 'addusuario':
|
||||
req.context['result'] = self._db.add_usuario(values)
|
||||
elif table == 'editusuario':
|
||||
req.context['result'] = self._db.edit_usuario(values)
|
||||
elif table == 'bdfl':
|
||||
req.context['result'] = self._db.importar_bdfl()
|
||||
elif table == 'invoicenotes':
|
||||
req.context['result'] = self._db.save_invoice_notes(values)
|
||||
elif table == 'nivedu':
|
||||
req.context['result'] = self._db.add_nivel_educativo(values)
|
||||
else:
|
||||
req.context['result'] = self._db.validate_cert(values, session)
|
||||
else:
|
||||
|
@ -154,6 +227,12 @@ class AppConfig(object):
|
|||
req.context['result'] = self._db.add_config(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete('config', values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppPartners(object):
|
||||
|
@ -179,6 +258,29 @@ class AppPartners(object):
|
|||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppStudents(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_students(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.students(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete('students', values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppProducts(object):
|
||||
|
||||
def __init__(self, db):
|
||||
|
@ -186,12 +288,17 @@ class AppProducts(object):
|
|||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_products(values)
|
||||
user = req.env['beaker.session']['userobj']
|
||||
|
||||
if 'opt' in values:
|
||||
req.context['result'] = self._db.products_get(values, user)
|
||||
else:
|
||||
req.context['result'] = self._db.get_products(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.product(values)
|
||||
req.context['result'] = self._db.products(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
|
@ -209,17 +316,26 @@ class AppInvoices(object):
|
|||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_invoices(values)
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.get_invoices(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.invoice(values)
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.invoice(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_put(self, req, resp):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.invoice_put(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete('invoice', values['id']):
|
||||
session = req.env['beaker.session']
|
||||
if self._db.delete('invoice', values['id'], session['userobj']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
@ -248,6 +364,24 @@ class AppPreInvoices(object):
|
|||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppTickets(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.get_tickets(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.tickets(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppEmisor(object):
|
||||
|
||||
def __init__(self, db):
|
||||
|
@ -309,7 +443,8 @@ class AppMovimientosBanco(object):
|
|||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.add_movbanco(values)
|
||||
# ~ req.context['result'] = self._db.add_movbanco(values)
|
||||
req.context['result'] = self._db.bankmovement(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
|
@ -343,17 +478,350 @@ class AppFolios(object):
|
|||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppEmployees(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_employees(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.employees(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete('employee', values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppNomina(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
if 'opt' in values:
|
||||
req.context['result'] = self._db.nomina_get(values, user)
|
||||
else:
|
||||
by = values.get('by', '')
|
||||
req.context['result'] = self._db.get_nomina(values)
|
||||
if 'download' in by:
|
||||
name = req.context['result']['name']
|
||||
req.context['blob'] = req.context['result']['data']
|
||||
resp.content_type = 'application/octet-stream'
|
||||
resp.append_header(
|
||||
'Content-Disposition', f'attachment; filename={name}')
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'] = self._db.nomina(values, session['userobj'])
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.delete('nomina', values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppDocumentos(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
#~ self._not_json = True
|
||||
|
||||
def on_get(self, req, resp, type_doc, id_doc):
|
||||
# ~ print('TD', type_doc)
|
||||
session = req.env['beaker.session']
|
||||
req.context['result'], file_name, content_type = \
|
||||
self._db.get_doc(type_doc, id_doc, session['rfc'])
|
||||
resp.append_header('Content-Disposition',
|
||||
'attachment; filename={}'.format(file_name))
|
||||
if not type_doc in ('pdf', 'pre', 'tpdf', 'pdfpago', 'html', 'nompdf'):
|
||||
resp.append_header('Content-Disposition',
|
||||
'attachment; filename={}'.format(file_name))
|
||||
if type_doc in ('pdf', 'nompdf', 'pdfpago'):
|
||||
resp.append_header('Content-Disposition',
|
||||
'inline; filename={}'.format(file_name))
|
||||
resp.content_type = content_type
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
# ~ Revisado
|
||||
class AppInvoicePay(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_invoicepay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppCfdiPay(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_cfdipay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.cfdipay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSATBancos(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_sat_bancos(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sat_bancos(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSATFormaPago(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_sat_forma_pago(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sat_forma_pago(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSATLeyendaFiscales(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sat_leyendas_fiscales_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sat_leyendas_fiscales_post(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_delete(self, req, resp):
|
||||
values = req.params
|
||||
if self._db.sat_leyendas_fiscales_delete(values['id']):
|
||||
resp.status = falcon.HTTP_200
|
||||
else:
|
||||
resp.status = falcon.HTTP_204
|
||||
|
||||
|
||||
class AppSociosCuentasBanco(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_partners_accounts_bank(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.partners_accounts_bank(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppCert(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.cert_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.cert_post(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSucursales(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sucursales_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.sucursales_post(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppPartnerProducts(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.partner_products_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.partner_products_post(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppInventoryEntries(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.inventory_entries_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.inventory_entries_post(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppWareHouse(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.warehouse_get(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.warehouse_post(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppWareHouseProduct(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.warehouseproduct_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.warehouseproduct_post(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppTicketsDetails(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.ticketsdetails_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppUsers(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.users_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.users_post(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSATUnidadesPeso(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.sat_unidades_peso_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.sat_unidades_peso_post(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSATRegimenes(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.sat_regimenes_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppSociosRegimenes(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
user = req.env['beaker.session']['userobj']
|
||||
req.context['result'] = self._db.socios_regimenes_get(values, user)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
|
|
@ -1,697 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#~ import re
|
||||
#~ from xml.etree import ElementTree as ET
|
||||
#~ from requests import Request, Session, exceptions
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
from lxml import etree
|
||||
from xml.dom.minidom import parseString
|
||||
from xml.sax.saxutils import escape, unescape
|
||||
from uuid import UUID
|
||||
|
||||
from logbook import Logger
|
||||
from zeep import Client
|
||||
from zeep.plugins import HistoryPlugin
|
||||
from zeep.cache import SqliteCache
|
||||
from zeep.transports import Transport
|
||||
from zeep.exceptions import Fault, TransportError
|
||||
|
||||
if __name__ == '__main__':
|
||||
from configpac import DEBUG, TIMEOUT, AUTH, URL
|
||||
else:
|
||||
from .configpac import DEBUG, TIMEOUT, AUTH, URL
|
||||
|
||||
|
||||
log = Logger('PAC')
|
||||
#~ node = client.create_message(client.service, SERVICE, **args)
|
||||
#~ print(etree.tostring(node, pretty_print=True).decode())
|
||||
|
||||
|
||||
class Ecodex(object):
|
||||
|
||||
def __init__(self):
|
||||
self.codes = URL['codes']
|
||||
self.error = ''
|
||||
self.message = ''
|
||||
self._transport = Transport(cache=SqliteCache(), timeout=TIMEOUT)
|
||||
self._plugins = None
|
||||
self._history = None
|
||||
if DEBUG:
|
||||
self._history = HistoryPlugin()
|
||||
self._plugins = [self._history]
|
||||
|
||||
def _get_token(self, rfc):
|
||||
client = Client(URL['seguridad'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.ObtenerToken(rfc, self._get_epoch())
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
s = '{}|{}'.format(AUTH['ID'], result.Token)
|
||||
return hashlib.sha1(s.encode()).hexdigest()
|
||||
|
||||
def _get_token_rest(self, rfc):
|
||||
data = {
|
||||
'rfc': rfc,
|
||||
'grant_type': 'authorization_token',
|
||||
}
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
result = requests.post(URL['token'], data=data, headers=headers)
|
||||
data = result.json()
|
||||
s = '{}|{}'.format(AUTH['ID'], data['service_token'])
|
||||
return hashlib.sha1(s.encode()).hexdigest(), data['access_token']
|
||||
|
||||
def _validate_xml(self, xml):
|
||||
NS_CFDI = {'cfdi': 'http://www.sat.gob.mx/cfd/3'}
|
||||
if os.path.isfile(xml):
|
||||
tree = etree.parse(xml).getroot()
|
||||
else:
|
||||
tree = etree.fromstring(xml.encode())
|
||||
|
||||
fecha = tree.get('Fecha')
|
||||
rfc = tree.xpath('string(//cfdi:Emisor/@Rfc)', namespaces=NS_CFDI)
|
||||
data = {
|
||||
'ComprobanteXML': etree.tostring(tree).decode(),
|
||||
'RFC': rfc,
|
||||
'Token': self._get_token(rfc),
|
||||
'TransaccionID': self._get_epoch(fecha),
|
||||
}
|
||||
return data
|
||||
|
||||
def _get_by_hash(self, sh, rfc):
|
||||
token, access_token = self._get_token_rest(rfc)
|
||||
url = URL['hash'].format(sh)
|
||||
headers = {
|
||||
'Authorization': 'Bearer {}'.format(access_token),
|
||||
'X-Auth-Token': token,
|
||||
}
|
||||
result = requests.get(url, headers=headers)
|
||||
if result.status_code == 200:
|
||||
print (result.json())
|
||||
return
|
||||
|
||||
def timbra_xml(self, xml):
|
||||
data = self._validate_xml(xml)
|
||||
client = Client(URL['timbra'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.TimbraXML(**data)
|
||||
except Fault as e:
|
||||
error = str(e)
|
||||
if self.codes['HASH'] in error:
|
||||
sh = error.split(' ')[3]
|
||||
return self._get_by_hash(sh[:40], data['RFC'])
|
||||
self.error = error
|
||||
return ''
|
||||
|
||||
tree = parseString(result.ComprobanteXML.DatosXML)
|
||||
xml = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return xml
|
||||
|
||||
def _get_epoch(self, date=None):
|
||||
if isinstance(date, str):
|
||||
f = '%Y-%m-%dT%H:%M:%S'
|
||||
e = int(time.mktime(time.strptime(date, f)))
|
||||
else:
|
||||
date = datetime.datetime.now()
|
||||
e = int(time.mktime(date.timetuple()))
|
||||
return e
|
||||
|
||||
def estatus_cuenta(self, rfc):
|
||||
#~ Codigos:
|
||||
#~ 100 = Cuenta encontrada
|
||||
#~ 101 = RFC no dado de alta en el sistema ECODEX
|
||||
token = self._get_token(rfc)
|
||||
if not token:
|
||||
return {}
|
||||
|
||||
data = {
|
||||
'RFC': rfc,
|
||||
'Token': token,
|
||||
'TransaccionID': self._get_epoch()
|
||||
}
|
||||
client = Client(URL['clients'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.EstatusCuenta(**data)
|
||||
except Fault as e:
|
||||
log.error(str(e))
|
||||
return
|
||||
#~ print (result)
|
||||
return result.Estatus
|
||||
|
||||
|
||||
class Finkok(object):
|
||||
|
||||
def __init__(self, auth={}):
|
||||
self.codes = URL['codes']
|
||||
self.error = ''
|
||||
self.message = ''
|
||||
self._transport = Transport(cache=SqliteCache(), timeout=TIMEOUT)
|
||||
self._plugins = None
|
||||
self._history = None
|
||||
self.uuid = ''
|
||||
self.fecha = None
|
||||
if DEBUG:
|
||||
self._history = HistoryPlugin()
|
||||
self._plugins = [self._history]
|
||||
self._auth = AUTH
|
||||
else:
|
||||
self._auth = auth
|
||||
|
||||
def _debug(self):
|
||||
if not DEBUG:
|
||||
return
|
||||
print('SEND', self._history.last_sent)
|
||||
print('RESULT', self._history.last_received)
|
||||
return
|
||||
|
||||
def _check_result(self, method, result):
|
||||
#~ print ('CODE', result.CodEstatus)
|
||||
#~ print ('INCIDENCIAS', result.Incidencias)
|
||||
self.message = ''
|
||||
MSG = {
|
||||
'OK': 'Comprobante timbrado satisfactoriamente',
|
||||
'307': 'Comprobante timbrado previamente',
|
||||
}
|
||||
status = result.CodEstatus
|
||||
if status is None and result.Incidencias:
|
||||
for i in result.Incidencias['Incidencia']:
|
||||
self.error += 'Error: {}\n{}'.format(
|
||||
i['CodigoError'], i['MensajeIncidencia'])
|
||||
return ''
|
||||
|
||||
if method == 'timbra' and status in (MSG['OK'], MSG['307']):
|
||||
#~ print ('UUID', result.UUID)
|
||||
#~ print ('FECHA', result.Fecha)
|
||||
if status == MSG['307']:
|
||||
self.message = MSG['307']
|
||||
tree = parseString(result.xml)
|
||||
response = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
self.uuid = result.UUID
|
||||
self.fecha = result.Fecha
|
||||
|
||||
return response
|
||||
|
||||
def _load_file(self, path):
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
except Exception as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
return data
|
||||
|
||||
def _validate_xml(self, file_xml):
|
||||
if os.path.isfile(file_xml):
|
||||
try:
|
||||
with open(file_xml, 'rb') as f:
|
||||
xml = f.read()
|
||||
except Exception as e:
|
||||
self.error = str(e)
|
||||
return False, ''
|
||||
else:
|
||||
xml = file_xml.encode('utf-8')
|
||||
return True, xml
|
||||
|
||||
def _validate_uuid(self, uuid):
|
||||
try:
|
||||
UUID(uuid)
|
||||
return True
|
||||
except ValueError:
|
||||
self.error = 'UUID no válido: {}'.format(uuid)
|
||||
return False
|
||||
|
||||
def timbra_xml(self, file_xml):
|
||||
self.error = ''
|
||||
|
||||
if not DEBUG and not self._auth:
|
||||
self.error = 'Sin datos para timbrar'
|
||||
return
|
||||
|
||||
method = 'timbra'
|
||||
ok, xml = self._validate_xml(file_xml)
|
||||
if not ok:
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'xml': xml,
|
||||
}
|
||||
if URL['quick_stamp']:
|
||||
try:
|
||||
result = client.service.quick_stamp(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
else:
|
||||
try:
|
||||
result = client.service.stamp(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
|
||||
return self._check_result(method, result)
|
||||
|
||||
def _get_xml(self, uuid):
|
||||
if not self._validate_uuid(uuid):
|
||||
return ''
|
||||
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'uuid': uuid,
|
||||
'taxpayer_id': self.rfc,
|
||||
'invoice_type': 'I',
|
||||
}
|
||||
try:
|
||||
result = client.service.get_xml(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
except TransportError as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.error:
|
||||
self.error = result.error
|
||||
return ''
|
||||
|
||||
tree = parseString(result.xml)
|
||||
xml = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return xml
|
||||
|
||||
def recupera_xml(self, file_xml='', uuid=''):
|
||||
self.error = ''
|
||||
if uuid:
|
||||
return self._get_xml(uuid)
|
||||
|
||||
method = 'timbra'
|
||||
ok, xml = self._validate_xml(file_xml)
|
||||
if not ok:
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.stamped(
|
||||
xml, self._auth['user'], self._auth['pass'])
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return self._check_result(method, result)
|
||||
|
||||
def estatus_xml(self, uuid):
|
||||
method = 'timbra'
|
||||
if not self._validate_uuid(uuid):
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.query_pending(
|
||||
self._auth['USER'], self._auth['PASS'], uuid)
|
||||
#~ print (result.date)
|
||||
#~ tree = parseString(unescape(result.xml))
|
||||
#~ response = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return result.status
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
def cancel_xml(self, rfc, uuids, path_cer, path_key):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
cer = self._load_file(path_cer)
|
||||
key = self._load_file(path_key)
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
uuid_type = client.get_type('ns1:UUIDS')
|
||||
sa = client.get_type('ns0:stringArray')
|
||||
|
||||
args = {
|
||||
'UUIDS': uuid_type(uuids=sa(string=uuids)),
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'cer': cer,
|
||||
'key': key,
|
||||
'store_pending': True,
|
||||
}
|
||||
try:
|
||||
result = client.service.cancel(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.CodEstatus and self.codes['205'] in result.CodEstatus:
|
||||
self.error = result.CodEstatus
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def cancel_signature(self, file_xml):
|
||||
method = 'cancel'
|
||||
if os.path.isfile(file_xml):
|
||||
root = etree.parse(file_xml).getroot()
|
||||
else:
|
||||
root = etree.fromstring(file_xml.encode())
|
||||
|
||||
xml = etree.tostring(root)
|
||||
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'xml': xml,
|
||||
'store_pending': True,
|
||||
}
|
||||
|
||||
try:
|
||||
result = client.service.cancel_signature(**args)
|
||||
return result
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
def get_acuse(self, rfc, uuids, type_acuse='C'):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'uuid': '',
|
||||
'type': type_acuse,
|
||||
}
|
||||
try:
|
||||
result = []
|
||||
for u in uuids:
|
||||
args['uuid'] = u
|
||||
r = client.service.get_receipt(**args)
|
||||
result.append(r)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def estatus_cancel(self, uuids):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': self._auth['USER'],
|
||||
'password': self._auth['PASS'],
|
||||
'uuid': '',
|
||||
}
|
||||
try:
|
||||
result = []
|
||||
for u in uuids:
|
||||
args['uuid'] = u
|
||||
r = client.service.query_pending_cancellation(**args)
|
||||
result.append(r)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def add_token(self, rfc, email):
|
||||
"""Agrega un nuevo token al cliente para timbrado.
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del cliente, ya debe existir
|
||||
email (str): El correo del cliente, funciona como USER al timbrar
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'username': 'username',
|
||||
'status': True or False
|
||||
'name': 'name',
|
||||
'success': True or False
|
||||
'token': 'Token de timbrado',
|
||||
'message': None
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': auth['USER'],
|
||||
'password': auth['PASS'],
|
||||
'name': rfc,
|
||||
'token_username': email,
|
||||
'taxpayer_id': rfc,
|
||||
'status': True,
|
||||
}
|
||||
try:
|
||||
result = client.service.add_token(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def get_date(self):
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.datetime(AUTH['USER'], AUTH['PASS'])
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.error:
|
||||
self.error = result.error
|
||||
return
|
||||
|
||||
return result.datetime
|
||||
|
||||
def add_client(self, rfc, type_user=False):
|
||||
"""Agrega un nuevo cliente para timbrado.
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del nuevo cliente
|
||||
|
||||
Kwargs:
|
||||
type_user (bool): False == 'P' == Prepago or True == 'O' == On demand
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'message':
|
||||
'Account Created successfully'
|
||||
'Account Already exists'
|
||||
'success': True or False
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
tu = {False: 'P', True: 'O'}
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': auth['USER'],
|
||||
'reseller_password': auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'type_user': tu[type_user],
|
||||
'added': datetime.datetime.now().isoformat()[:19],
|
||||
}
|
||||
try:
|
||||
result = client.service.add(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def edit_client(self, rfc, status=True):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
status = 'A' or 'S'
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
sv = {False: 'S', True: 'A'}
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': auth['USER'],
|
||||
'reseller_password': auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'status': sv[status],
|
||||
}
|
||||
try:
|
||||
result = client.service.edit(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def get_client(self, rfc):
|
||||
"""Regresa el estatus del cliente
|
||||
.
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del emisor
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'message': None,
|
||||
'users': {
|
||||
'ResellerUser': [
|
||||
{
|
||||
'status': 'A',
|
||||
'counter': 0,
|
||||
'taxpayer_id': '',
|
||||
'credit': 0
|
||||
}
|
||||
]
|
||||
} or None si no existe
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': auth['USER'],
|
||||
'reseller_password': auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
}
|
||||
|
||||
try:
|
||||
result = client.service.get(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
except TransportError as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def assign_client(self, rfc, credit):
|
||||
"""Agregar credito a un emisor
|
||||
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del emisor, debe existir
|
||||
credit (int): Cantidad de folios a agregar
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'success': True or False,
|
||||
'credit': nuevo credito despues de agregar or None
|
||||
'message':
|
||||
'Success, added {credit} of credit to {RFC}'
|
||||
'RFC no encontrado'
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': auth['USER'],
|
||||
'password': auth['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'credit': credit,
|
||||
}
|
||||
try:
|
||||
result = client.service.assign(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _get_data_sat(path):
|
||||
BF = 'string(//*[local-name()="{}"]/@{})'
|
||||
NS_CFDI = {'cfdi': 'http://www.sat.gob.mx/cfd/3'}
|
||||
|
||||
try:
|
||||
if os.path.isfile(path):
|
||||
tree = etree.parse(path).getroot()
|
||||
else:
|
||||
tree = etree.fromstring(path.encode())
|
||||
|
||||
data = {}
|
||||
emisor = escape(
|
||||
tree.xpath('string(//cfdi:Emisor/@rfc)', namespaces=NS_CFDI) or
|
||||
tree.xpath('string(//cfdi:Emisor/@Rfc)', namespaces=NS_CFDI)
|
||||
)
|
||||
receptor = escape(
|
||||
tree.xpath('string(//cfdi:Receptor/@rfc)', namespaces=NS_CFDI) or
|
||||
tree.xpath('string(//cfdi:Receptor/@Rfc)', namespaces=NS_CFDI)
|
||||
)
|
||||
data['total'] = tree.get('total') or tree.get('Total')
|
||||
data['emisor'] = emisor
|
||||
data['receptor'] = receptor
|
||||
data['uuid'] = tree.xpath(BF.format('TimbreFiscalDigital', 'UUID'))
|
||||
except Exception as e:
|
||||
print (e)
|
||||
return {}
|
||||
|
||||
return '?re={emisor}&rr={receptor}&tt={total}&id={uuid}'.format(**data)
|
||||
|
||||
|
||||
def get_status_sat(xml):
|
||||
data = _get_data_sat(xml)
|
||||
if not data:
|
||||
return 'XML inválido'
|
||||
|
||||
URL = 'https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc?wsdl'
|
||||
client = Client(URL, transport=Transport(cache=SqliteCache()))
|
||||
try:
|
||||
result = client.service.Consulta(expresionImpresa=data)
|
||||
except Exception as e:
|
||||
return 'Error: {}'.format(str(e))
|
||||
|
||||
return result.Estado
|
||||
|
||||
|
||||
def main():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from .comerciodigital import PACComercioDigital
|
||||
from .finkok import PACFinkok
|
|
@ -0,0 +1,350 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import datetime
|
||||
import getpass
|
||||
import hashlib
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import lxml.etree as ET
|
||||
import xmlsec
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.x509.oid import ExtensionOID
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
|
||||
from conf import TOKEN
|
||||
|
||||
|
||||
class SATCertificate(object):
|
||||
|
||||
def __init__(self, cer=b'', key=b'', password=''):
|
||||
self._error = ''
|
||||
self._init_values()
|
||||
self._get_data_cer(cer)
|
||||
self._get_data_key(key, password)
|
||||
# ~ if not password:
|
||||
# ~ self._test()
|
||||
|
||||
# ~ def _test(self):
|
||||
# ~ key = self._get_key('')
|
||||
# ~ self._p = ''
|
||||
# ~ self._key_der = key.private_bytes(
|
||||
# ~ encoding=serialization.Encoding.DER,
|
||||
# ~ format=serialization.PrivateFormat.PKCS8,
|
||||
# ~ encryption_algorithm=serialization.BestAvailableEncryption(self._p.encode())
|
||||
# ~ )
|
||||
# ~ return
|
||||
|
||||
def _init_values(self):
|
||||
self._rfc = ''
|
||||
self._serial_number = ''
|
||||
self._serial_number2 = ''
|
||||
self._subject = ''
|
||||
self._issuer = ''
|
||||
self._not_before = None
|
||||
self._not_after = None
|
||||
self._is_fiel = False
|
||||
self._are_couple = False
|
||||
self._is_valid_time = False
|
||||
self._key = b''
|
||||
self._cer = b''
|
||||
self._cer_pem = ''
|
||||
self._cer_txt = ''
|
||||
self._key_enc = b''
|
||||
self._key_der = b''
|
||||
self._p12 = b''
|
||||
self._cer_modulus = 0
|
||||
self._key_modulus = 0
|
||||
return
|
||||
|
||||
def __str__(self):
|
||||
msg = '\tRFC: {}\n'.format(self.rfc)
|
||||
msg += '\tNo de Serie: {}\n'.format(self.serial_number)
|
||||
msg += '\tVálido desde: {}\n'.format(self.not_before)
|
||||
msg += '\tVálido hasta: {}\n'.format(self.not_after)
|
||||
msg += '\tEs vigente: {}\n'.format(self.is_valid_time)
|
||||
msg += '\tSon pareja: {}\n'.format(self.are_couple)
|
||||
msg += '\tEs FIEL: {}\n'.format(self.is_fiel)
|
||||
return msg
|
||||
|
||||
def __bool__(self):
|
||||
return self.is_valid
|
||||
|
||||
def _get_hash(self):
|
||||
digest = hashes.Hash(hashes.SHA512(), default_backend())
|
||||
digest.update(self._rfc.encode())
|
||||
digest.update(self._serial_number.encode())
|
||||
digest.update(TOKEN.encode())
|
||||
return digest.finalize()
|
||||
|
||||
def _get_data_cer(self, cer):
|
||||
self._cer = cer
|
||||
obj = x509.load_der_x509_certificate(cer, default_backend())
|
||||
|
||||
self._issuer = obj.issuer.rfc4514_string()
|
||||
self._subject = obj.subject.rfc4514_string()
|
||||
|
||||
self._rfc = obj.subject.get_attributes_for_oid(
|
||||
NameOID.X500_UNIQUE_IDENTIFIER)[0].value.split(' ')[0]
|
||||
self._serial_number2 = '{0:x}'.format(obj.serial_number)
|
||||
self._serial_number = self._serial_number2[1::2]
|
||||
self._not_before = obj.not_valid_before
|
||||
self._not_after = obj.not_valid_after
|
||||
now = datetime.datetime.utcnow()
|
||||
self._is_valid_time = (now > self.not_before) and (now < self.not_after)
|
||||
if not self._is_valid_time:
|
||||
msg = 'El certificado no es vigente'
|
||||
self._error = msg
|
||||
|
||||
self._is_fiel = obj.extensions.get_extension_for_oid(
|
||||
ExtensionOID.KEY_USAGE).value.key_agreement
|
||||
|
||||
self._cer_pem = obj.public_bytes(serialization.Encoding.PEM).decode()
|
||||
self._cer_txt = ''.join(self._cer_pem.split('\n')[1:-2])
|
||||
self._cer_modulus = obj.public_key().public_numbers().n
|
||||
return
|
||||
|
||||
def _get_data_key(self, key, password):
|
||||
self._key = key
|
||||
self._keyp = password
|
||||
self._key_enc = key
|
||||
if not key or not password:
|
||||
return
|
||||
|
||||
try:
|
||||
obj = serialization.load_der_private_key(
|
||||
key, password.encode(), default_backend())
|
||||
except ValueError:
|
||||
msg = 'La contraseña es incorrecta'
|
||||
self._error = msg
|
||||
return
|
||||
|
||||
p = self._get_hash()
|
||||
self._key_enc = obj.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.BestAvailableEncryption(p)
|
||||
)
|
||||
|
||||
self._key_modulus = obj.public_key().public_numbers().n
|
||||
self._are_couple = self._cer_modulus == self._key_modulus
|
||||
if not self._are_couple:
|
||||
msg = 'El CER y el KEY no son pareja'
|
||||
self._error = msg
|
||||
return
|
||||
|
||||
def _get_key(self, password):
|
||||
if not password:
|
||||
password = self._get_hash()
|
||||
private_key = serialization.load_pem_private_key(
|
||||
self._key_enc, password=password, backend=default_backend())
|
||||
return private_key
|
||||
|
||||
def _get_key_pem(self):
|
||||
obj = self._get_key('')
|
||||
key_pem = obj.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
)
|
||||
return key_pem
|
||||
|
||||
# Not work
|
||||
def _get_p12(self):
|
||||
obj = serialization.pkcs12.serialize_key_and_certificates('test',
|
||||
self.key_pem, self.cer_pem, None,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
)
|
||||
return obj
|
||||
|
||||
def sign(self, data, password=''):
|
||||
private_key = self._get_key(password)
|
||||
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
|
||||
return base64.b64encode(firma).decode()
|
||||
|
||||
def sign_xml(self, tree):
|
||||
node = xmlsec.tree.find_node(tree, xmlsec.constants.NodeSignature)
|
||||
ctx = xmlsec.SignatureContext()
|
||||
key = xmlsec.Key.from_memory(
|
||||
self.key_pem, xmlsec.constants.KeyDataFormatPem)
|
||||
ctx.key = key
|
||||
ctx.sign(node)
|
||||
|
||||
node = xmlsec.tree.find_node(tree, 'X509Certificate')
|
||||
node.text = self.cer_txt
|
||||
node = xmlsec.tree.find_node(tree, 'X509IssuerName')
|
||||
node.text = self.issuer
|
||||
node = xmlsec.tree.find_node(tree, 'X509SerialNumber')
|
||||
node.text = self.serial_number
|
||||
node = xmlsec.tree.find_node(tree, 'SignatureValue')
|
||||
node.text = node.text.replace('\n', '')
|
||||
node = xmlsec.tree.find_node(tree, 'Modulus')
|
||||
node.text = node.text.replace('\n', '')
|
||||
|
||||
# ~ xml_signed = ET.tostring(tree,
|
||||
# ~ xml_declaration=True, encoding='UTF-8').decode()
|
||||
xml_signed = ET.tostring(tree, encoding='UTF-8').decode().replace('\n', '')
|
||||
|
||||
return xml_signed
|
||||
|
||||
@property
|
||||
def rfc(self):
|
||||
return self._rfc
|
||||
|
||||
@property
|
||||
def serial_number(self):
|
||||
return self._serial_number
|
||||
|
||||
@property
|
||||
def serial_number2(self):
|
||||
return self._serial_number2
|
||||
|
||||
@property
|
||||
def issuer(self):
|
||||
return self._issuer
|
||||
|
||||
@property
|
||||
def subject(self):
|
||||
return self._subject
|
||||
|
||||
@property
|
||||
def not_before(self):
|
||||
return self._not_before
|
||||
|
||||
@property
|
||||
def not_after(self):
|
||||
return self._not_after
|
||||
|
||||
@property
|
||||
def is_fiel(self):
|
||||
return self._is_fiel
|
||||
|
||||
@property
|
||||
def are_couple(self):
|
||||
return self._are_couple
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
return not bool(self.error)
|
||||
|
||||
@property
|
||||
def is_valid_time(self):
|
||||
return self._is_valid_time
|
||||
|
||||
@property
|
||||
def cer(self):
|
||||
return self._cer
|
||||
|
||||
@property
|
||||
def cer_pem(self):
|
||||
return self._cer_pem.encode()
|
||||
|
||||
@property
|
||||
def cer_txt(self):
|
||||
return self._cer_txt
|
||||
|
||||
@property
|
||||
def key_pem(self):
|
||||
return self._get_key_pem()
|
||||
|
||||
@property
|
||||
def key_enc(self):
|
||||
return self._key_enc
|
||||
|
||||
@property
|
||||
def p12(self):
|
||||
return self._get_p12()
|
||||
|
||||
@property
|
||||
def error(self):
|
||||
return self._error
|
||||
|
||||
@classmethod
|
||||
def save_cert(cls, obj):
|
||||
import hashlib
|
||||
|
||||
cer = x509.load_pem_x509_certificate(obj.cer_pem.encode(), default_backend())
|
||||
cer_der = cer.public_bytes(serialization.Encoding.DER)
|
||||
token = hashlib.md5(obj.rfc.encode()).hexdigest()
|
||||
path = Path(f'/tmp/{obj.rfc}.key')
|
||||
path.write_text(obj.key_enc)
|
||||
args = f'openssl rsa -inform PEM -outform PEM -in "{str(path)}" -passin pass:{token}'
|
||||
pem = subprocess.check_output(args, shell=True).decode()
|
||||
key = serialization.load_pem_private_key(
|
||||
pem.encode(), password=None, backend=default_backend())
|
||||
|
||||
digest = hashes.Hash(hashes.SHA512(), default_backend())
|
||||
digest.update(obj.rfc.encode())
|
||||
digest.update(obj.serie.encode())
|
||||
digest.update(TOKEN.encode())
|
||||
p = digest.finalize()
|
||||
|
||||
key_enc = key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.BestAvailableEncryption(p)
|
||||
)
|
||||
|
||||
cert = SATCertificate(cer_der, key_enc)
|
||||
obj.key_enc = cert.key_enc
|
||||
obj.cer = cert.cer
|
||||
obj.serie = cert.serial_number
|
||||
obj.desde = cert.not_before
|
||||
obj.hasta = cert.not_after
|
||||
obj.save()
|
||||
return
|
||||
|
||||
|
||||
def main(args):
|
||||
# ~ contra = getpass.getpass('Introduce la contraseña del archivo KEY: ')
|
||||
contra = '12345678a'
|
||||
if not contra.strip():
|
||||
msg = 'La contraseña es requerida'
|
||||
print(msg)
|
||||
return
|
||||
|
||||
path_cer = Path(args.cer)
|
||||
path_key = Path(args.key)
|
||||
|
||||
if not path_cer.is_file():
|
||||
msg = 'El archivo CER es necesario'
|
||||
print(msg)
|
||||
return
|
||||
|
||||
if not path_key.is_file():
|
||||
msg = 'El archivo KEY es necesario'
|
||||
print(msg)
|
||||
return
|
||||
|
||||
cer = path_cer.read_bytes()
|
||||
key = path_key.read_bytes()
|
||||
cert = SATCertificate(cer, key, contra)
|
||||
|
||||
if cert.error:
|
||||
print(cert.error)
|
||||
else:
|
||||
print(cert)
|
||||
return
|
||||
|
||||
|
||||
def _process_command_line_arguments():
|
||||
parser = argparse.ArgumentParser(description='CFDI Certificados')
|
||||
|
||||
help = 'Archivo CER'
|
||||
parser.add_argument('-c', '--cer', help=help, default='')
|
||||
help = 'Archivo KEY'
|
||||
parser.add_argument('-k', '--key', help=help, default='')
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = _process_command_line_arguments()
|
||||
main(args)
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from .comercio import PACComercioDigital
|
|
@ -0,0 +1,431 @@
|
|||
#!/usr/bin/env python
|
||||
# ~
|
||||
# ~ PAC
|
||||
# ~ Copyright (C) 2018-2019 Mauricio Baeza Servin - public [AT] elmau [DOT] net
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import base64
|
||||
import logging
|
||||
|
||||
import lxml.etree as ET
|
||||
import requests
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
from .conf import DEBUG
|
||||
# ~ , AUTH
|
||||
|
||||
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_DATE = '%d/%m/%Y %H:%M:%S'
|
||||
logging.addLevelName(logging.ERROR, '\033[1;41mERROR\033[1;0m')
|
||||
logging.addLevelName(logging.DEBUG, '\x1b[33mDEBUG\033[1;0m')
|
||||
logging.addLevelName(logging.INFO, '\x1b[32mINFO\033[1;0m')
|
||||
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
logging.getLogger('requests').setLevel(logging.ERROR)
|
||||
|
||||
|
||||
TIMEOUT = 10
|
||||
|
||||
NAMESPACES = {
|
||||
'3.3': 'http://www.sat.gob.mx/cfd/3',
|
||||
'4.0': 'http://www.sat.gob.mx/cfd/4',
|
||||
'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
}
|
||||
|
||||
|
||||
def pretty_print_POST(req):
|
||||
"""
|
||||
At this point it is completely built and ready
|
||||
to be fired; it is "prepared".
|
||||
|
||||
However pay attention at the formatting used in
|
||||
this function because it is programmed to be pretty
|
||||
printed and may differ from the actual request.
|
||||
"""
|
||||
print('{}\n{}\r\n{}\r\n\r\n{}'.format(
|
||||
'-----------START-----------',
|
||||
req.method + ' ' + req.url,
|
||||
'\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
|
||||
req.body,
|
||||
))
|
||||
|
||||
|
||||
class PACComercioDigital(object):
|
||||
ws = 'https://{}.comercio-digital.mx/{}'
|
||||
api = 'https://app2.comercio-digital.mx/{}'
|
||||
URL = {
|
||||
'timbra': ws.format('ws', 'timbre4/timbrarV5'),
|
||||
'cancel': ws.format('cancela', 'cancela4/cancelarUuid'),
|
||||
'cancelxml': ws.format('cancela', 'cancela4/cancelarXml'),
|
||||
'status': ws.format('cancela', 'arws/consultaEstatus'),
|
||||
'client': api.format('x3/altaEmpresa'),
|
||||
'saldo': api.format('x3/saldo'),
|
||||
'timbres': api.format('x3/altaTimbres'),
|
||||
}
|
||||
CODES = {
|
||||
'000': '000 Exitoso',
|
||||
'004': '004 RFC {} ya esta dado de alta con Estatus=A',
|
||||
'704': '704 Usuario Invalido',
|
||||
'702': '702 Error rfc/empresa invalido',
|
||||
}
|
||||
NS_CFDI = {
|
||||
'cfdi': 'http://www.sat.gob.mx/cfd/4',
|
||||
'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
}
|
||||
|
||||
if DEBUG:
|
||||
ws = 'https://pruebas.comercio-digital.mx/{}'
|
||||
ws6 = 'https://pruebas6.comercio-digital.mx/arws/{}'
|
||||
URL = {
|
||||
'timbra': ws.format('timbre4/timbrarV5'),
|
||||
'cancel': ws.format('cancela4/cancelarUuid'),
|
||||
'cancelxml': ws.format('cancela4/cancelarXml'),
|
||||
'status': ws6.format('consultaEstatus'),
|
||||
'client': api.format('x3/altaEmpresa'),
|
||||
'saldo': api.format('x3/saldo'),
|
||||
'timbres': api.format('x3/altaTimbres'),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.error = ''
|
||||
|
||||
def _error(self, msg):
|
||||
self.error = str(msg)
|
||||
log.error(msg)
|
||||
return
|
||||
|
||||
def _post(self, url, data, headers={}):
|
||||
result = None
|
||||
headers['host'] = url.split('/')[2]
|
||||
headers['Content-type'] = 'text/plain'
|
||||
headers['Connection'] = 'Keep-Alive'
|
||||
headers['Expect'] = '100-continue'
|
||||
|
||||
if DEBUG:
|
||||
req = requests.Request('POST', url, headers=headers, data=data)
|
||||
prepared = req.prepare()
|
||||
pretty_print_POST(prepared)
|
||||
|
||||
try:
|
||||
result = requests.post(url, data=data, headers=headers, timeout=TIMEOUT)
|
||||
except ConnectionError as e:
|
||||
self._error(e)
|
||||
|
||||
return result
|
||||
|
||||
def _validate_cfdi(self, xml):
|
||||
"""
|
||||
Comercio Digital solo soporta la declaración con doble comilla
|
||||
"""
|
||||
# ~ tree = ET.fromstring(xml.encode())
|
||||
# ~ xml = ET.tostring(tree,
|
||||
# ~ pretty_print=True, doctype='<?xml version="1.0" encoding="utf-8"?>')
|
||||
return xml.encode('utf-8')
|
||||
|
||||
def stamp(self, cfdi, auth):
|
||||
# ~ if DEBUG or not auth:
|
||||
# ~ auth = AUTH
|
||||
|
||||
url = self.URL['timbra']
|
||||
headers = {
|
||||
'usrws': auth['user'],
|
||||
'pwdws': auth['pass'],
|
||||
'tipo': 'XML',
|
||||
}
|
||||
cfdi = self._validate_cfdi(cfdi)
|
||||
result = self._post(url, cfdi, headers)
|
||||
|
||||
if result is None:
|
||||
return ''
|
||||
|
||||
if result.status_code != 200:
|
||||
return ''
|
||||
|
||||
if 'errmsg' in result.headers:
|
||||
self._error(result.headers['errmsg'])
|
||||
return ''
|
||||
|
||||
xml = result.content
|
||||
tree = ET.fromstring(xml)
|
||||
cfdi_uuid = tree.xpath(
|
||||
'string(//cfdi:Complemento/tdf:TimbreFiscalDigital/@UUID)',
|
||||
namespaces=self.NS_CFDI)
|
||||
date_stamped = tree.xpath(
|
||||
'string(//cfdi:Complemento/tdf:TimbreFiscalDigital/@FechaTimbrado)',
|
||||
namespaces=self.NS_CFDI)
|
||||
|
||||
data = {
|
||||
'xml': xml.decode(),
|
||||
'uuid': cfdi_uuid,
|
||||
'date': date_stamped,
|
||||
}
|
||||
return data
|
||||
|
||||
def _get_data_cancel(self, cfdi, info, auth):
|
||||
info['tipo'] = 'cfdi'
|
||||
info['key'] = base64.b64encode(info['key_enc']).decode()
|
||||
info['cer'] = base64.b64encode(info['cer_ori']).decode()
|
||||
|
||||
tree = ET.fromstring(cfdi.encode())
|
||||
version = tree.attrib['Version']
|
||||
|
||||
namespaces = {
|
||||
'cfdi': NAMESPACES[version],
|
||||
'tdf': NAMESPACES['tdf'],
|
||||
}
|
||||
|
||||
tipo = tree.xpath(
|
||||
'string(//cfdi:Comprobante/@TipoDeComprobante)',
|
||||
namespaces=namespaces)
|
||||
total = tree.xpath(
|
||||
'string(//cfdi:Comprobante/@Total)',
|
||||
namespaces=namespaces)
|
||||
rfc_emisor = tree.xpath(
|
||||
'string(//cfdi:Comprobante/cfdi:Emisor/@Rfc)',
|
||||
namespaces=namespaces)
|
||||
rfc_receptor = tree.xpath(
|
||||
'string(//cfdi:Comprobante/cfdi:Receptor/@Rfc)',
|
||||
namespaces=namespaces)
|
||||
uid = tree.xpath(
|
||||
'string(//cfdi:Complemento/tdf:TimbreFiscalDigital/@UUID)',
|
||||
namespaces=namespaces)
|
||||
data = (
|
||||
f"USER={auth['user']}",
|
||||
f"PWDW={auth['pass']}",
|
||||
f"RFCE={rfc_emisor}",
|
||||
f"UUID={uid}",
|
||||
f"PWDK={info['pass']}",
|
||||
f"KEYF={info['key']}",
|
||||
f"CERT={info['cer']}",
|
||||
f"TIPO1={info['tipo']}",
|
||||
f"ACUS=SI",
|
||||
f"RFCR={rfc_receptor}",
|
||||
f"TIPOC={tipo}",
|
||||
f"TOTAL={total}",
|
||||
f"UUIDREL={info['args']['uuid']}",
|
||||
f"MOTIVO={info['args']['reason']}",
|
||||
)
|
||||
return '\n'.join(data)
|
||||
|
||||
def cancel(self, cfdi, info, auth):
|
||||
# ~ if DEBUG or not auth:
|
||||
# ~ auth = AUTH
|
||||
url = self.URL['cancel']
|
||||
data = self._get_data_cancel(cfdi, info, auth)
|
||||
|
||||
result = self._post(url, data)
|
||||
|
||||
if result is None:
|
||||
return ''
|
||||
|
||||
if result.status_code != 200:
|
||||
return ''
|
||||
|
||||
if result.headers['codigo'] != '000':
|
||||
self._error(result.headers['errmsg'])
|
||||
return ''
|
||||
|
||||
tree = ET.fromstring(result.text)
|
||||
date_cancel = tree.xpath('string(//Acuse/@Fecha)')[:19]
|
||||
|
||||
data = {
|
||||
'acuse': result.text,
|
||||
'date': date_cancel,
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def _get_headers_cancel_xml(self, cfdi, info, auth):
|
||||
NS_CFDI = {
|
||||
'cfdi': 'http://www.sat.gob.mx/cfd/3',
|
||||
'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
}
|
||||
tree = ET.fromstring(cfdi.encode())
|
||||
tipocfdi = tree.xpath(
|
||||
'string(//cfdi:Comprobante/@TipoDeComprobante)',
|
||||
namespaces=NS_CFDI)
|
||||
total = tree.xpath(
|
||||
'string(//cfdi:Comprobante/@Total)',
|
||||
namespaces=NS_CFDI)
|
||||
rfc_receptor = tree.xpath(
|
||||
'string(//cfdi:Comprobante/cfdi:Receptor/@Rfc)',
|
||||
namespaces=NS_CFDI)
|
||||
|
||||
headers = {
|
||||
'usrws': auth['user'],
|
||||
'pwdws': auth['pass'],
|
||||
'rfcr': rfc_receptor,
|
||||
'total': total,
|
||||
'tipocfdi': tipocfdi,
|
||||
}
|
||||
headers.update(info)
|
||||
|
||||
return headers
|
||||
|
||||
def cancel_xml(self, xml, auth, cfdi='', info={'tipo': 'cfdi'}):
|
||||
# ~ if DEBUG or not auth:
|
||||
# ~ auth = AUTH
|
||||
|
||||
url = self.URL['cancelxml']
|
||||
headers = self._get_headers_cancel_xml(cfdi, info, auth)
|
||||
result = self._post(url, xml, headers)
|
||||
|
||||
if result is None:
|
||||
return ''
|
||||
|
||||
if result.status_code != 200:
|
||||
return ''
|
||||
|
||||
if result.headers['codigo'] != '000':
|
||||
self._error(result.headers['errmsg'])
|
||||
return ''
|
||||
|
||||
tree = ET.fromstring(result.text)
|
||||
date_cancel = tree.xpath('string(//Acuse/@Fecha)')[:19]
|
||||
|
||||
data = {
|
||||
'acuse': result.text,
|
||||
'date': date_cancel,
|
||||
}
|
||||
return data
|
||||
|
||||
def status(self, data, auth):
|
||||
# ~ if not auth:
|
||||
# ~ auth = AUTH
|
||||
url = self.URL['status']
|
||||
|
||||
data = (
|
||||
f"USER={auth['user']}",
|
||||
f"PWDW={auth['pass']}",
|
||||
f"RFCR={data['rfc_receptor']}",
|
||||
f"RFCE={data['rfc_emisor']}",
|
||||
f"TOTAL={data['total']}",
|
||||
f"UUID={data['uuid']}",
|
||||
)
|
||||
data = '\n'.join(data)
|
||||
result = self._post(url, data)
|
||||
|
||||
if result is None:
|
||||
return ''
|
||||
|
||||
if result.status_code != 200:
|
||||
self._error(result.status_code)
|
||||
return self.error
|
||||
|
||||
return result.text
|
||||
|
||||
def _get_data_client(self, auth, values):
|
||||
data = [f"usr_ws={auth['user']}", f"pwd_ws={auth['pass']}"]
|
||||
fields = (
|
||||
'rfc_contribuyente',
|
||||
'nombre_contribuyente',
|
||||
'calle',
|
||||
'noExterior',
|
||||
'noInterior',
|
||||
'colonia',
|
||||
'localidad',
|
||||
'municipio',
|
||||
'estado',
|
||||
'pais',
|
||||
'cp',
|
||||
'contacto',
|
||||
'telefono',
|
||||
'email',
|
||||
'rep_nom',
|
||||
'rep_rfc',
|
||||
'email_fact',
|
||||
'pwd_asignado',
|
||||
)
|
||||
data += [f"{k}={values[k]}" for k in fields]
|
||||
|
||||
return '\n'.join(data)
|
||||
|
||||
def client_add(self, data, auth):
|
||||
# ~ auth = AUTH
|
||||
url = self.URL['client']
|
||||
data = self._get_data_client(auth, data)
|
||||
|
||||
result = self._post(url, data)
|
||||
|
||||
if result is None:
|
||||
return False
|
||||
|
||||
if result.status_code != 200:
|
||||
self._error(f'Code: {result.status_code}')
|
||||
return False
|
||||
|
||||
if result.text != self.CODES['000']:
|
||||
self._error(result.text)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def client_balance(self, data, rfc=''):
|
||||
url = self.URL['saldo']
|
||||
host = url.split('/')[2]
|
||||
headers = {
|
||||
'Content-type': 'text/plain',
|
||||
'Host': host,
|
||||
'Connection' : 'Keep-Alive',
|
||||
}
|
||||
data = {'usr': data['user'], 'pwd': data['pass']}
|
||||
try:
|
||||
result = requests.get(url, params=data, headers=headers, timeout=TIMEOUT)
|
||||
except ConnectionError as e:
|
||||
self._error(e)
|
||||
return ''
|
||||
|
||||
if result.status_code != 200:
|
||||
return ''
|
||||
|
||||
if result.text == self.CODES['704']:
|
||||
self._error(result.text)
|
||||
return ''
|
||||
|
||||
if result.text == self.CODES['702']:
|
||||
self._error(result.text)
|
||||
return ''
|
||||
|
||||
return result.text
|
||||
|
||||
def client_add_timbres(self, data, auth):
|
||||
# ~ if not auth:
|
||||
# ~ auth = AUTH
|
||||
url = self.URL['timbres']
|
||||
data = '\n'.join((
|
||||
f"usr_ws={auth['user']}",
|
||||
f"pwd_ws={auth['pass']}",
|
||||
f"rfc_recibir={data['rfc']}",
|
||||
f"num_timbres={data['timbres']}"
|
||||
))
|
||||
|
||||
result = self._post(url, data)
|
||||
|
||||
if result is None:
|
||||
return False
|
||||
|
||||
if result.status_code != 200:
|
||||
self._error(f'Code: {result.status_code}')
|
||||
return False
|
||||
|
||||
if result.text != self.CODES['000']:
|
||||
self._error(result.text)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python
|
||||
# ~
|
||||
# ~ PAC
|
||||
# ~ Copyright (C) 2018-2019 Mauricio Baeza Servin - public [AT] elmau [DOT] net
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# ~ Siempre consulta la documentación de PAC
|
||||
# ~ AUTH = Las credenciales de timbrado proporcionadas por el PAC
|
||||
# ~ NO cambies las credenciales de prueba
|
||||
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
AUTH = {
|
||||
'user': '',
|
||||
'pass': '',
|
||||
}
|
||||
|
||||
|
||||
if DEBUG:
|
||||
AUTH = {
|
||||
'user': 'AAA010101AAA',
|
||||
'pass': 'PWD',
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from .finkok import PACFinkok
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python
|
||||
# ~
|
||||
# ~ PAC
|
||||
# ~ Copyright (C) 2018-2019 Mauricio Baeza Servin - public [AT] elmau [DOT] net
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# ~ Siempre consulta la documentación de PAC
|
||||
# ~ AUTH = Las credenciales de timbrado proporcionadas por el PAC
|
||||
# ~ NO cambies las credenciales de prueba
|
||||
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
AUTH = {
|
||||
'user': '',
|
||||
'pass': '',
|
||||
'RESELLER': {
|
||||
'user': '',
|
||||
'pass': ''
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if DEBUG:
|
||||
AUTH = {
|
||||
'user': 'pruebas-finkok@correolibre.net',
|
||||
'pass': '5c9a88da105bff9a8c430cb713f6d35269f51674bdc5963c1501b7316366',
|
||||
'RESELLER': {
|
||||
'user': '',
|
||||
'pass': ''
|
||||
}
|
||||
}
|
|
@ -0,0 +1,580 @@
|
|||
#!/usr/bin/env python
|
||||
# ~
|
||||
# ~ PAC
|
||||
# ~ Copyright (C) 2018-2019 Mauricio Baeza Servin - public [AT] elmau [DOT] net
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# ~ import base64
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from io import BytesIO
|
||||
from xml.sax.saxutils import unescape
|
||||
|
||||
import lxml.etree as ET
|
||||
from zeep import Client
|
||||
from zeep.plugins import Plugin
|
||||
from zeep.cache import SqliteCache
|
||||
from zeep.transports import Transport
|
||||
from zeep.exceptions import Fault, TransportError
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
from .conf import DEBUG, AUTH
|
||||
|
||||
|
||||
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||
LOG_DATE = '%d/%m/%Y %H:%M:%S'
|
||||
logging.addLevelName(logging.ERROR, '\033[1;41mERROR\033[1;0m')
|
||||
logging.addLevelName(logging.DEBUG, '\x1b[33mDEBUG\033[1;0m')
|
||||
logging.addLevelName(logging.INFO, '\x1b[32mINFO\033[1;0m')
|
||||
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
|
||||
log = logging.getLogger(__name__)
|
||||
logging.getLogger('requests').setLevel(logging.ERROR)
|
||||
logging.getLogger('zeep').setLevel(logging.ERROR)
|
||||
|
||||
|
||||
TIMEOUT = 10
|
||||
DEBUG_SOAP = False
|
||||
|
||||
|
||||
class DebugPlugin(Plugin):
|
||||
|
||||
def _to_string(self, envelope, name):
|
||||
if DEBUG_SOAP:
|
||||
data = ET.tostring(envelope, pretty_print=True, encoding='utf-8').decode()
|
||||
path = f'/tmp/soap_{name}.xml'
|
||||
with open(path, 'w') as f:
|
||||
f.write(data)
|
||||
# ~ print(data)
|
||||
return
|
||||
|
||||
def egress(self, envelope, http_headers, operation, binding_options):
|
||||
self._to_string(envelope, 'request')
|
||||
return envelope, http_headers
|
||||
|
||||
def ingress(self, envelope, http_headers, operation):
|
||||
self._to_string(envelope, 'response')
|
||||
return envelope, http_headers
|
||||
|
||||
|
||||
class PACFinkok(object):
|
||||
WS = 'https://facturacion.finkok.com/servicios/soap/{}.wsdl'
|
||||
NS_TYPE = 'ns1'
|
||||
if DEBUG:
|
||||
WS = 'https://demo-facturacion.finkok.com/servicios/soap/{}.wsdl'
|
||||
NS_TYPE = 'ns0'
|
||||
URL = {
|
||||
'quick_stamp': False,
|
||||
'timbra': WS.format('stamp'),
|
||||
'cancel': WS.format('cancel'),
|
||||
'client': WS.format('registration'),
|
||||
'util': WS.format('utilities'),
|
||||
}
|
||||
CODE = {
|
||||
'200': 'Comprobante timbrado satisfactoriamente',
|
||||
'205': 'No Encontrado',
|
||||
'307': 'Comprobante timbrado previamente',
|
||||
'702': 'No se encontro el RFC del emisor',
|
||||
'IP': 'Invalid Passphrase',
|
||||
'IPMSG': 'Frase de paso inválida',
|
||||
'NE': 'No Encontrado',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self._error = ''
|
||||
self._transport = Transport(cache=SqliteCache(), timeout=TIMEOUT)
|
||||
self._plugins = [DebugPlugin()]
|
||||
|
||||
@property
|
||||
def error(self):
|
||||
return self._error
|
||||
|
||||
def _validate_result(self, result):
|
||||
if hasattr(result, 'Incidencias') and not result.Incidencias is None:
|
||||
fault = result.Incidencias.Incidencia[0]
|
||||
cod_error = fault.CodigoError.encode('utf-8').decode()
|
||||
msg_error = fault.MensajeIncidencia.encode('utf-8').decode()
|
||||
error = 'Error: {}\n{}'.format(cod_error, msg_error)
|
||||
if cod_error == '307':
|
||||
return result
|
||||
|
||||
self._error = self.CODE.get(cod_error, error)
|
||||
return {}
|
||||
|
||||
if hasattr(result, 'CodEstatus'):
|
||||
ce = result.CodEstatus
|
||||
if ce is None:
|
||||
return result
|
||||
|
||||
if ce == self.CODE['IP']:
|
||||
self._error = self.CODE['IPMSG']
|
||||
return {}
|
||||
|
||||
if self.CODE['NE'] in ce:
|
||||
self._error = 'UUID ' + self.CODE['NE']
|
||||
return {}
|
||||
|
||||
if ce == 'UUID Not Found':
|
||||
self._error = 'UUID ' + self.CODE['NE']
|
||||
return {}
|
||||
|
||||
if self.CODE['200'] != ce:
|
||||
self._error = ce
|
||||
return {}
|
||||
|
||||
return result
|
||||
|
||||
return result
|
||||
|
||||
def _get_result(self, client, method, args):
|
||||
self._error = ''
|
||||
try:
|
||||
result = getattr(client.service, method)(**args)
|
||||
except Fault as e:
|
||||
self._error = str(e)
|
||||
return {}
|
||||
except TransportError as e:
|
||||
if '413' in str(e):
|
||||
self._error = '413<BR><BR><b>Documento muy grande para timbrar</b>'
|
||||
else:
|
||||
self._error = str(e)
|
||||
return {}
|
||||
except ConnectionError as e:
|
||||
msg = '502 - Error de conexión'
|
||||
self._error = msg
|
||||
return {}
|
||||
|
||||
return self._validate_result(result)
|
||||
|
||||
def _to_string(self, data):
|
||||
root = ET.parse(BytesIO(data.encode('utf-8'))).getroot()
|
||||
xml = ET.tostring(root,
|
||||
pretty_print=True, xml_declaration=True, encoding='utf-8')
|
||||
return xml.decode('utf-8')
|
||||
|
||||
def stamp(self, cfdi, auth={}):
|
||||
if DEBUG or not auth:
|
||||
auth = AUTH
|
||||
|
||||
method = 'timbra'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'xml': cfdi.encode('utf-8'),
|
||||
}
|
||||
result = self._get_result(client, 'stamp', args)
|
||||
if self.error:
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
data = {
|
||||
'xml': self._to_string(result.xml),
|
||||
'uuid': result.UUID,
|
||||
'date': result.Fecha,
|
||||
}
|
||||
return data
|
||||
|
||||
def _get_data_cancel(self, cfdi):
|
||||
VERSIONS = {
|
||||
'3.3': 'http://www.sat.gob.mx/cfd/3',
|
||||
'4.0': 'http://www.sat.gob.mx/cfd/4',
|
||||
}
|
||||
NS_CFDI = {
|
||||
'tdf': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
}
|
||||
tree = ET.fromstring(cfdi.encode())
|
||||
|
||||
version = tree.attrib['Version']
|
||||
NS_CFDI['cfdi'] = VERSIONS[version]
|
||||
|
||||
rfc_emisor = tree.xpath(
|
||||
'string(//cfdi:Comprobante/cfdi:Emisor/@Rfc)',
|
||||
namespaces=NS_CFDI)
|
||||
cfdi_uuid = tree.xpath(
|
||||
'string(//cfdi:Complemento/tdf:TimbreFiscalDigital/@UUID)',
|
||||
namespaces=NS_CFDI)
|
||||
return rfc_emisor, cfdi_uuid
|
||||
|
||||
def cancel(self, cfdi, info, auth={}):
|
||||
if DEBUG or not auth:
|
||||
auth = AUTH
|
||||
|
||||
rfc_emisor, cfdi_uuid = self._get_data_cancel(cfdi)
|
||||
method = 'cancel'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
|
||||
uuid_type = client.get_type(f'{self.NS_TYPE}:UUIDS')
|
||||
ns1_uuid = client.get_type(f'{self.NS_TYPE}:UUID')
|
||||
|
||||
# ~ sa = client.get_type('ns0:stringArray')
|
||||
|
||||
data_uuid = {
|
||||
'UUID': cfdi_uuid,
|
||||
'FolioSustitucion': info['args']['uuid'],
|
||||
'Motivo': info['args']['reason'],
|
||||
}
|
||||
# ~ 'UUIDS': uuid_type(uuids=sa(string=cfdi_uuid)),
|
||||
|
||||
args = {
|
||||
'UUIDS': uuid_type(ns1_uuid(**data_uuid)),
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'taxpayer_id': rfc_emisor,
|
||||
'cer': info['cer'],
|
||||
'key': info['key'],
|
||||
'store_pending': False,
|
||||
}
|
||||
|
||||
result = self._get_result(client, 'cancel', args)
|
||||
if self.error:
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
folio = result['Folios']['Folio'][0]
|
||||
status = folio['EstatusUUID']
|
||||
if status != '201':
|
||||
log.debug(f'Cancel status: {status} - {cfdi_uuid}')
|
||||
|
||||
data = {
|
||||
'acuse': result['Acuse'],
|
||||
'date': result['Fecha'],
|
||||
}
|
||||
return data
|
||||
|
||||
def cancel_xml(self, xml, auth={}, cfdi=''):
|
||||
if DEBUG or not auth:
|
||||
auth = AUTH
|
||||
|
||||
method = 'cancel'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
client.set_ns_prefix('can', 'http://facturacion.finkok.com/cancel')
|
||||
args = {
|
||||
'xml': xml.encode(),
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'store_pending': False,
|
||||
}
|
||||
result = self._get_result(client, 'cancel_signature', args)
|
||||
if self.error:
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
folio = result['Folios']['Folio'][0]
|
||||
status = folio['EstatusUUID']
|
||||
|
||||
if status == '708':
|
||||
self._error = 'Error 708 del SAT, intenta más tarde.'
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
if status != '201':
|
||||
log.debug(f'Cancel status: {status} -')
|
||||
|
||||
data = {
|
||||
'acuse': result['Acuse'],
|
||||
'date': result['Fecha'],
|
||||
}
|
||||
return data
|
||||
|
||||
def client_add(self, rfc, type_user=False):
|
||||
"""Agrega un nuevo cliente para timbrado.
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del nuevo cliente
|
||||
|
||||
Kwargs:
|
||||
type_user (bool):
|
||||
False == 'P' == Prepago
|
||||
True == 'O' == On demand
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
|
||||
origin PAC
|
||||
'message':
|
||||
'Account Created successfully'
|
||||
'Account Already exists'
|
||||
'success': True or False
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
tu = {True: 'O', False: 'P'}
|
||||
|
||||
method = 'client'
|
||||
client = Client(
|
||||
self.URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'reseller_username': auth['user'],
|
||||
'reseller_password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
'type_user': tu[type_user],
|
||||
'added': datetime.datetime.now().isoformat()[:19],
|
||||
}
|
||||
|
||||
result = self._get_result(client, 'add', args)
|
||||
if self.error:
|
||||
return False
|
||||
|
||||
if not result.success:
|
||||
self.error = result.message
|
||||
return False
|
||||
|
||||
# ~ PAC success debería ser False
|
||||
msg = 'Account Already exists'
|
||||
if result.message == msg:
|
||||
self.error = msg
|
||||
return True
|
||||
|
||||
return result.success
|
||||
|
||||
def client_get_token(self, rfc, email):
|
||||
"""Genera un nuevo token al cliente para timbrado.
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del cliente, ya debe existir
|
||||
email (str): El correo del cliente, funciona como USER al timbrar
|
||||
|
||||
Returns:
|
||||
token (str): Es la contraseña para timbrar
|
||||
|
||||
origin PAC
|
||||
dict
|
||||
'username': 'username',
|
||||
'status': True or False
|
||||
'name': 'name',
|
||||
'success': True or False
|
||||
'token': 'Token de timbrado',
|
||||
'message': None
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
method = 'util'
|
||||
client = Client(
|
||||
self.URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'name': rfc,
|
||||
'token_username': email,
|
||||
'taxpayer_id': rfc,
|
||||
'status': True,
|
||||
}
|
||||
|
||||
result = self._get_result(client, 'add_token', args)
|
||||
if self.error:
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
if not result.success:
|
||||
self.error = result.message
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
return result.token
|
||||
|
||||
def client_add_timbres(self, rfc, credit):
|
||||
"""Agregar credito a un emisor
|
||||
|
||||
Se requiere cuenta de reseller
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del emisor, debe existir
|
||||
credit (int): Cantidad de folios a agregar
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'success': True or False,
|
||||
'credit': nuevo credito despues de agregar or None
|
||||
'message':
|
||||
'Success, added {credit} of credit to {RFC}.'
|
||||
'RFC no encontrado'
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
method = 'client'
|
||||
client = Client(
|
||||
self.URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
'credit': credit,
|
||||
}
|
||||
|
||||
result = self._get_result(client, 'assign', args)
|
||||
if self.error:
|
||||
log.error(error)
|
||||
return ''
|
||||
|
||||
if not result.success:
|
||||
self.error = result.message
|
||||
return 0
|
||||
|
||||
return result.credit
|
||||
|
||||
def client_balance(self, auth={}, rfc=''):
|
||||
"""Regresa los timbres restantes del cliente
|
||||
Se pueden usar las credenciales de relleser o las credenciales del emisor
|
||||
|
||||
Args:
|
||||
auth (dict): Credenciales del emisor
|
||||
rfc (str): El RFC del emisor
|
||||
|
||||
Returns:
|
||||
int Cantidad de timbres restantes
|
||||
"""
|
||||
if not auth:
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
method = 'client'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': auth['user'],
|
||||
'reseller_password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
}
|
||||
result = self._get_result(client, 'get', args)
|
||||
|
||||
if self.error:
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
success = bool(result.users)
|
||||
if not success:
|
||||
self._error = result.message or 'RFC no existe'
|
||||
log.error(self.error)
|
||||
return 0
|
||||
|
||||
return result.users.ResellerUser[0].credit
|
||||
|
||||
def client_set_status(self, rfc, status):
|
||||
"""Edita el estatus (Activo o Suspendido) de un cliente
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del cliente
|
||||
|
||||
Kwargs:
|
||||
status (bool):
|
||||
True == 'A' == Activo
|
||||
False == 'S' == Suspendido
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'message':
|
||||
'Account Created successfully'
|
||||
'Account Already exists'
|
||||
'success': True or False
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
ts = {True: 'A', False: 'S'}
|
||||
method = 'client'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'reseller_username': auth['user'],
|
||||
'reseller_password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
'status': ts[status],
|
||||
}
|
||||
result = self._get_result(client, 'edit', args)
|
||||
|
||||
if self.error:
|
||||
return False
|
||||
|
||||
if not result.success:
|
||||
self.error = result.message
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def client_switch(self, rfc, type_user):
|
||||
"""Edita el tipo de timbrado (OnDemand o Prepago) de un cliente
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
|
||||
Args:
|
||||
rfc (str): El RFC del cliente
|
||||
|
||||
Kwargs:
|
||||
status (bool):
|
||||
True == 'O' == OnDemand
|
||||
False == 'P' == Prepago
|
||||
|
||||
Returns:
|
||||
dict
|
||||
'message':
|
||||
'Account Created successfully'
|
||||
'Account Already exists'
|
||||
'success': True or False
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
tu = {True: 'O', False: 'P'}
|
||||
method = 'client'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
'type_user': tu[type_user],
|
||||
}
|
||||
result = self._get_result(client, 'switch', args)
|
||||
|
||||
if self.error:
|
||||
return False
|
||||
|
||||
if not result.success:
|
||||
self.error = result.message
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def client_report_folios(self, rfc, date_from, date_to, invoice_type='I'):
|
||||
"""Obtiene un reporte del total de facturas timbradas
|
||||
"""
|
||||
auth = AUTH['RESELLER']
|
||||
|
||||
args = {
|
||||
'username': auth['user'],
|
||||
'password': auth['pass'],
|
||||
'taxpayer_id': rfc,
|
||||
'date_from': date_from,
|
||||
'date_to': date_to,
|
||||
'invoice_type': invoice_type,
|
||||
}
|
||||
|
||||
method = 'util'
|
||||
client = Client(self.URL[method],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
|
||||
result = self._get_result(client, 'report_total', args)
|
||||
|
||||
if result.result is None:
|
||||
# ~ PAC - Debería regresar RFC inexistente o sin registros
|
||||
self.error = 'RFC no existe o no tiene registros'
|
||||
return 0
|
||||
|
||||
total = result.result.ReportTotal[0].total
|
||||
|
||||
return total
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from decimal import Decimal, getcontext
|
||||
# ~ getcontext().prec = 6
|
||||
|
||||
import lxml.etree as ET
|
||||
from requests.structures import CaseInsensitiveDict as CIDict
|
||||
|
||||
|
||||
NS_CFDI = {
|
||||
'cfdi': 'http://www.sat.gob.mx/cfd/3',
|
||||
'tfd': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||
'nomina12': 'http://www.sat.gob.mx/nomina12',
|
||||
}
|
||||
PRE = '/cfdi:Comprobante'
|
||||
|
||||
|
||||
class CfdiRead(object):
|
||||
|
||||
def __init__(self, source):
|
||||
self._source = source
|
||||
self._data = {}
|
||||
self._error = ''
|
||||
self._rfc_emisor = ''
|
||||
self._rfc_receptor = ''
|
||||
self._parse()
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
return self._source
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def rfc_emisor(self):
|
||||
return self._rfc_emisor
|
||||
|
||||
@property
|
||||
def rfc_receptor(self):
|
||||
return self._rfc_receptor
|
||||
|
||||
@property
|
||||
def error(self):
|
||||
return self._error
|
||||
|
||||
def _parse(self):
|
||||
self._tree = ET.fromstring(self.source)
|
||||
self._data['cfdi'] = dict(self._tree.attrib)
|
||||
|
||||
node_name = f'{PRE}/cfdi:Emisor'
|
||||
self._data['emisor'] = self._get_attr(node_name)
|
||||
self._rfc_emisor = self._data['emisor']['Rfc']
|
||||
|
||||
node_name = f'{PRE}/cfdi:Receptor'
|
||||
self._data['receptor'] = self._get_attr(node_name)
|
||||
self._rfc_receptor = self._data['receptor']['Rfc']
|
||||
|
||||
node_name = f'{PRE}/cfdi:Complemento/tfd:TimbreFiscalDigital'
|
||||
self._data['timbre'] = self._get_attr(node_name)
|
||||
|
||||
self._parse_details()
|
||||
return
|
||||
|
||||
def _get_attr(self, node_name):
|
||||
node = self._tree.xpath(node_name, namespaces=NS_CFDI)[0]
|
||||
attr = dict(node.attrib)
|
||||
return attr
|
||||
|
||||
def _parse_details(self):
|
||||
node_name = f'{PRE}/cfdi:Conceptos/cfdi:Concepto'
|
||||
details = self._tree.xpath(node_name, namespaces=NS_CFDI)
|
||||
rows = []
|
||||
for detail in details:
|
||||
row = dict(detail.attrib)
|
||||
for k, v in row.items():
|
||||
if k in ('Cantidad', 'ValorUnitario', 'Descuento', 'Importe'):
|
||||
row[k] = Decimal(v)
|
||||
# ~ row['taxes'] = self._get_taxes(detail)
|
||||
rows.append(row)
|
||||
self._data['conceptos'] = rows
|
||||
return
|
||||
|
||||
|
||||
class CfdiWrite(object):
|
||||
pass
|
|
@ -0,0 +1,33 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name cfdi.empresalibre.net;
|
||||
|
||||
location / {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass 127.0.0.1:3033;
|
||||
|
||||
access_log /var/log/nginx/empresa-libre.access.log;
|
||||
error_log /var/log/nginx/empresa-libre.error.log;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
# redirect server error pages to the static page /50x.html
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
location /static {
|
||||
alias /opt/empresa-libre/static;
|
||||
}
|
||||
|
||||
if ($http_user_agent ~* (python|curl) ) {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# Necesario para Let's Encrypt
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
default_type "text/plain";
|
||||
root /opt/www;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=uWSGI instance to serve Empresa Libre
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/uwsgi /opt/empresa-libre/app/main.ini
|
||||
KillSignal=SIGQUIT
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -15,3 +15,5 @@ thunder-lock = true
|
|||
#~ stats = 127.0.0.1:9191
|
||||
#~ Establece una ruta accesible para el servidor web
|
||||
logger = file:/srv/log/empresalibre-uwsgi.log
|
||||
log-maxsize = 1000000
|
||||
http-timeout = 180
|
|
@ -8,7 +8,6 @@ from middleware import (
|
|||
AuthMiddleware,
|
||||
JSONTranslator,
|
||||
ConnectionMiddleware,
|
||||
static,
|
||||
handle_404
|
||||
)
|
||||
from models.db import StorageEngine
|
||||
|
@ -16,9 +15,22 @@ from controllers.main import (AppEmpresas,
|
|||
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
|
||||
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
|
||||
AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco,
|
||||
AppMovimientosBanco
|
||||
AppMovimientosBanco, AppTickets, AppStudents, AppEmployees, AppNomina,
|
||||
AppInvoicePay, AppCfdiPay, AppSATBancos, AppSociosCuentasBanco,
|
||||
AppSATFormaPago, AppSATLeyendaFiscales, AppCert, AppSucursales,
|
||||
AppPartnerProducts,
|
||||
AppInventoryEntries,
|
||||
AppTicketsDetails,
|
||||
AppUsers,
|
||||
AppWareHouse,
|
||||
AppWareHouseProduct,
|
||||
AppSATUnidadesPeso,
|
||||
AppSATRegimenes,
|
||||
AppSociosRegimenes,
|
||||
)
|
||||
from settings import DEBUG
|
||||
|
||||
|
||||
from settings import DEBUG, MV, NO_HTTPS, PATH_SESSIONS
|
||||
|
||||
|
||||
db = StorageEngine()
|
||||
|
@ -47,19 +59,42 @@ api.add_route('/partners', AppPartners(db))
|
|||
api.add_route('/products', AppProducts(db))
|
||||
api.add_route('/invoices', AppInvoices(db))
|
||||
api.add_route('/preinvoices', AppPreInvoices(db))
|
||||
api.add_route('/tickets', AppTickets(db))
|
||||
api.add_route('/cuentasbanco', AppCuentasBanco(db))
|
||||
api.add_route('/movbanco', AppMovimientosBanco(db))
|
||||
|
||||
|
||||
if DEBUG:
|
||||
api.add_sink(static, '/static')
|
||||
api.add_route('/students', AppStudents(db))
|
||||
api.add_route('/employees', AppEmployees(db))
|
||||
api.add_route('/nomina', AppNomina(db))
|
||||
api.add_route('/invoicepay', AppInvoicePay(db))
|
||||
api.add_route('/cfdipay', AppCfdiPay(db))
|
||||
api.add_route('/satbancos', AppSATBancos(db))
|
||||
api.add_route('/satformapago', AppSATFormaPago(db))
|
||||
api.add_route('/socioscb', AppSociosCuentasBanco(db))
|
||||
api.add_route('/leyendasfiscales', AppSATLeyendaFiscales(db))
|
||||
api.add_route('/cert', AppCert(db))
|
||||
api.add_route('/sucursales', AppSucursales(db))
|
||||
api.add_route('/partnerproducts', AppPartnerProducts(db))
|
||||
api.add_route('/inventoryentries', AppInventoryEntries(db))
|
||||
api.add_route('/warehouse', AppWareHouse(db))
|
||||
api.add_route('/warehouseproduct', AppWareHouseProduct(db))
|
||||
api.add_route('/ticketsdetails', AppTicketsDetails(db))
|
||||
api.add_route('/users', AppUsers(db))
|
||||
api.add_route('/satunidadespeso', AppSATUnidadesPeso(db))
|
||||
api.add_route('/satregimenes', AppSATRegimenes(db))
|
||||
api.add_route('/sociosregimenes', AppSociosRegimenes(db))
|
||||
|
||||
|
||||
session_options = {
|
||||
'session.type': 'file',
|
||||
'session.cookie_expires': True,
|
||||
'session.data_dir': '/tmp/cache/data',
|
||||
'session.lock_dir': '/tmp/cache/lock',
|
||||
'session.httponly': True,
|
||||
'session.secure': True,
|
||||
'session.data_dir': PATH_SESSIONS['data'],
|
||||
'session.lock_dir': PATH_SESSIONS['lock'],
|
||||
}
|
||||
# ~ Si no usas (NO deberías) certificados en tu servidor, ponla siempre en False
|
||||
if DEBUG or MV or NO_HTTPS:
|
||||
session_options['session.secure'] = False
|
||||
|
||||
app = SessionMiddleware(api, session_options)
|
||||
|
||||
|
|
|
@ -6,3 +6,6 @@ master = true
|
|||
processes = 4
|
||||
threads = 4
|
||||
py-autoreload = 1
|
||||
thunder-lock = true
|
||||
static-map = /static=../static
|
||||
http-timeout = 300
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
[uwsgi]
|
||||
http = :8000
|
||||
uid = empresa
|
||||
gid = empresa
|
||||
chdir = /home/empresa/.opt/empresa-libre/source/app
|
||||
wsgi-file = main.py
|
||||
callable = app
|
||||
master = true
|
||||
processes = 4
|
||||
threads = 4
|
||||
thunder-lock = true
|
||||
static-map = /static=../static
|
||||
logger = file:../../../empresa-libre-uwsgi.log
|
|
@ -3,7 +3,7 @@
|
|||
import falcon
|
||||
from controllers import util
|
||||
from models import main
|
||||
from settings import MV, PATH_STATIC
|
||||
from settings import MV
|
||||
|
||||
|
||||
def handle_404(req, resp):
|
||||
|
@ -20,27 +20,44 @@ def get_template(req, resp, resource):
|
|||
resp.body = util.get_template(resource.template, data)
|
||||
|
||||
|
||||
def static(req, res):
|
||||
path = PATH_STATIC + req.path
|
||||
if util.is_file(path):
|
||||
res.content_type = util.get_mimetype(path)
|
||||
res.stream, res.stream_len = util.get_stream(path)
|
||||
res.status = falcon.HTTP_200
|
||||
else:
|
||||
res.status = falcon.HTTP_404
|
||||
# ~ def static(req, res):
|
||||
# ~ path = PATH_STATIC + req.path
|
||||
# ~ if util.is_file(path):
|
||||
# ~ res.content_type = util.get_mimetype(path)
|
||||
# ~ res.stream, res.stream_len = util.get_stream(path)
|
||||
# ~ res.status = falcon.HTTP_200
|
||||
# ~ else:
|
||||
# ~ res.status = falcon.HTTP_404
|
||||
|
||||
|
||||
class AuthMiddleware(object):
|
||||
|
||||
def process_response(self, req, resp, resource):
|
||||
pass
|
||||
|
||||
def process_resource(self, req, resp, resource, params):
|
||||
session = req.env['beaker.session']
|
||||
user = session.get('userobj', None)
|
||||
id_session = req.cookies.get('beaker.session.id', '')
|
||||
if req.path == '/empresas':
|
||||
|
||||
if req.path == '/values/titlelogin':
|
||||
pass
|
||||
elif req.path == '/empresas' or req.path == '/values/empresas':
|
||||
if MV:
|
||||
pass
|
||||
else:
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
elif id_session and req.path == '/admin':
|
||||
if user is None:
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
elif not user.es_admin and not user.es_superusuario:
|
||||
raise falcon.HTTPTemporaryRedirect('/main')
|
||||
elif not id_session and req.path != '/':
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
elif id_session and user is None:
|
||||
session.delete()
|
||||
if req.path == '/main':
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
|
||||
class JSONTranslator(object):
|
||||
|
@ -51,9 +68,15 @@ class JSONTranslator(object):
|
|||
def process_response(self, req, resp, resource):
|
||||
if 'result' not in req.context:
|
||||
return
|
||||
|
||||
if '/doc/' in req.path:
|
||||
resp.body = req.context['result']
|
||||
return
|
||||
|
||||
if 'blob' in req.context:
|
||||
resp.body = req.context['blob']
|
||||
return
|
||||
|
||||
resp.body = util.dumps(req.context['result'])
|
||||
|
||||
|
||||
|
@ -66,7 +89,10 @@ class ConnectionMiddleware(object):
|
|||
rfc = session.get('rfc', '')
|
||||
if id_session and rfc:
|
||||
opt = util.get_con(rfc)
|
||||
main.conectar(opt)
|
||||
if opt:
|
||||
main.conectar(opt)
|
||||
else:
|
||||
raise falcon.HTTPTemporaryRedirect('/')
|
||||
|
||||
def process_response(self, req, resp, resource):
|
||||
main.desconectar()
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import main
|
||||
|
||||
|
||||
|
@ -11,15 +27,67 @@ class StorageEngine(object):
|
|||
def authenticate(self, args):
|
||||
return main.authenticate(args)
|
||||
|
||||
def get_values(self, table, values=None):
|
||||
def get_employees(self, values):
|
||||
return main.Empleados.get_by(values)
|
||||
|
||||
def get_nomina(self, values):
|
||||
return main.CfdiNomina.get_by(values)
|
||||
|
||||
def empresa_agregar(self, values):
|
||||
# ~ return main.empresa_agregar(values['alta_rfc'], False)
|
||||
return main._new_client(values['alta_rfc'], False)
|
||||
|
||||
def empresa_borrar(self, values):
|
||||
# ~ return main.empresa_borrar(values['rfc'])
|
||||
return main._delete_client(values['rfc'], False, False)
|
||||
|
||||
def respaldar_dbs(self):
|
||||
return main.respaldar_dbs()
|
||||
|
||||
def get_values(self, table, values=None, session=None):
|
||||
if table in ('allusuarios', 'usuarioupdate', 'main'):
|
||||
return getattr(self, '_get_{}'.format(table))(values, session)
|
||||
return getattr(self, '_get_{}'.format(table))(values)
|
||||
|
||||
def _get_main(self, values):
|
||||
return main.config_main()
|
||||
def _get_timbres(self, values):
|
||||
return main.Emisor.get_timbres()
|
||||
|
||||
def _get_schoolgroups(self, values):
|
||||
return main.Grupos.get_by(values)
|
||||
|
||||
def _get_nivedusat(self, values):
|
||||
return main.SATNivelesEducativos.get_by()
|
||||
|
||||
def _get_niveduall(self, values):
|
||||
return main.NivelesEducativos.get_all()
|
||||
|
||||
def _get_titlelogin(self, values):
|
||||
return main.get_title_app(2)
|
||||
|
||||
def _get_canopenpre(self, values):
|
||||
return main.PreFacturasDetalle.can_open(values['id'])
|
||||
|
||||
def _get_importinvoice(self, values):
|
||||
return main.import_invoice()
|
||||
|
||||
def _get_importceods(self, values):
|
||||
return main.import_ceods()
|
||||
|
||||
def _get_main(self, values, session):
|
||||
return main.config_main(session['userobj'])
|
||||
|
||||
def _get_configtimbrar(self, values):
|
||||
return main.config_timbrar()
|
||||
|
||||
def _get_invoicenotes(self, values):
|
||||
return main.Facturas.get_notes(values['id'])
|
||||
|
||||
def save_invoice_notes(self, values):
|
||||
return main.Facturas.save_notes(values)
|
||||
|
||||
def _get_configticket(self, values):
|
||||
return main.config_ticket()
|
||||
|
||||
def _get_saldocuenta(self, values):
|
||||
return main.CuentasBanco.get_saldo(values['id'])
|
||||
|
||||
|
@ -55,17 +123,20 @@ class StorageEngine(object):
|
|||
def enviar_prefac(self, values):
|
||||
return main.PreFacturas.enviar(values['id'])
|
||||
|
||||
def _get_cancelinvoice(self, values):
|
||||
return main.Facturas.cancel(values['id'])
|
||||
|
||||
def _get_statussat(self, values):
|
||||
return main.Facturas.get_status_sat(values['id'])
|
||||
def _get_verifysat(self, values):
|
||||
return main.Facturas.get_verify_sat(values['id'])
|
||||
|
||||
def _get_filteryears(self, values):
|
||||
years1 = main.Facturas.filter_years()
|
||||
years2 = main.PreFacturas.filter_years()
|
||||
return [years1, years2]
|
||||
|
||||
def _get_filteryearsticket(self, values):
|
||||
return main.Tickets.filter_years()
|
||||
|
||||
def _get_filteryearsnomina(self, values):
|
||||
return main.CfdiNomina.filter_years()
|
||||
|
||||
def _get_cuentayears(self, values):
|
||||
return main.CuentasBanco.get_years()
|
||||
|
||||
|
@ -93,12 +164,24 @@ class StorageEngine(object):
|
|||
def _get_unidades(self, values):
|
||||
return main.SATUnidades.get_activos()
|
||||
|
||||
def _get_unitbykey(self, values):
|
||||
return main.SATUnidades.get_activos_by_key()
|
||||
|
||||
def add_moneda(self, values):
|
||||
return main.SATMonedas.add(values)
|
||||
|
||||
def add_unidad(self, values):
|
||||
return main.SATUnidades.add(values)
|
||||
|
||||
def add_impuesto(self, values):
|
||||
return main.SATImpuestos.add(values)
|
||||
|
||||
def add_usuario(self, values):
|
||||
return main.Usuarios.add(values)
|
||||
|
||||
def edit_usuario(self, values):
|
||||
return main.Usuarios.edit(values)
|
||||
|
||||
def _get_taxes(self, values):
|
||||
return main.SATImpuestos.get_activos()
|
||||
|
||||
|
@ -117,6 +200,19 @@ class StorageEngine(object):
|
|||
def _get_allformasdepago(self, values):
|
||||
return main.SATFormaPago.get_()
|
||||
|
||||
def _get_allusoscfdi(self, values):
|
||||
return main.SATUsoCfdi.get_all()
|
||||
|
||||
def _get_allregimenes(self, values):
|
||||
filters = {'opt': 'all'}
|
||||
return main.SATRegimenes.get_data(filters, None)
|
||||
|
||||
def _get_allusuarios(self, values, session):
|
||||
return main.Usuarios.get_(session['userobj'])
|
||||
|
||||
def _get_usuarioupdate(self, values, session):
|
||||
return main.Usuarios.actualizar(values, session['userobj'])
|
||||
|
||||
def _get_taxupdate(self, values):
|
||||
return main.SATImpuestos.actualizar(values)
|
||||
|
||||
|
@ -126,21 +222,36 @@ class StorageEngine(object):
|
|||
def _get_bancoupdate(self, values):
|
||||
return main.SATBancos.actualizar(values)
|
||||
|
||||
def _get_emisorbancoupdate(self, values):
|
||||
return main.CuentasBanco.activate(values)
|
||||
|
||||
def _get_unidadupdate(self, values):
|
||||
return main.SATUnidades.actualizar(values)
|
||||
|
||||
def _get_formasdepagoupdate(self, values):
|
||||
return main.SATFormaPago.actualizar(values)
|
||||
|
||||
def _get_usocfdiupdate(self, values):
|
||||
return main.SATUsoCfdi.actualizar(values)
|
||||
|
||||
def _get_regimenesupdate(self, values):
|
||||
return main.SATRegimenes.actualizar(values)
|
||||
|
||||
def _get_emisorcuentasbanco(self, values):
|
||||
return main.CuentasBanco.emisor()
|
||||
|
||||
def _get_satkey(self, values):
|
||||
return main.get_sat_key(values['key'])
|
||||
|
||||
def _get_satmonedas(self, values):
|
||||
return main.get_sat_monedas(values['key'])
|
||||
|
||||
def _get_satunidades(self, values):
|
||||
return main.get_sat_unidades(values['key'])
|
||||
|
||||
def _get_satunidadespeso(self, values):
|
||||
return main.get_sat_unidadespeso(values['key'])
|
||||
|
||||
def _get_satproductos(self, values):
|
||||
return main.get_sat_productos(values['key'])
|
||||
|
||||
|
@ -165,54 +276,90 @@ class StorageEngine(object):
|
|||
def _get_ebancomov(self, values):
|
||||
return main.MovimientosBanco.con(values['id'])
|
||||
|
||||
def delete(self, table, id):
|
||||
def delete(self, table, id, user=None):
|
||||
if table == 'partner':
|
||||
return main.Socios.remove(id)
|
||||
if table == 'product':
|
||||
return main.Productos.remove(id)
|
||||
if table == 'invoice':
|
||||
return main.Facturas.remove(id)
|
||||
return main.Facturas.remove(id, user)
|
||||
if table == 'folios':
|
||||
return main.Folios.remove(id)
|
||||
if table == 'preinvoice':
|
||||
return main.PreFacturas.remove(id)
|
||||
if table == 'satimpuesto':
|
||||
return main.SATImpuestos.remove(id)
|
||||
if table == 'satunit':
|
||||
return main.SATUnidades.remove(id)
|
||||
if table == 'cuentasbanco':
|
||||
return main.CuentasBanco.remove(id)
|
||||
if table == 'movbanco':
|
||||
return main.MovimientosBanco.remove(id)
|
||||
if table == 'usuario':
|
||||
return main.Usuarios.remove(id)
|
||||
if table == 'config':
|
||||
return main.Configuracion.remove(id)
|
||||
if table == 'nivedu':
|
||||
return main.NivelesEducativos.remove(id)
|
||||
if table == 'students':
|
||||
return main.Alumnos.remove(id)
|
||||
if table == 'employee':
|
||||
return main.Empleados.remove(id)
|
||||
if table == 'nomina':
|
||||
return main.CfdiNomina.remove(id)
|
||||
return False
|
||||
|
||||
def _get_client(self, values):
|
||||
return main.Socios.get_by_client(values)
|
||||
|
||||
def _get_student(self, values):
|
||||
return main.Alumnos.get_by_name(values)
|
||||
|
||||
def _get_product(self, values):
|
||||
return main.Productos.get_by(values)
|
||||
|
||||
def _get_productokey(self, values):
|
||||
return main.Productos.get_by_key(values)
|
||||
|
||||
def get_partners(self, values):
|
||||
return main.Socios.get_(values)
|
||||
|
||||
def partner(self, values):
|
||||
if 'opt' in values:
|
||||
return main.Socios.opt(values)
|
||||
|
||||
id = int(values.pop('id', '0'))
|
||||
if id:
|
||||
return main.Socios.actualizar(values, id)
|
||||
|
||||
return main.Socios.add(values)
|
||||
|
||||
def get_products(self, values):
|
||||
return main.Productos.get_(values)
|
||||
|
||||
def product(self, values):
|
||||
def products(self, values):
|
||||
id = int(values.pop('id', '0'))
|
||||
if id:
|
||||
return main.Productos.actualizar(values, id)
|
||||
|
||||
opt = values.get('opt', '')
|
||||
if opt:
|
||||
return main.Productos.opt(values)
|
||||
|
||||
return main.Productos.add(values)
|
||||
|
||||
def invoice(self, values):
|
||||
def invoice(self, values, user):
|
||||
if 'opt' in values:
|
||||
return main.Facturas.opt(values, user)
|
||||
|
||||
id = int(values.pop('id', '0'))
|
||||
if id:
|
||||
return main.Facturas.actualizar(values, id)
|
||||
return main.Facturas.add(values)
|
||||
|
||||
return main.Facturas.add(values, user)
|
||||
|
||||
def invoice_put(self, values, user):
|
||||
return main.Facturas.put(values, user)
|
||||
|
||||
def preinvoice(self, values):
|
||||
id = int(values.pop('id', '0'))
|
||||
|
@ -220,14 +367,40 @@ class StorageEngine(object):
|
|||
#~ return main.PreFacturas.actualizar(values, id)
|
||||
return main.PreFacturas.add(values)
|
||||
|
||||
def get_invoices(self, values):
|
||||
return main.Facturas.get_(values)
|
||||
def get_students(self, values):
|
||||
return main.Alumnos.get_by(values)
|
||||
|
||||
def students(self, values):
|
||||
opt = values.pop('opt')
|
||||
if opt == 'add':
|
||||
return main.Alumnos.add(values['values'])
|
||||
if opt == 'edit':
|
||||
return main.Alumnos.actualizar(values['values'])
|
||||
|
||||
def tickets(self, values, user):
|
||||
opt = values.pop('opt')
|
||||
if opt == 'add':
|
||||
return main.Tickets.add(values, user)
|
||||
if opt == 'cancel':
|
||||
return main.Tickets.cancel(values, user)
|
||||
if opt == 'invoice':
|
||||
return main.Tickets.invoice(values, user)
|
||||
if opt == 'print':
|
||||
return main.Tickets.printer(values)
|
||||
|
||||
def get_tickets(self, values, user):
|
||||
return main.Tickets.get_by(values, user)
|
||||
|
||||
def get_invoices(self, filters, user):
|
||||
if filters.get('by', ''):
|
||||
return main.Facturas.get_by(filters, user)
|
||||
return main.Facturas.get_(filters)
|
||||
|
||||
def get_preinvoices(self, values):
|
||||
return main.PreFacturas.get_(values)
|
||||
|
||||
def _get_timbrar(self, values):
|
||||
return main.Facturas.timbrar(int(values['id']))
|
||||
# ~ def _get_timbrar(self, values):
|
||||
# ~ return main.Facturas.timbrar(values)
|
||||
|
||||
def _get_anticipoegreso(self, values):
|
||||
return main.Facturas.anticipo_egreso(int(values['id']))
|
||||
|
@ -241,8 +414,8 @@ class StorageEngine(object):
|
|||
def cuentasbanco(self, values):
|
||||
return main.CuentasBanco.add(values)
|
||||
|
||||
def add_movbanco(self, values):
|
||||
return main.MovimientosBanco.add(values)
|
||||
# ~ def add_movbanco(self, values):
|
||||
# ~ return main.MovimientosBanco.add(values)
|
||||
|
||||
def get_cuentasbanco(self, values):
|
||||
return main.CuentasBanco.get_(values)
|
||||
|
@ -253,24 +426,123 @@ class StorageEngine(object):
|
|||
def add_folios(self, values):
|
||||
return main.Folios.add(values)
|
||||
|
||||
def get_doc(self, type_doc, id, rfc):
|
||||
if type_doc == 'xml':
|
||||
data, file_name = main.Facturas.get_xml(id)
|
||||
content_type = 'application/xml'
|
||||
elif type_doc == 'pdf':
|
||||
data, file_name = main.Facturas.get_pdf(id, rfc)
|
||||
content_type = 'application/pdf'
|
||||
elif type_doc == 'zip':
|
||||
data, file_name = main.Facturas.get_zip(id, rfc)
|
||||
content_type = 'application/octet-stream'
|
||||
elif type_doc == 'pdf2':
|
||||
data, file_name = main.PreFacturas.get_pdf(id)
|
||||
content_type = 'application/pdf'
|
||||
def add_nivel_educativo(self, values):
|
||||
return main.NivelesEducativos.add(values)
|
||||
|
||||
return data, file_name, content_type
|
||||
def get_doc(self, type_doc, id, rfc):
|
||||
return main.get_doc(type_doc, id, rfc)
|
||||
|
||||
def get_movimientosbanco(self, values):
|
||||
return main.MovimientosBanco.get_(values)
|
||||
|
||||
def importar_bdfl(self):
|
||||
return main.importar_bdfl()
|
||||
|
||||
# ~ Revisado
|
||||
def get_invoicepay(self, values):
|
||||
return main.FacturasPagos.get_values(values)
|
||||
|
||||
def get_cfdipay(self, values):
|
||||
return main.CfdiPagos.get_values(values)
|
||||
|
||||
def get_sat_bancos(self, values):
|
||||
return main.SATBancos.get_values(values)
|
||||
|
||||
def get_sat_forma_pago(self, values):
|
||||
return main.SATFormaPago.get_values(values)
|
||||
|
||||
def get_partners_accounts_bank(self, values):
|
||||
return main.SociosCuentasBanco.get_values(values)
|
||||
|
||||
def cfdipay(self, values):
|
||||
return main.CfdiPagos.post(values)
|
||||
|
||||
def bankmovement(self, values):
|
||||
return main.MovimientosBanco.post(values)
|
||||
|
||||
def sat_bancos(self, values):
|
||||
return main.SATBancos.post(values)
|
||||
|
||||
def sat_forma_pago(self, values):
|
||||
return main.SATFormaPago.post(values)
|
||||
|
||||
def partners_accounts_bank(self, values):
|
||||
return main.SociosCuentasBanco.post(values)
|
||||
|
||||
def nomina(self, values, user):
|
||||
return main.CfdiNomina.post(values, user)
|
||||
|
||||
def sat_leyendas_fiscales_get(self, values):
|
||||
return main.SATLeyendasFiscales.get_values(values)
|
||||
|
||||
def sat_leyendas_fiscales_post(self, values):
|
||||
return main.SATLeyendasFiscales.post(values)
|
||||
|
||||
def sat_leyendas_fiscales_delete(self, values):
|
||||
return main.SATLeyendasFiscales.remove(values)
|
||||
|
||||
# ~ v2
|
||||
def cert_get(self, filters):
|
||||
return main.Certificado.get_data(filters)
|
||||
|
||||
def cert_post(self, filters):
|
||||
return main.Certificado.post(filters)
|
||||
|
||||
def sucursales_get(self, filters):
|
||||
return main.Sucursales.get_data(filters)
|
||||
|
||||
def sucursales_post(self, filters):
|
||||
return main.Sucursales.post(filters)
|
||||
|
||||
def partner_products_get(self, filters):
|
||||
return main.PartnerProducts.get_data(filters)
|
||||
|
||||
def inventory_entries_get(self, filters):
|
||||
return main.InventoryEntries.get_data(filters)
|
||||
|
||||
def inventory_entries_post(self, filters, user):
|
||||
return main.InventoryEntries.post(filters, user)
|
||||
|
||||
def warehouse_get(self, filters):
|
||||
return main.Almacenes.get_data(filters)
|
||||
|
||||
def warehouse_post(self, values, user):
|
||||
return main.Almacenes.post(values, user)
|
||||
|
||||
def warehouseproduct_get(self, filters, user):
|
||||
return main.WareHouseProduct.get_data(filters, user)
|
||||
|
||||
def warehouseproduct_post(self, filters, user):
|
||||
return main.WareHouseProduct.post(filters, user)
|
||||
|
||||
def users_get(self, filters, user):
|
||||
return main.Usuarios.get_data(filters, user)
|
||||
|
||||
def users_post(self, args, user):
|
||||
return main.Usuarios.post(args, user)
|
||||
|
||||
def ticketsdetails_get(self, filters, user):
|
||||
return main.TicketsDetalle.get_data(filters, user)
|
||||
|
||||
def products_get(self, filters, user):
|
||||
return main.Productos.get_data(filters, user)
|
||||
|
||||
def nomina_get(self, filters, user):
|
||||
return main.CfdiNomina.get_data(filters, user)
|
||||
|
||||
def sat_unidades_peso_get(self, filters, user):
|
||||
return main.SATUnidadesPeso.get_data(filters, user)
|
||||
|
||||
def sat_unidades_peso_post(self, args, user):
|
||||
return main.SATUnidadesPeso.post(args, user)
|
||||
|
||||
def sat_regimenes_get(self, filters, user):
|
||||
return main.SATRegimenes.get_data(filters, user)
|
||||
|
||||
def socios_regimenes_get(self, filters, user):
|
||||
return main.SociosRegimenes.get_data(filters, user)
|
||||
|
||||
# Companies only in MV
|
||||
def _get_empresas(self, values):
|
||||
return main.companies_get()
|
||||
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (publico@cuates.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 of the License, or
|
||||
# ~ (at your option) any later version.
|
||||
# ~
|
||||
# ~ This program is distributed in the hope that it will be useful,
|
||||
# ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# ~ GNU General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logbook
|
||||
import os
|
||||
|
@ -9,13 +25,38 @@ logbook.set_datetime_format('local')
|
|||
|
||||
from conf import DEBUG, MV, LOG_PATH
|
||||
|
||||
try:
|
||||
from conf import DEFAULT_PASSWORD
|
||||
except ImportError:
|
||||
DEFAULT_PASSWORD = 'salgueiro4.0'
|
||||
|
||||
TITLE_APP = 'Empresa Libre'
|
||||
|
||||
try:
|
||||
from conf import NO_HTTPS
|
||||
except ImportError:
|
||||
NO_HTTPS = True
|
||||
|
||||
|
||||
DEBUG = DEBUG
|
||||
VERSION = '0.2.1'
|
||||
EMAIL_SUPPORT = ('soporte@empresalibre.net',)
|
||||
VERSION = '2.3.2'
|
||||
|
||||
EMAIL_SUPPORT = ('soporte@empresalibre.mx',)
|
||||
TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION)
|
||||
|
||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..'))
|
||||
COMPANIES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'rfc.db'))
|
||||
|
||||
path_static = os.path.abspath(os.path.join(BASE_DIR, '..', 'static'))
|
||||
path_docs = os.path.abspath(os.path.join(BASE_DIR, '..', 'docs'))
|
||||
|
||||
path_css = os.path.join(path_static, 'css')
|
||||
path_img = os.path.join(path_static, 'img')
|
||||
path_user_template = os.path.join(path_docs, 'templates')
|
||||
path_user_logos = os.path.join(path_docs, 'logos')
|
||||
|
||||
# ~ PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..'))
|
||||
|
||||
PATH_TEMPLATES = os.path.abspath(os.path.join(BASE_DIR, '..', 'templates'))
|
||||
PATH_MEDIA = os.path.abspath(os.path.join(BASE_DIR, '..', 'docs'))
|
||||
|
||||
|
@ -23,19 +64,26 @@ PATH_CP = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'cp.db'))
|
|||
COMPANIES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'rfc.db'))
|
||||
DB_SAT = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'sat.db'))
|
||||
|
||||
PATH_SESSIONS = {
|
||||
'data': os.path.abspath(os.path.join(BASE_DIR, '..', 'cache', 'data')),
|
||||
'lock': os.path.abspath(os.path.join(BASE_DIR, '..', 'cache', 'lock')),
|
||||
}
|
||||
|
||||
IV = 'valores_iniciales.json'
|
||||
INIT_VALUES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', IV))
|
||||
CT = 'cancel_template.xml'
|
||||
TEMPLATE_CANCEL = os.path.abspath(os.path.join(PATH_TEMPLATES, CT))
|
||||
# ~ CT = 'cancel_template.xml'
|
||||
# ~ TEMPLATE_CANCEL = os.path.abspath(os.path.join(PATH_TEMPLATES, CT))
|
||||
|
||||
PATH_XSLT = os.path.abspath(os.path.join(BASE_DIR, '..', 'xslt'))
|
||||
PATH_BIN = os.path.abspath(os.path.join(BASE_DIR, '..', 'bin'))
|
||||
|
||||
template_lookup = TemplateLookup(directories=[PATH_TEMPLATES],
|
||||
PATH_TEMPLATES_USER = os.path.abspath(os.path.join(
|
||||
BASE_DIR, '..', 'docs', 'templates'))
|
||||
directories=[PATH_TEMPLATES, PATH_TEMPLATES_USER]
|
||||
template_lookup = TemplateLookup(directories=directories,
|
||||
input_encoding='utf-8',
|
||||
output_encoding='utf-8')
|
||||
|
||||
LOG_PATH = 'empresalibre.log'
|
||||
LOG_NAME = 'API'
|
||||
LOG_LEVEL = 'INFO'
|
||||
|
||||
|
@ -77,12 +125,29 @@ if 'win' in sys.platform:
|
|||
PATH_XMLSEC = os.path.join(PATH_BIN, 'xmlsec.exe')
|
||||
|
||||
|
||||
PRE_DEFAULT = {
|
||||
'CFDI': {'VERSION': '4.0', 'PRE': '{http://www.sat.gob.mx/cfd/4}'},
|
||||
'NOMINA': {'VERSION': '1.2', 'PRE': '{http://www.sat.gob.mx/nomina12}'},
|
||||
'PAGOS': {'VERSION': '2.0', 'PRE': '{http://www.sat.gob.mx/Pagos20}'},
|
||||
'TIBRE': {'VERSION': '1.1', 'PRE': '{http://www.sat.gob.mx/TimbreFiscalDigital}'},
|
||||
}
|
||||
|
||||
pre2 ='{http://www.sat.gob.mx/cfd/2}'
|
||||
pre3 ='{http://www.sat.gob.mx/cfd/3}'
|
||||
PRE_HISTORY = {
|
||||
'CFDI': {'2.0': pre2, '2.2': pre2,
|
||||
'3.0': pre3, '3.2': pre3, '3.3': pre3},
|
||||
'NOMINA': {'1.1': '{http://www.sat.gob.mx/nomina}'},
|
||||
'PAGOS': {'1.0': '{http://www.sat.gob.mx/Pagos}'},
|
||||
}
|
||||
|
||||
PRE = {
|
||||
'2.0': '{http://www.sat.gob.mx/cfd/2}',
|
||||
'2.2': '{http://www.sat.gob.mx/cfd/2}',
|
||||
'3.0': '{http://www.sat.gob.mx/cfd/3}',
|
||||
'3.2': '{http://www.sat.gob.mx/cfd/3}',
|
||||
'3.3': '{http://www.sat.gob.mx/cfd/3}',
|
||||
'4.0': '{http://www.sat.gob.mx/cfd/4}',
|
||||
'TIMBRE': '{http://www.sat.gob.mx/TimbreFiscalDigital}',
|
||||
'DONATARIA': '{http://www.sat.gob.mx/donat}',
|
||||
'INE': '{http://www.sat.gob.mx/ine}',
|
||||
|
@ -90,19 +155,165 @@ PRE = {
|
|||
'NOMINA': {
|
||||
'1.1': '{http://www.sat.gob.mx/nomina}',
|
||||
'1.2': '{http://www.sat.gob.mx/nomina12}',
|
||||
}
|
||||
},
|
||||
'PAGOS': {
|
||||
'1.0': '{http://www.sat.gob.mx/Pagos}',
|
||||
}
|
||||
}
|
||||
|
||||
CURRENT_CFDI = '3.3'
|
||||
DEFAULT_PASSWORD = 'blades3.3'
|
||||
# To delete
|
||||
# ~ CURRENT_CFDI = '4.0'
|
||||
# ~ CURRENT_CFDI_NOMINA = '1.2'
|
||||
|
||||
DECIMALES = 2
|
||||
DECIMALES_TAX = 4
|
||||
DECIMALES_PRECIOS = 4
|
||||
IMPUESTOS = {
|
||||
'ISR': '001',
|
||||
'IVA': '002',
|
||||
'IEPS': '003',
|
||||
'EXENTO': '000',
|
||||
'ISH': '000',
|
||||
'INSPECCION DE OBRA': '000',
|
||||
'ICIC': '000',
|
||||
'CEDULAR': '000',
|
||||
'CMIC': '000',
|
||||
'SUPERVISION': '000',
|
||||
}
|
||||
DEFAULT_SAT_PRODUCTO = '01010101'
|
||||
DEFAULT_SERIE_TICKET = 'T'
|
||||
DEFAULT_CFDIPAY = {
|
||||
'SERIE': 'FP',
|
||||
'TYPE': 'P',
|
||||
'WAYPAY': 'PPD',
|
||||
'CURRENCY': 'XXX',
|
||||
'TC': '1',
|
||||
'USED': 'CP01',
|
||||
'KEYSAT': '84111506',
|
||||
'UNITKEY': 'ACT',
|
||||
'DESCRIPTION': 'Pago',
|
||||
'TYPE_RELATION': '04',
|
||||
}
|
||||
DIR_FACTURAS = 'facturas'
|
||||
USAR_TOKEN = False
|
||||
CANCEL_SIGNATURE = False
|
||||
PUBLIC = 'Público en general'
|
||||
DEFAULT_SAT_NOMINA = {
|
||||
'SERIE': 'N',
|
||||
'FORMA_PAGO': '99',
|
||||
'USO_CFDI': 'CN01',
|
||||
'CLAVE': '84111505',
|
||||
'UNIDAD': 'ACT',
|
||||
'DESCRIPCION': 'Pago de nómina',
|
||||
}
|
||||
|
||||
API = 'https://api.empresalibre.net{}'
|
||||
|
||||
CURRENCY_MN = 'MXN'
|
||||
|
||||
# ~ v2
|
||||
CANCEL_VERSION = ('3.3', '4.0')
|
||||
CFDI_VERSIONS = CANCEL_VERSION
|
||||
|
||||
IS_MV = MV
|
||||
DB_COMPANIES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'rfc.db'))
|
||||
path_bk = os.path.join(path_docs, 'tmp')
|
||||
path_local = 'facturas'
|
||||
path_sat = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'valores_iniciales.json'))
|
||||
|
||||
EXT = {
|
||||
'CSS': 'css',
|
||||
'HTML': 'html',
|
||||
'ODS': 'ods',
|
||||
'PNG': 'png',
|
||||
'JSON': 'json',
|
||||
}
|
||||
MXN = 'MXN'
|
||||
|
||||
CARTA_PORTE = {
|
||||
'MONEDA': 'XXX',
|
||||
}
|
||||
|
||||
PATHS = {
|
||||
'STATIC': path_static,
|
||||
'CSS': path_css,
|
||||
'IMG': path_img,
|
||||
'DOCS': path_docs,
|
||||
'USER': path_user_template,
|
||||
'LOGOS': path_user_logos,
|
||||
'BK': path_bk,
|
||||
'LOCAL': path_local,
|
||||
'SAT': path_sat,
|
||||
'xslt': PATH_XSLT,
|
||||
}
|
||||
|
||||
VALUES_PDF = {
|
||||
'CANCEL': {True: 'inline', False: 'none'},
|
||||
'TYPE': {'I': 'Ingreso', 'E': 'Egreso', 'T': 'Traslado'},
|
||||
'TAX': {'001': 'ISR', '002': 'IVA', '003': 'IEPS'},
|
||||
'METHOD': {
|
||||
'PUE': 'Pago en una sola exhibición',
|
||||
'PPD': 'Pago en parcialidades o diferido',
|
||||
},
|
||||
}
|
||||
|
||||
RESICO = '626'
|
||||
|
||||
RFCS = {
|
||||
'PUBLIC': 'XAXX010101000',
|
||||
'FOREIGN': 'XEXX010101000',
|
||||
'CVD110412TF6': 'finkok',
|
||||
'SCD110105654': 'comercio',
|
||||
'AAA010101AAA': 'comercio',
|
||||
'SPR190613I52': 'comercio',
|
||||
}
|
||||
|
||||
URL = {
|
||||
'SEAFILE': 'https://seafile.cuates.net',
|
||||
}
|
||||
|
||||
DEFAULT_GLOBAL = {
|
||||
'cantidad': 1.00,
|
||||
'unidad': 'ACT',
|
||||
'descripcion': 'Venta',
|
||||
'clave_sat': '01010101',
|
||||
}
|
||||
|
||||
# ~ TEMPLATE_CANCEL = """<CancelaCFD xmlns="http://cancelacfd.sat.gob.mx">
|
||||
# ~ <Cancelacion xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RfcEmisor="{rfc}" Fecha="{fecha}">
|
||||
# ~ <Folios>
|
||||
# ~ <Folio UUID="{uuid}" Motivo="{motivo}"{folio}/>
|
||||
# ~ </Folios>
|
||||
# ~ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
# ~ <SignedInfo>
|
||||
# ~ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
|
||||
# ~ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
|
||||
# ~ <Reference URI="">
|
||||
# ~ <Transforms>
|
||||
# ~ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
|
||||
# ~ </Transforms>
|
||||
# ~ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
|
||||
# ~ <DigestValue/>
|
||||
# ~ </Reference>
|
||||
# ~ </SignedInfo>
|
||||
# ~ <SignatureValue/>
|
||||
# ~ <KeyInfo>
|
||||
# ~ <X509Data>
|
||||
# ~ <X509IssuerSerial>
|
||||
# ~ <X509IssuerName/>
|
||||
# ~ <X509SerialNumber/>
|
||||
# ~ </X509IssuerSerial>
|
||||
# ~ <X509Certificate/>
|
||||
# ~ </X509Data>
|
||||
# ~ <KeyValue>
|
||||
# ~ <RSAKeyValue>
|
||||
# ~ <Modulus/>
|
||||
# ~ <Exponent/>
|
||||
# ~ </RSAKeyValue>
|
||||
# ~ </KeyValue>
|
||||
# ~ </KeyInfo>
|
||||
# ~ </Signature>
|
||||
# ~ </Cancelacion>
|
||||
# ~ </CancelaCFD>"""
|
||||
|
||||
TEMPLATE_CANCEL = """<CancelaCFD xmlns="http://cancelacfd.sat.gob.mx"><Cancelacion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Fecha="{fecha}" RfcEmisor="{rfc}" xmlns="http://cancelacfd.sat.gob.mx"><Folios><Folio UUID="{uuid}" Motivo="{motivo}"{folio}/></Folios><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue/></Reference></SignedInfo><SignatureValue/><KeyInfo><X509Data><X509IssuerSerial><X509IssuerName/><X509SerialNumber/></X509IssuerSerial><X509Certificate/></X509Data><KeyValue><RSAKeyValue><Modulus/><Exponent/></RSAKeyValue></KeyValue></KeyInfo></Signature></Cancelacion></CancelaCFD>"""
|
||||
|
|
BIN
source/db/cp.db
BIN
source/db/sat.db
|
@ -0,0 +1,473 @@
|
|||
id key name
|
||||
1 Tu Contenedor externo
|
||||
2 X1A Tambor de acero
|
||||
3 X1B Tambor de aluminio
|
||||
4 X1D Tambor contrachapado
|
||||
5 X1F Contenedor flexible
|
||||
6 X1G Tambor de fibra
|
||||
7 X1w Tambor de madera
|
||||
8 X2C Barril de madera
|
||||
9 X3A Bidón de acero
|
||||
10 X3H Bidón de plástico
|
||||
11 X43 Bolsa de gran tamaño
|
||||
12 X44 Bolsa de plástico
|
||||
13 X4A Caja de acero
|
||||
14 X4B Caja de aluminio
|
||||
15 X4C Caja de madera natural
|
||||
16 X4D Caja de contrachapado
|
||||
17 X4F Caja de madera reconstituida
|
||||
18 X4G Caja de cartón
|
||||
19 X4H Caja de plástico
|
||||
20 X5H Bolsa de plástico tejido
|
||||
21 X5L Bolsa textil
|
||||
22 X5M Bolsa de papel
|
||||
23 X6H Recipiente de plástico, Contenedor compuesto.
|
||||
24 X6P Recipiente de vidrio, Contenedor compuesto.
|
||||
25 X7A Estuche para carro
|
||||
26 X7B Estuche de madera
|
||||
27 X8A Pallet de madera
|
||||
28 X8B Cajón de madera
|
||||
29 X8C Madera flejada
|
||||
30 XAA Contenedor intermedio para gráneles de plástico rígido
|
||||
31 XAB Contenedor de fibra
|
||||
32 XAC Contenedor de papel
|
||||
33 XAD Contenedor de madera
|
||||
34 XAE Aerosol
|
||||
35 XAF Pallet modular con collares, 80cms * 60cms
|
||||
36 XAG Pallet o empaquetado
|
||||
37 XAH Pallet, 100cms X 110cms
|
||||
38 XAI Contenedor tipo concha
|
||||
39 XAJ Cono
|
||||
40 XAL Esfera
|
||||
41 XAM Ampolleta no protegida
|
||||
42 XAP Ampolleta protegida
|
||||
43 XAT Atomizador
|
||||
44 XAV Cápsula
|
||||
45 XB4 Cinturón
|
||||
46 XBA Barril
|
||||
47 XBB Bobina
|
||||
48 XBC Cajón para botellas / Estante para botellas
|
||||
49 XBD Tablero
|
||||
50 XBE Flejado
|
||||
51 XBF Globo no protegido
|
||||
52 XBG Bolso
|
||||
53 XBH Manojo
|
||||
54 XBI Compartimiento
|
||||
55 XBJ Cubeta
|
||||
56 XBK Cesta
|
||||
57 XBL Paca comprimida
|
||||
58 XBM Cuenco
|
||||
59 XBN Paca no comprimida
|
||||
60 XBO Botella no-protegida y cilíndrica
|
||||
61 XBP Globo protegido
|
||||
62 XBQ Botella cilíndrica protegida
|
||||
63 XBR Barra
|
||||
64 XBS Botella, no-protegida en forma de bulbo
|
||||
65 XBT Rollo de tela
|
||||
66 XBU Butt
|
||||
67 XBV Botella de bulbo protegido
|
||||
68 XBW Caja para líquidos
|
||||
69 XBX Caja
|
||||
70 XBY Tablero, con fleje/ agrupados/ armados
|
||||
71 XBZ Barras, con fleje/ agrupados/ armados
|
||||
72 XCA Lata rectangular
|
||||
73 XCB Cajón para cerveza
|
||||
74 XCC Mantequera
|
||||
75 XCD Lata con mango y boquilla
|
||||
76 XCE Cesto tejido
|
||||
77 XCF Cofre
|
||||
78 XCG Contenedor tipo Jaula
|
||||
79 XCH Cajonera
|
||||
80 XCI Frasco
|
||||
81 XCJ Ataúd
|
||||
82 XCK Barrica
|
||||
83 XCL Espiral
|
||||
84 XCM Paquete de tarjetas
|
||||
85 XCN Contenedor, no especificado como equipo de transporte
|
||||
86 XCO Garrafón no protegido
|
||||
87 XCP Garrafón protegido
|
||||
88 XCQ Cartucho
|
||||
89 XCR Cajón
|
||||
90 XCS Estuche
|
||||
91 XCT Cartón
|
||||
92 XCU Vaso
|
||||
93 XCV Cubierta
|
||||
94 XCW Jaula estilo rodillo
|
||||
95 XCX Lata cilíndrica
|
||||
96 XCY Cilindro
|
||||
97 XCZ Lona
|
||||
98 XDA Cajón multicapa de plástico
|
||||
99 XDB Cajón de varias capas de madera
|
||||
100 XDC Cajón multicapa de cartón
|
||||
101 XDG Jaula, Según la clasificación de la compañía (Commonwealth Handling Equipment Pool (CHEP))
|
||||
102 XDH Caja, Según la clasificación de la compañía (CHEP), Eurobox
|
||||
103 XDI Tambor de hierro
|
||||
104 XDJ damajuana o garrafa, no protegido
|
||||
105 XDK Cajón a granel, cartón
|
||||
106 XDL Cajas de plástico
|
||||
107 XDM Cajones a granel de madera
|
||||
108 XDN Dispensador
|
||||
109 XDP damajuana o garrafa, protegido
|
||||
110 XDR Tambor
|
||||
111 XDS Bandeja de una capa sin cubierta y de plástico
|
||||
112 XDT Bandeja de una capa sin cubierta y de madera
|
||||
113 XDU Bandeja de una capa sin cubierta y poliestireno
|
||||
114 XDV Bandeja de una capa sin cubierta y de cartón
|
||||
115 XDW Bandeja de dos capas sin tapa y con bandeja de plástico
|
||||
116 XDX Bandeja de dos capas sin cubierta y de madera
|
||||
117 XDY Bandeja de dos capas sin cubierta y de cartón
|
||||
118 XEC Bolsa de plástico
|
||||
119 XED Estuche, con pallet de base
|
||||
120 XEE Estuche, con pallet base de madera
|
||||
121 XEF Estuche, con pallet base de cartón
|
||||
122 XEG Estuche, con pallet base de plástico
|
||||
123 XEH Estuche, con pallet base de metal
|
||||
124 XEI Estuche isotérmico
|
||||
125 XEN Sobre
|
||||
126 XFB Bolsa flexible
|
||||
127 XFC Cajón para fruta
|
||||
128 XFD Cajón enmarcado
|
||||
129 XFE Tanque flexible
|
||||
130 XFI Firkin
|
||||
131 XFL Matraz
|
||||
132 XFO Cajón para zapatos
|
||||
133 XFP Caja auxiliar para película fotográfica
|
||||
134 XFR Marco
|
||||
135 XFT Contenedor para alimentos
|
||||
136 XFW Carro de cama plana
|
||||
137 XFX Bolsa flexible tipo contenedor
|
||||
138 XGB Botella para gas
|
||||
139 XGI Viga
|
||||
140 XGL Contenedor tipo galón
|
||||
141 XGR Recipiente de vidrio
|
||||
142 XGU Bandeja contenedor para apilar horizontalmente objetos planos
|
||||
143 XGY Costal de Yute
|
||||
144 XGZ Vigas con correas o agrupadas
|
||||
145 XHA Cesta con mango y de plástico
|
||||
146 XHB Cesta con mango y de madera
|
||||
147 XHC Cesta con asa y de cartón
|
||||
148 XHG Hogshead
|
||||
149 XHN Gancho
|
||||
150 XHR Cesto
|
||||
151 XIA Paquete con pantalla y de madera
|
||||
152 XIB Paquete con pantalla y de cartón
|
||||
153 XIC Paquete con pantalla y de plástico
|
||||
154 XID Paquete con pantalla y de metal
|
||||
155 XIE Paquete de mostrador.
|
||||
156 XIF Envase para alimentos
|
||||
157 XIG Paquete envuelto en papel
|
||||
158 XIH Tambor de plástico
|
||||
159 XIK Paquete de cartón con los agujeros para botellas
|
||||
160 XIL Bandeja rígida con tapa y apilable (CEN TS 14482: 2002)
|
||||
161 XIN Lingote
|
||||
162 XIZ Lingotes con correas/ agrupados
|
||||
163 XJB Bolsa jumbo
|
||||
164 XJC Bidón rectangular
|
||||
165 XJG Jarra
|
||||
166 XJR Tarro
|
||||
167 XJT Bolsa de yute
|
||||
168 XJY Bidón, cilíndrico
|
||||
169 XKG Barrilete
|
||||
170 XKI Kit (Conjunto de piezas)
|
||||
171 XLE Valijas
|
||||
172 XLG Bitácora
|
||||
173 XLT Lote
|
||||
174 XLU Caja de arrastre
|
||||
175 XLV Contenedor pequeño
|
||||
176 XLZ Registros con fleje/ agrupados/ armados
|
||||
177 XMA Cajón metálico
|
||||
178 XMB Múltiplo de bolsas
|
||||
179 XMC Cajón para leche
|
||||
180 XME Contenedor de metal
|
||||
181 XMR Recipiente de metal
|
||||
182 XMS Saco milti-pared
|
||||
183 XMT Tapete
|
||||
184 XMW Contenedor envuelto en plástico
|
||||
185 XMX Caja pequeña de cerillos
|
||||
186 XNA No disponible
|
||||
187 XNE Sin empaque o no empaquetado
|
||||
188 XNF Sin empaque o no empaquetado, unidad simple
|
||||
189 XNG Sin empaque o no empaquetado, unidades múltiples
|
||||
190 XNS Caja nido
|
||||
191 XNT Red
|
||||
192 XNU Red de plástico con tubo
|
||||
193 XNV Red textil con tubo
|
||||
194 XOA Pallet, Según la clasificación de la compañía (Commonwealth Handling Equipment Pool (CHEP) 40 cm x 60 cm
|
||||
195 XOB Pallet, Según la clasificación de la compañía (Commonwealth Handling Equipment Pool (CHEP) 80 cm x 120 cm
|
||||
196 XOC Pallet, Según la clasificación de la compañía (Commonwealth Handling Equipment Pool (CHEP) 100 cm x 120 cm
|
||||
197 XOD Pallet, AS 4068-1993
|
||||
198 XOE Pallet, ISO T11
|
||||
199 XOF Plataforma, peso o dimensión no especificada
|
||||
200 XOK Bloque
|
||||
201 XOT Octabin
|
||||
202 XP2 Charola
|
||||
203 XPA Cajetilla
|
||||
204 XPB Pallet, Caja combinada y abierta con caja y pallet.
|
||||
205 XPC Paquete postal
|
||||
206 XPD Pallet modular con collares (80cms * 100cms)
|
||||
207 XPE Pallet modular con collares (80cms * 120cms)
|
||||
208 XPF Corral
|
||||
209 XPG Placa
|
||||
210 XPH Cantaro
|
||||
211 XPI Pleca
|
||||
212 XPJ Canastilla
|
||||
213 XPK Paquete
|
||||
214 XPL Balde
|
||||
215 XPN Tablón
|
||||
216 XPO Bolsa pequeña
|
||||
217 XPR Contenedor de plástico
|
||||
218 XPT Maceta
|
||||
219 XPU Cacerola
|
||||
220 XPV Tubos, con fleje/ agrupados/ armados
|
||||
221 XPX Pallet
|
||||
222 XPY Placas con fleje/ agrupados/ armados
|
||||
223 XPZ Tablones con fleje/ agrupados/ armados
|
||||
224 XQA Tambor de acero con cabeza no desmontable
|
||||
225 XQB Tambor de acero con cabeza extraíble
|
||||
226 XQC Tambor de aluminio con cabeza no extraíble
|
||||
227 XQD Tambor de aluminio con cabeza extraíble
|
||||
228 XQF Tambor, plástico con cabeza no desmontable
|
||||
229 XQG Tambor, plástico, cabeza extraíble
|
||||
230 XQH Barril de madera con tapón
|
||||
231 XQJ Barril de madera con cabeza desprendible
|
||||
232 XQK Bidón de acero con cabeza no desmontable
|
||||
233 XQL Bidón de acero con cabeza desmontable
|
||||
234 XQM Bidón de plástico con cabeza no desmontable
|
||||
235 XQN Bidón de plástico con cabeza extraíble
|
||||
236 XQP Caja de madera natural estándar
|
||||
237 XQQ Caja de madera natural con muros a prueba de filtraciones
|
||||
238 XQR Caja de plástico expandida
|
||||
239 XQS Caja de plástico sólida
|
||||
240 XRD Rod
|
||||
241 XRG Anillo
|
||||
242 XRJ Estante, Perchero para ropa
|
||||
243 XRK Estante
|
||||
244 XRL Carrete
|
||||
245 XRO Rollo
|
||||
246 XRT Red Roja
|
||||
247 XRZ Varillas con fleje/ agrupados/ armados
|
||||
248 XSA Saco
|
||||
249 XSB Losa
|
||||
250 XSC Cajón poco profundo
|
||||
251 XSD Huso
|
||||
252 XSE Baúl
|
||||
253 XSH Bolsa pequeña hermética
|
||||
254 XSI Patín
|
||||
255 XSK Carcasa esqueleto
|
||||
256 XSL Hoja de deslizamiento
|
||||
257 XSM Hoja de metal
|
||||
258 XSO Carrete pequeño
|
||||
259 XSP Hoja de empaque de plástico
|
||||
260 XSS Cajón de acero
|
||||
261 XSU Maleta
|
||||
262 XSV Sobre de acero
|
||||
263 XSW Envoltorio
|
||||
264 XSY Manga
|
||||
265 XSZ Hojas con fleje/ agrupados/ armados
|
||||
266 XT1 Tableta
|
||||
267 XTB Tina
|
||||
268 XTC Caja para té
|
||||
269 XTD Tubo plegable
|
||||
270 XTG Contenedor de tanque genérico
|
||||
271 XTI Tierce
|
||||
272 XTK Tanque rectangular
|
||||
273 XTL Tina con tapa
|
||||
274 XTN Hojalata
|
||||
275 XTO Tonel
|
||||
276 XTR Maletero
|
||||
277 XTS Estructura
|
||||
278 XTT Bolsa de mano
|
||||
279 XTU Tubo
|
||||
280 XTV Tubo con boquilla
|
||||
281 XTW Pallet tricapa
|
||||
282 XTY Tanque cilíndrico
|
||||
283 XTZ Tubos con fleje/ agrupados/ armados
|
||||
284 XUC Sin empaque
|
||||
285 XUN Unidad
|
||||
286 XVA Tanque
|
||||
287 XVG Tanque de gas (a 1,031 mbar y 15° C)
|
||||
288 XVI Frasco pequeño
|
||||
289 XVK Paquete transportable
|
||||
290 XVL Contenedor para líquidos a granel
|
||||
291 XVN Vehículo
|
||||
292 XVO "Contenedor para sólido de partículas grandes a granel (""nódulos"")"
|
||||
293 XVP Envasado al vacío
|
||||
294 XVQ Tanque para Gas licuado (a temperatura / presión anormal)
|
||||
295 XVR Contenedor para sólidos de partículas granulares a granel (Granos)
|
||||
296 XVS Contenedor de chatarra a granel
|
||||
297 XVY "Contenedor para sólido de partículas finas a granel (""polvos"")"
|
||||
298 XWA Contenedor de granel intermedio
|
||||
299 XWB Botella de mimbre
|
||||
300 XWC Contenedor intermedio para gráneles y de acero
|
||||
301 XWD Contenedor intermedio para gráneles y de aluminio
|
||||
302 XWF Contenedor intermedio para gráneles y de metal
|
||||
303 XWG Contenedor intermedio para gráneles y de acero presurizado menor a 10 kpa
|
||||
304 XWH Contenedor intermedio para gráneles y de aluminio, presurizado menor a 10 kpa
|
||||
305 XWJ Contenedor intermedio para gráneles y de metal con una presión de 10 kpa
|
||||
306 XWK Contenedor intermedio para gráneles y de acero para líquido
|
||||
307 XWL Contenedor intermedio para gráneles y de aluminio para líquido
|
||||
308 XWM Contenedor intermedio para gráneles y de metal para líquido
|
||||
309 XWN Contenedor intermedio para gráneles con tejido plástico sin capa con revestimiento
|
||||
310 XWP Contenedor intermedio para gráneles con tejido plástico y recubierto
|
||||
311 XWQ Contenedor intermedio para gráneles con tejido plástico con revestimiento
|
||||
312 XWR Contenedor intermedio para gráneles con tejido plástico, revestido y con forro
|
||||
313 XWS Contenedor intermedio para gráneles con película de plástico
|
||||
314 XWT Contenedor intermedio para gráneles textil sin capa / forro
|
||||
315 XWU Contenedor intermedio para gráneles de madera natural con forro interior
|
||||
316 XWV Contenedor intermedio para gráneles textil recubierto
|
||||
317 XWW Contenedor intermedio para gráneles textil con revestimiento
|
||||
318 XWX Contenedor intermedio para gráneles textil recubierto y con forro
|
||||
319 XWY Contenedor intermedio para gráneles contrachapado con revestimiento interior
|
||||
320 XWZ Contenedor intermedio para gráneles de madera reconstituida con revestimiento interior
|
||||
321 XXA Bolsa de tejido plástico, sin abrigo interior ni forro
|
||||
322 XXB Bolsa de tejido plástico a prueba de filtraciones
|
||||
323 XXC Bolsa de tejido plástico resistente al agua
|
||||
324 XXD Bolsa con película de plástico
|
||||
325 XXF Bolsa textil sin capa ni forro interior
|
||||
326 XXG Bolsa textil a prueba de filtraciones
|
||||
327 XXH Bolsa textil resistente al agua
|
||||
328 XXJ Bolsa de papel multi-pared
|
||||
329 XXK Bolsa de papel multi-pared, resistente al agua
|
||||
330 XYA Empaque compuesto, recipiente de plástico en tambor de acero
|
||||
331 XYB Empaque compuesto, recipiente de plástico en cajas de acero
|
||||
332 XYC Empaque compuesto, recipiente de plástico en tambor de aluminio
|
||||
333 XYD Empaque compuesto, recipiente de plástico en cajón de aluminio
|
||||
334 XYF Empaque compuesto, recipiente de plástico en caja de madera
|
||||
335 XYG Empaque compuesto, recipiente de plástico en tambor de madera contrachapada
|
||||
336 XYH Empaque compuesto, recipiente de plástico en caja de madera contrachapada
|
||||
337 XYJ Empaque compuesto, recipiente de plástico en tambor de fibra
|
||||
338 XYK Empaque compuesto, recipiente de plástico en caja de cartón
|
||||
339 XYL Empaque compuesto, recipiente de plástico en el tambor de plástico
|
||||
340 XYM Empaque compuesto, recipiente de plástico en caja de plástico sólido
|
||||
341 XYN Empaque compuesto, receptáculo de vidrio en tambor de acero
|
||||
342 XYP Empaque compuesto, receptáculo de vidrio en caja de cajas de acero
|
||||
343 XYQ Empaque compuesto, recipiente de vidrio en tambor de aluminio
|
||||
344 XYR Empaque compuesto, receptáculo de vidrio en caja de aluminio
|
||||
345 XYS Empaque compuesto, recipiente de vidrio en caja de madera
|
||||
346 XYT Empaque compuesto, recipiente de vidrio en tambor de madera contrachapada
|
||||
347 Xyv Empaque compuesto, recipiente de vidrio en el cesto de mimbre
|
||||
348 XYW Empaque compuesto, recipiente de vidrio en tambor de fibra
|
||||
349 XYX Empaque compuesto, recipiente de vidrio en caja de cartón
|
||||
350 XYY Empaque compuesto, recipiente de vidrio en paquete de plástico expandible
|
||||
351 XYZ Empaque compuesto, recipiente de vidrio en paquete de plástico sólido
|
||||
352 XZA Contenedor de granel intermedio, papel, multi-pared
|
||||
353 XZB Bolsa grande
|
||||
354 XZC Contenedor intermedio para gráneles de papel, multi-pared y resistente al agua
|
||||
355 XZD Contenedor intermedio para gráneles de plástico rígido, con equipo estructural para sólidos
|
||||
356 XZF Contenedor intermedio para gráneles de plástico rígido, autoportante para sólidos
|
||||
357 XZG Contenedor intermedio para gráneles de plástico rígido, con equipo estructural, presurizado
|
||||
358 XZH Contenedor intermedio para gráneles de plástico rígido, autoportante y presurizado
|
||||
359 XZJ Contenedor intermedio para gráneles de plástico rígido, con equipo estructural para líquidos
|
||||
360 XZK Contenedor intermedio para gráneles de plástico rígido, autoportante, líquidos
|
||||
361 XZL Contenedor intermedio para gráneles, compuesto y de plástico rígido, sólidos
|
||||
362 XZM Contenedor intermedio para gráneles, compuesto y de plástico flexible, sólidos
|
||||
363 XZN Contenedor intermedio para gráneles, compuesto y de plástico rígido, presurizado
|
||||
364 XZP Contenedor intermedio para gráneles, compuesto y de plástico flexible, presurizado
|
||||
365 XZQ Contenedor intermedio para gráneles, compuesto y de plástico rígido, líquidos
|
||||
366 XZR Contenedor intermedio para gráneles, compuesto y de plástico flexible para líquidos
|
||||
367 XZS Contenedor intermedio para gráneles, compuesto
|
||||
368 XZT Contenedor intermedio para gráneles con tablero de fibras
|
||||
369 XZU Contenedor intermedio para gráneles flexible
|
||||
370 XZV Contenedor intermedio para gráneles de metal, distinto del acero
|
||||
371 XZW Contenedor intermedio para gráneles, de madera natural
|
||||
372 XZX Contenedor intermedio para gráneles, de contrachapado
|
||||
373 XZY Contenedor intermedio para gráneles, de madera reconstituida
|
||||
374 KGM Kilogramo
|
||||
375 MC Microgramo
|
||||
376 DJ Decagramo
|
||||
377 DG Decigramo
|
||||
378 GRM Gramo
|
||||
379 CGM Centigramo
|
||||
380 TNE Tonelada (tonelada métrica)
|
||||
381 DTN Decitonelada métrica
|
||||
382 MGM Miligramo
|
||||
383 HGM Hectogramo
|
||||
384 KTN Kilotonelada Métrica
|
||||
385 2U Megagramo
|
||||
386 LBR Libra
|
||||
387 GRN Grano
|
||||
388 ONZ Onza (avoirdupois)
|
||||
389 CWI Hundredweight
|
||||
390 CWA Hundred pound
|
||||
391 LTN Tonelada (UK) o tonelada larga (estados unidos)
|
||||
392 STI Estone (UK)
|
||||
393 STN Tonelada (estados unidos) o tonelada corta (UK y estados unidos)
|
||||
394 APZ Onza troy u onza farmacéutica
|
||||
395 F13 Slug
|
||||
396 K64 Libra (avoirdupois) por grado fahrenheit
|
||||
397 L69 Tonelada por kelvin
|
||||
398 L87 Tonelada corta por grado fahrenheit
|
||||
399 M85 Tonelada, ensayo
|
||||
400 M86 Libra Alemana
|
||||
401 J33 Microgramo por kilogramo
|
||||
402 L32 Nanogramo por kilogramo
|
||||
403 NA Miligramo por kilogramo
|
||||
404 M29 Kilogramo por kilogramo
|
||||
405 M91 Libra por libra
|
||||
406 Q29 Microgramo por hectogramo
|
||||
407 MTQ Metro cúbico
|
||||
408 MAL Megalitro
|
||||
409 LTR Litro
|
||||
410 MMQ Milímetro cúbico
|
||||
411 CMQ Centímetro cúbico
|
||||
412 DMQ Decímetro cúbico
|
||||
413 MLT Mililitro
|
||||
414 HLT Hectolitro
|
||||
415 CLT Centilitro
|
||||
416 DMA Decámetro cúbico
|
||||
417 H19 Hectómetro cúbico
|
||||
418 H20 Kilómetro cúbico
|
||||
419 M71 Metro cúbico por pascal (joules)
|
||||
420 DLT Decilitro
|
||||
421 4G Microlitro
|
||||
422 K6 Kilolitro
|
||||
423 A44 Decalitro
|
||||
424 G94 Centímetro cúbico por bar
|
||||
425 G95 Litro por bar
|
||||
426 G96 Metro cúbico por bar
|
||||
427 G97 Mililitro por bar
|
||||
428 5I Pies cúbicos estándar
|
||||
429 INQ Pulgada cúbica
|
||||
430 FTQ Pie cúbico
|
||||
431 YDQ Yarda cúbica
|
||||
432 GLI Galón (UK)
|
||||
433 GLL Galón (EUA)
|
||||
434 PT Pinta (US)
|
||||
435 PTI Pint (uk)
|
||||
436 QTI Cuarto (UK)
|
||||
437 PTL Pinta líquida (estados unidos)
|
||||
438 QTL Cuarto de líquido (estadis unidos)
|
||||
439 PTD Pinta seca (estados unidos)
|
||||
440 OZI Onza líquida (UK)
|
||||
441 QT Cuarto (EUA)
|
||||
442 J57 Barril (uk petróleo)
|
||||
443 K21 Pie cúbico por grado fahrenheit
|
||||
444 K23 Pie cúbico por psi (libra por pulgada cuadrada)
|
||||
445 L43 Peck (UK)
|
||||
446 L61 Pinta (US seco)
|
||||
447 L62 Cuarto de galón (seco de los EUA)
|
||||
448 L84 Tonelada (flota UK)
|
||||
449 L86 Tonelada (flota estados unidos)
|
||||
450 M11 Yarda cúbica por grado fahrenheit
|
||||
451 M14 Yarda cúbica por psi (libra por pulgada cuadrada)
|
||||
452 OZA Onza líquida (estados unidos)
|
||||
453 BUI Bushel (UK)
|
||||
454 BUA Bushel (EUA)
|
||||
455 BLL Barril (EUA)
|
||||
456 BLD Barril seco (EUA)
|
||||
457 GLD Galón seco (EUA)
|
||||
458 QTD Cuarto seco (estados unidos)
|
||||
459 G26 Estere
|
||||
460 G21 Taza (unidad de volumen)
|
||||
461 G24 Cucharada (estados unidos)
|
||||
462 G25 Cucharilla (estados unidos)
|
||||
463 G23 Peck
|
||||
464 M67 Acre-pie
|
||||
465 M68 Cordón
|
||||
466 M69 Milla cúbica (reino unido)
|
||||
467 M70 Unidad tradicional de capacidad de carga
|
||||
468 Q32 Femtolitro
|
||||
469 Q33 Picolitro
|
||||
470 Q34 Nanolitro
|
||||
471 NM3 Metro cúbico normalizado
|
||||
472 SM3 Metro cúbico estándar
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
@license
|
||||
webix UI v.5.0.0
|
||||
webix UI v.5.4.3
|
||||
This software is covered by Webix Commercial License.
|
||||
Usage without proper license is prohibited.
|
||||
(c) XB Software Ltd.
|
||||
|
@ -9,12 +9,12 @@ Usage without proper license is prohibited.
|
|||
.webix_view.webix_form{background-color:#fff}
|
||||
body{-webkit-tap-highlight-color:transparent!important}
|
||||
.webix_abslayout{position:relative}
|
||||
.webix_abslayout>.webix_view{position:absolute}
|
||||
.webix_abslayout>.webix_view{position:absolute!important}
|
||||
.webix_layout_space,.webix_layout_wide{background-color:#ebebeb}
|
||||
.webix_layout_accordion,.webix_layout_clean,.webix_layout_line,.webix_multiview{background:0 0}
|
||||
.webix_overlay{width:100%;height:100%;position:absolute;z-index:10;text-align:center;padding-top:10px}
|
||||
.webix_view>.webix_disabled{width:100%;height:100%;position:absolute;top:0;left:0;background-color:#ddd;opacity:.4;filter:alpha(opacity=40);z-index:1}
|
||||
.webix_disabled_view{overflow:hidden!important}
|
||||
.webix_disabled_view{overflow:hidden!important;position:relative}
|
||||
body.webix_full_screen{margin:0;padding:0;overflow:hidden}
|
||||
.webix_noselect,.webix_noselect div{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.webix_selectable{-moz-user-select:text;-webkit-user-select:text;user-select:text}
|
||||
|
@ -25,38 +25,38 @@ body.webix_full_screen{margin:0;padding:0;overflow:hidden}
|
|||
.webix_section>.webix_template{padding:0 8px;background-color:#fff;display:inline}
|
||||
.webix_layout_space>.webix_section>.webix_template,.webix_layout_wide>.webix_section>.webix_template{padding:0 8px;background-color:#ebebeb}
|
||||
.webix_layout_clean>.webix_section>.webix_template,.webix_layout_line>.webix_section>.webix_template{padding:0 8px;background-color:#fff}
|
||||
.webix_header>div{padding-left:10px;font-family:Helvetica,Verdana;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);line-height:32px;line-height:34px;padding-top:0;padding-bottom:0}
|
||||
.webix_header>div{padding-left:10px;font-family:Helvetica,Verdana;color:#1e2022;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;line-height:32px;line-height:34px;padding-top:0;padding-bottom:0}
|
||||
.webix_header>div .webix_el_label,.webix_header>div .webix_inp_label{color:#1e2022}
|
||||
.webix_spacer{background:0 0}
|
||||
.webix_view_animate{position:relative;width:100%;height:100%}
|
||||
x\:ui{display:none}
|
||||
.webix_flexlayout{display:flex!important;flex-wrap:wrap;flex-direction:row;overflow:hidden;box-sizing:border-box}
|
||||
.webix_view.webix_flexlayout{display:flex!important;flex-wrap:wrap;flex-direction:row;overflow:hidden;box-sizing:border-box}
|
||||
.webix_flexlayout>div{display:block!important}
|
||||
.webix_view_align{background:0 0}
|
||||
.webix_view a.webix_list_item,.webix_view div,.webix_view span{outline:0}
|
||||
.webix_view a.webix_list_item:focus,.webix_view div:focus,.webix_view span:focus,.webix_view.webix_window:focus{outline:#727981 dotted 1px}
|
||||
.webix_view a.webix_list_item:focus,.webix_view div:focus,.webix_view span:focus,.webix_view.webix_window:focus{outline-color:#727981;outline-style:dotted;outline-width:1px}
|
||||
.webix_view div.webix_inp_static:focus,button,input,select,textarea{outline:0}
|
||||
.webix_resize_area{position:absolute;top:0;left:0;width:100%;height:100%}
|
||||
.webix_resize_handle_x .webix_handle_content,.webix_resize_handle_y .webix_handle_content{width:100%;height:100%;background:rgba(100,100,100,.1);border:1px dotted #9fa5aa}
|
||||
.webix_resize_handle_x{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:e-resize;width:1px;height:100%;position:absolute;z-index:2;top:0}
|
||||
.webix_resize_handle_x{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:ew-resize;width:1px;height:100%;position:absolute;z-index:2;top:0}
|
||||
.webix_resize_handle_x .webix_handle_content{border-width:0 1px}
|
||||
.webix_resize_origin_x{cursor:e-resize;width:3px;height:100%;position:absolute;z-index:2;top:0}
|
||||
.webix_resize_handle_y{cursor:n-resize;height:1px;width:100%;position:absolute;z-index:2;left:0}
|
||||
.webix_resize_origin_x{cursor:ew-resize;width:3px;height:100%;position:absolute;z-index:2;top:0}
|
||||
.webix_resize_handle_y{cursor:ns-resize;height:1px;width:100%;position:absolute;z-index:2;left:0}
|
||||
.webix_resize_handle_y .webix_handle_content{border-width:1px 0}
|
||||
.webix_resize_origin_y{cursor:n-resize;height:3px;width:100%;position:absolute;z-index:2;left:0}
|
||||
.webix_resize_origin_y{cursor:ns-resize;height:3px;width:100%;position:absolute;z-index:2;left:0}
|
||||
.webix_resizer.webix_disabled_view{cursor:default}
|
||||
.webix_resizer_vy{cursor:n-resize;margin-top:0!important;border:0!important;padding:0!important;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAADAQMAAABCowZuAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA9JREFUCB1jXMUABoxAGgAJaAFXPIkJqAAAAABJRU5ErkJggg==) center center no-repeat}
|
||||
.webix_resizer_vx{cursor:e-resize;margin-left:0!important;border:0!important;padding:0!important;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAXAQMAAAD0oWdxAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA5JREFUeF5jWMDAQDwGAKyuB4FpGQdzAAAAAElFTkSuQmCC) center center no-repeat}
|
||||
.webix_resizer_y{cursor:n-resize;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAADAQMAAABCowZuAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA9JREFUCB1jXMUABoxAGgAJaAFXPIkJqAAAAABJRU5ErkJggg==) center center no-repeat #fff}
|
||||
.webix_resizer_x{cursor:e-resize;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAXAQMAAAD0oWdxAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA5JREFUeF5jWMDAQDwGAKyuB4FpGQdzAAAAAElFTkSuQmCC) center center no-repeat #fff}
|
||||
.webix_resizer_vy{cursor:ns-resize;margin-top:0!important;border:0!important;padding:0!important;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAADAQMAAABCowZuAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA9JREFUCB1jXMUABoxAGgAJaAFXPIkJqAAAAABJRU5ErkJggg==) no-repeat center center}
|
||||
.webix_resizer_vx{cursor:ew-resize;margin-left:0!important;border:0!important;padding:0!important;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAXAQMAAAD0oWdxAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA5JREFUeF5jWMDAQDwGAKyuB4FpGQdzAAAAAElFTkSuQmCC) no-repeat center center}
|
||||
.webix_resizer_y{cursor:ns-resize;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAADAQMAAABCowZuAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA9JREFUCB1jXMUABoxAGgAJaAFXPIkJqAAAAABJRU5ErkJggg==) no-repeat center center;background-color:#fff}
|
||||
.webix_resizer_x{cursor:ew-resize;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAXAQMAAAD0oWdxAAAABlBMVEUAAACkvtSA7tmIAAAAAXRSTlMAQObYZgAAAA5JREFUeF5jWMDAQDwGAKyuB4FpGQdzAAAAAElFTkSuQmCC) no-repeat center center;background-color:#fff}
|
||||
.webix_accordionitem_body{position:relative}
|
||||
.webix_accordionitem_header{border-bottom:1px solid #a4bed4;position:relative;z-index:2;font-family:Helvetica,Verdana;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);line-height:32px;cursor:pointer;overflow:hidden}
|
||||
.webix_accordionitem_header{border-bottom:1px solid #a4bed4;position:relative;z-index:2;font-family:Helvetica,Verdana;color:#1e2022;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;line-height:32px;cursor:pointer;overflow:hidden}
|
||||
.webix_accordionitem_header .webix_el_label,.webix_accordionitem_header .webix_inp_label{color:#1e2022}
|
||||
.webix_ie.horizontal>.webix_accordionitem_header.collapsed{-ms-writing-mode:tb-lr}
|
||||
.webix_ie.horizontal>.webix_accordionitem_header.collapsed .webix_accordionitem_label{padding-left:0;padding-top:10px}
|
||||
.webix_ie.horizontal>.webix_accordionitem_header.collapsed .webix_accordionitem_button{margin:0}
|
||||
.webix_accordionitem_label{height:100%;padding-left:10px}
|
||||
.webix_accordionitem_button{float:right;position:relative;height:11px;width:11px;margin:14px}
|
||||
.webix_accordionitem_button{float:right;position:relative;height:11px;width:11px;margin:14px 14px}
|
||||
.webix_carousel{position:relative}
|
||||
.webix_nav_panel{bottom:15px;height:auto;line-height:8px;overflow:hidden;position:absolute;text-align:center}
|
||||
.webix_nav_item{display:inline-block;height:8px;padding:6px 5px 6px 4px;width:8px;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}
|
||||
|
@ -89,10 +89,10 @@ x\:ui{display:none}
|
|||
.webix_dark .webix_nav_button_side.webix_nav_button_next .webix_nav_button_inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAiCAYAAACwaJKDAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gcdCSE1IU5u4gAAAW1JREFUSMet1rtOwzAUgOG/5jbBwsQD8BAwIAa2TggegjmRgELbuFeo1GRlQEJMMDN264CUiYdgg0dolzIkFUEk9nHSbLGtT76cc+xaMA53gUegDnwCgfa9Vyp8CngCToFNYB940WF0WRWt57SPqsAK+C7oG+kwuiqLdg3992Xgtelk8jGN4w3gqGDMyTSOZ8eHB+8uM0X7XhMYGMbd6TC6dkIzcH8VsMr+aN9rCeCGEyqEhzZY5TWmcM8C3zihKdy2wIMiWJmWURZWtk1P4a4FvnVCUziwwP0srKQBLYSbALXFYuGU1zqMNBAYhrRUiSI0s/RvKcdZNoChcQt8Tz5TKSg/fQdQFqdJcJvAXha0Z1QCDixgW577drCbBxZXKRkYyOtpkm6lwf+VPwH7VcC/d5Qd7EjA39s0KQQ2UIvvfbZ3zoEHU2Rp3+u4vlDGqwSX6N4qwSX6ltMelAUB1oELYA6cAV/poTxXeZ/+AOFqn1e/Gh7yAAAAAElFTkSuQmCC)}
|
||||
.webix_list_item{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:2px 10px;line-height:23px;cursor:pointer;border-bottom:1px solid #ebebeb;text-align:left}
|
||||
.webix_list_item.webix_invalid{background-color:#fee}
|
||||
.webix_list_item.webix_selected{color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_list_item.webix_selected{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_list .webix_list_item.webix_selected{border-bottom:1px solid #ffd47b;box-shadow:0 1px #ffe3a9 inset;padding:2px 10px}
|
||||
.webix_group{position:relative}
|
||||
.webix_group_back,.webix_group_back.webix_selected{position:relative;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webix_group_back,.webix_group_back.webix_selected{position:relative;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_arrow_icon{position:absolute;top:50%;bottom:50%;margin-top:-12px;right:15px;width:9px;height:22px;line-height:22px;color:#1e2022;font-size:18px;font-family:FontAwesome}
|
||||
.webix_arrow_icon:before{content:'\f105'}
|
||||
.webix_group_back{padding-left:29px}
|
||||
|
@ -103,18 +103,19 @@ x\:ui{display:none}
|
|||
.webix_unit_header{padding:0 10px;line-height:19px;text-align:left;background-color:#d6e8ff}
|
||||
.webix_list-x .webix_list_item{display:inline-block;vertical-align:top;border-right:1px solid #ebebeb;border-bottom:none}
|
||||
.webix_list-x .webix_list_item.webix_selected{border-right:1px solid #ffd47b;border-left:1px solid #ffd47b;padding-left:9px}
|
||||
.webix_list-x .webix_scroll_cont{display:inline}
|
||||
.webix_list-x .webix_scroll_cont{display:inline-block;overflow:visible}
|
||||
.webix_view.webix_list-x{white-space:nowrap}
|
||||
.webix_list_item.webix_disabled{color:#8b949e}
|
||||
.webix_list_item.webix_disabled .webix_submenu_icon{visibility:hidden}
|
||||
.webix_view.webix_pager{padding:2px 0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:transparent}
|
||||
.webix_pager_item,.webix_pager_item_selected{padding:0 6px;text-align:center;height:100%;width:32px;border:1px solid #a4bed4;margin:0 2px;cursor:pointer;background-color:#fff;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana;font-size:13px}
|
||||
.webix_pager_item,.webix_pager_item_selected{padding:0 6px;text-align:center;height:100%;width:auto;min-width:32px;border:1px solid #a4bed4;margin:0 2px;cursor:pointer;background-color:#fff;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana;font-size:13px}
|
||||
.webix_pager_item_selected{cursor:default;background-color:#ffdb8f;border:1px solid #ffd47b}
|
||||
.webix_animation .webix_ss_header{position:relative;z-index:10}
|
||||
.webix_animation .webix_ss_footer,.webix_animation .webix_vscroll_x{position:absolute;bottom:0;z-index:10}
|
||||
.webix_allow_selection{-moz-user-select:text;-webkit-user-select:text;user-select:text}
|
||||
.webix_dataview_item{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:2px 10px;line-height:23px;cursor:pointer;border-bottom:1px solid #ebebeb;text-align:left;border-right:1px solid #ebebeb}
|
||||
.webix_dataview_item.webix_selected{color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f);border-bottom:1px solid #ffd47b;border-right:1px solid #ffd47b}
|
||||
.webix_dataview_item.webix_selected{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f);border-bottom:1px solid #ffd47b;border-right:1px solid #ffd47b}
|
||||
.webix_dataview_item.webix_invalid{background-color:#fee}
|
||||
.webix_chart{position:relative;font-family:Helvetica,Verdana;font-size:13px;color:#1e2022;overflow:hidden;z-index:1}
|
||||
.webix_chart canvas{position:absolute}
|
||||
.webix_canvas_text{position:absolute;text-align:center;overflow:hidden;white-space:nowrap;font-size:12px;z-index:100}
|
||||
|
@ -155,11 +156,11 @@ x\:ui{display:none}
|
|||
.webix_dt_editor select{padding-right:0;padding-left:5px}
|
||||
.webix_clipbuffer{width:2000px;height:1px;padding:0;margin:0;border:0;left:0;top:0;white-space:pre-wrap;position:fixed;filter:alpha(opacity=0);opacity:0;pointer-events:none;cursor:default}
|
||||
.webix_message_area{position:fixed;right:5px;width:250px;z-index:1000}
|
||||
.webix_info{min-width:120px;font-family:Tahoma,Arial;z-index:10000;overflow:hidden;margin:5px 5px 10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}
|
||||
.webix_info{min-width:120px;font-family:Tahoma,Arial;z-index:10000;overflow:hidden;margin:5px;margin-bottom:10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}
|
||||
.webix_no_transition{-webkit-transition:none;-moz-transition:none;transition:none}
|
||||
.webix_info.hidden{height:0;min-height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:0;margin-bottom:0;overflow:hidden}
|
||||
.webix_modal_box{overflow:hidden;display:inline-block;min-width:250px;width:250px;text-align:center;position:fixed;background-color:#fff;box-shadow:0 3px 6px #c8c8c8;font-family:Helvetica,Verdana;z-index:20000;border-radius:0;outline:0}
|
||||
.webix_popup_title{border-top-left-radius:-1px;border-top-right-radius:-1px;border-width:0}
|
||||
.webix_popup_title{border-top-left-radius:-1px;border-top-right-radius:-1px;border-width:0;background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%)}
|
||||
.webix_button,.webix_info,.webix_popup_button{cursor:pointer}
|
||||
.webix_popup_text{overflow:hidden}
|
||||
.webix_popup_controls{border-radius:6px;padding:5px 10px 10px}
|
||||
|
@ -171,12 +172,12 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_alert_error .webix_popup_title,.webix_confirm_error .webix_popup_title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAIAAAArRUU2AAAATklEQVR4nIWLuw2AMBBDjVuQiBT2oWbRDATrnB0KQOJoqPzRe3BrHI6dcBASYREKovtK6/6DsDOX+stN+3H1YX9ciRgnYq5EWYhS2dftBIuLT4JyIrPCAAAAAElFTkSuQmCC)}
|
||||
.webix_alert_error,.webix_confirm_error{border:1px solid red}
|
||||
.webix_button,.webix_popup_button{border:1px solid #a4bed4}
|
||||
.webix_button input,.webix_popup_button div{font-size:13px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);height:28px;line-height:28px}
|
||||
.webix_popup_button.confirm div{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webix_button input,.webix_popup_button div{font-size:13px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);height:28px;line-height:28px}
|
||||
.webix_popup_button.confirm div{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_popup_title{color:#fff;height:40px;line-height:40px}
|
||||
.webix_popup_text{margin:0 0 5px;padding-top:25px;font-size:13px;color:#1e2022;min-height:60px}
|
||||
.webix_popup_text{margin:0 0 5px 0;padding-top:25px;font-size:13px;color:#1e2022;min-height:60px}
|
||||
.webix_error,.webix_info{font-size:13px;color:#333;box-shadow:0 0 10px #888;padding:0;background-color:#FFF;border-radius:3px;border:1px solid #fff}
|
||||
.webix_info div{padding:5px 10px;background-color:#fff;border-radius:3px;border:1px solid #B8B8B8}
|
||||
.webix_info div{padding:5px 10px 5px 10px;background-color:#fff;border-radius:3px;border:1px solid #B8B8B8}
|
||||
.webix_error{background-color:#d81b1b;border:1px solid #ff3c3c;box-shadow:0 0 10px #000}
|
||||
.webix_error div{background-color:#d81b1b;border:1px solid #940000;color:#FFF}
|
||||
.webix_drag_zone{position:absolute;box-shadow:1px 1px 5px #a4bed4;background-color:#fff;font-family:Helvetica,Verdana;font-size:13px;color:#1e2022;pointer-events:none}
|
||||
|
@ -201,13 +202,13 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_block_selection,.webix_cell,.webix_hcell,.webix_ss_footer td,.webix_ss_header td,.webix_table_cell,.webix_view.webix_table_cell{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_block_selection{position:absolute}
|
||||
.webix_ss_sort_asc,.webix_ss_sort_desc{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.webix_hcell.webix_ss_filter{padding:2px 5px}
|
||||
.webix_hcell.webix_ss_filter{padding:2px 5px 2px 5px}
|
||||
.webix_ss_filter input,.webix_ss_filter select{width:100%;font-size:inherit;color:#1e2022!important;height:30px;margin-top:-2px;padding:0 3px;vertical-align:top;border:1px solid #a4bed4;line-height:30px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana}
|
||||
.webix_richfilter{margin-top:1px;line-height:30px}
|
||||
.webix_ss_filter select{padding:3px}
|
||||
.webix_dd_drag_column,.webix_ss_header,.webix_ss_header TD,.webix_ss_vscroll_header{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webix_dd_drag_column,.webix_ss_header,.webix_ss_header TD,.webix_ss_vscroll_header{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_ss_footer TD,.webix_ss_vscroll_footer{background:#fafafa}
|
||||
.webix_hcell{padding:0 10px;text-align:left}
|
||||
.webix_hcell{padding:0 10px 0 10px;text-align:left}
|
||||
.webix_ss_header td{border-right:1px solid #a4bed4;border-bottom:1px solid #a4bed4}
|
||||
.webix_ss_footer td{border-right:1px solid #ebebeb;border-top:1px solid #ebebeb}
|
||||
.webix_size_row td{border:none}
|
||||
|
@ -222,31 +223,32 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_block_selection{background:rgba(0,0,0,.1);border:2px solid #ffd47b}
|
||||
.webix_dd_drag{white-space:nowrap;overflow:hidden;border-left:1px solid #ebebeb;height:34px}
|
||||
.webix_dd_drag>div{display:inline-block;vertical-align:top;background:#fff;border-top:1px solid #ebebeb;border-right:1px solid #ebebeb;border-bottom:1px solid #ebebeb;padding:5px 10px;height:34px;line-height:26px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_dd_drag_column{padding:5px 10px}
|
||||
.webix_dd_drag_column{padding:5px 10px 5px 10px}
|
||||
.webix_column>.webix_drag_over.webix_cell{background-color:#e6e6e6;color:#1e2022}
|
||||
.webix_ss_header table,.webix_ss_header td{padding:0;margin:0}
|
||||
.webix_cell.webix_invalid,.webix_column>.webix_cell.webix_invalid:nth-child(even){background-color:#fee}
|
||||
.webix_invalid_cell{position:relative}
|
||||
.webix_invalid_cell:after{content:"";position:absolute;top:0;right:0;width:0;height:1px;border-top:8px solid #f44;border-left:8px solid transparent}
|
||||
.webix_column>div.webix_cell_select,.webix_column>div.webix_column_select,.webix_column>div.webix_row_select{color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_column>div.webix_cell_select,.webix_column>div.webix_column_select,.webix_column>div.webix_row_select{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_column>div.webix_cell_select{border-bottom:1px solid #ffd47b;box-shadow:0 1px #ffe3a9 inset;border-right:1px solid #ffd47b;border-left:1px solid #ffd47b;padding-top:0;padding-left:9px}
|
||||
.webix_ss_right .webix_column.webix_first>div.webix_cell_select{padding-left:10px}
|
||||
.webix_column>div.webix_invalid.webix_row_select:nth-child(even),.webix_column>div.webix_row_select{border-bottom:1px solid #ffd47b;box-shadow:0 1px #ffe3a9 inset;padding-top:0}
|
||||
.webix_column>div.webix_column_select{border-right:1px solid #ffd47b;border-left:1px solid #ffd47b;padding-left:9px}
|
||||
.webix_column>.webix_cell.webix_invalid.webix_cell_select:nth-child(even){color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_cell.webix_dtable_colrow,.webix_cell.webix_dtable_subrow,.webix_cell.webix_dtable_subview{position:absolute;left:0;top:0;background-color:#fff;width:100%;padding-right:28px;padding-left:10px;padding-top:1px;border-bottom:1px solid #ebebeb}
|
||||
.webix_column>.webix_cell.webix_invalid.webix_cell_select:nth-child(even){background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_cell.webix_dtable_colrow,.webix_cell.webix_dtable_subrow,.webix_dtable_subview{position:absolute;left:0;top:0;background-color:#fff;width:100%;padding-right:28px;padding-left:10px;padding-top:1px;border-bottom:1px solid #ebebeb}
|
||||
.webix_cell.webix_dtable_colrow.webix_selected{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_dtable_subrow{border-top:1px solid #ebebeb;text-align:right}
|
||||
.webix_dtable_subview{background:#ebebeb;border-top:1px solid #ebebeb;padding:0 0 0 10px;box-sizing:border-box}
|
||||
.webix_dtable_subview{background:#ebebeb;border-top:1px solid #ebebeb;padding:0;padding-left:10px;box-sizing:border-box}
|
||||
.number .webix_cell{text-align:right}
|
||||
.webix_rotate{transform:rotate(-90deg);-webkit-transform:rotate(-90deg);line-height:normal}
|
||||
.webix_measure_rotate{line-height:normal;white-space:normal;padding:10px}
|
||||
.webix_span_layer,.webix_span_layer_top{background:0 0;position:absolute;left:0;top:0;height:0;width:0;overflow:visible}
|
||||
.webix_span_layer_top{z-index:1;overflow:hidden}
|
||||
.webix_span_layer_top{z-index:1}
|
||||
.webix_ss_right .webix_span_layer,.webix_ss_right .webix_span_layer_top{border-left:1px solid #a4bed4}
|
||||
.webix_dtable_span{position:absolute;background:#fff;text-align:left}
|
||||
.webix_dtable_span.webix_selected{color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_dtable_span.webix_selected{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_hcell span.webix_input_icon{background-color:#a4bed4}
|
||||
.webix_area_selection_layer{position:absolute;z-index:1}
|
||||
.webix_area_selection_layer{position:absolute;z-index:2}
|
||||
.webix_area_selection{position:absolute;background:#1e2022}
|
||||
.webix_area_selection_bottom,.webix_area_selection_top{height:2px}
|
||||
.webix_area_selection_left,.webix_area_selection_right{width:2px}
|
||||
|
@ -256,7 +258,7 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_win_body{overflow:hidden}
|
||||
.webix_win_body,.webix_win_body>.webix_view,.webix_win_body>.webix_view .webix_cal_month,.webix_win_content,.webix_window{border-radius:0}
|
||||
.webix_win_head{border-bottom:1px solid silver}
|
||||
.webix_win_head>.webix_view>.webix_template{font-family:Helvetica,Verdana;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);padding:0;text-align:center;line-height:34px}
|
||||
.webix_win_head>.webix_view>.webix_template{font-family:Helvetica,Verdana;color:#1e2022;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;padding:0;text-align:center;line-height:34px}
|
||||
.webix_win_head>.webix_view>.webix_template .webix_el_label,.webix_win_head>.webix_view>.webix_template .webix_inp_label{color:#1e2022}
|
||||
.webix_win_content{height:auto;width:auto;overflow:hidden}
|
||||
.webix_modal{width:100%;height:100%;position:fixed;top:0;left:0;background-color:#000;filter:alpha(opacity=20);opacity:.2}
|
||||
|
@ -268,18 +270,19 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_point_bottom{background-position:0 0}
|
||||
.webix_point_right{background-position:0 -22px}
|
||||
.webix_point_left{background-position:0 -9px}
|
||||
.webix_resize_handle{position:absolute;width:15px;height:15px;bottom:0;line-height:15px;right:-1px;text-align:center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAAABlBMVEUAAAAAAAClZ7nPAAAAAXRSTlMAQObYZgAAABZJREFUeAFjIAUwUshlpJDLSIhLGAAACQ4AFk79JaMAAAAASUVORK5CYII=);cursor:nw-resize}
|
||||
.webix_resize_handle{position:absolute;z-index:2;width:15px;height:15px;bottom:0;line-height:15px;right:-1px;text-align:center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAAABlBMVEUAAAAAAAClZ7nPAAAAAXRSTlMAQObYZgAAABZJREFUeAFjIAUwUshlpJDLSIhLGAAACQ4AFk79JaMAAAAASUVORK5CYII=);cursor:nw-resize}
|
||||
.webix_resize_frame{position:absolute;filter:alpha(opacity=10);opacity:.1;background:#d6e8ff;display:block;border:1px solid #70afff;box-shadow:1px 3px 6px #000}
|
||||
.webix_resize_cursor{cursor:nw-resize}
|
||||
.webix_tree .webix_scroll_cont>.webix_tree_leaves{padding:9px 10px 9px 9px}
|
||||
.webix_tree_item{clear:both;height:22px;line-height:22px;white-space:nowrap}
|
||||
.webix_tree_item.webix_selected{background:0 0}
|
||||
.webix_tree_item.webix_selected span{padding:4px 10px 4px 4px;margin-left:-4px;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_tree_item.webix_selected span{padding:4px 10px 4px 4px;margin-left:-4px;background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_tree_item.webix_invalid{background-color:#fee}
|
||||
.webix_tree_checkbox{margin:1px 0 0;padding:0;float:left;vertical-align:middle;height:100%;width:13px}
|
||||
.webix_indeterminate{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gcCCSwfRyGesAAAAAxpVFh0Q29tbWVudAAAAAAAvK6ymQAAAExJREFUKM9jLCgo+M9AAmBhYGBgaGtrY+Tk5MSrsLCwkIGBgeE/EwOJgGQNLMgcJSUlBgYGBnQ/Md67d498G+jsB6hbGQfWSYykJg0AUMsPVoNrFX0AAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:left center;height:100%;width:13px;margin-top:0!important}
|
||||
.webix_measure_size input,.webix_measure_size select,.webix_measure_size textarea{width:5px}
|
||||
.webix_measure_size div{margin-left:-5px;float:none}
|
||||
.webix_measure_size a,.webix_measure_size div{display:inline-block!important}
|
||||
.webix_measure_size a,.webix_measure_size div{display:inline-block!important;position:static!important}
|
||||
.webix_tree_close,.webix_tree_file,.webix_tree_folder,.webix_tree_folder_open,.webix_tree_none,.webix_tree_open{float:left;width:20px;height:100%;cursor:pointer;margin:0;background-repeat:no-repeat}
|
||||
.webix_tree_close,.webix_tree_none,.webix_tree_open{background-position:center center}
|
||||
.webix_cell .webix_tree_close,.webix_cell .webix_tree_none,.webix_cell .webix_tree_open{background-color:transparent}
|
||||
|
@ -291,7 +294,7 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_tree_file{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQVAPv7+2RkZPf39/r6+vj4+Pn5+fT09Pb29vX19fHx8fDw8Onp6fLy8u7u7uzs7PPz8+vr6+rq6uXl5ejo6O/v7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABUALAAAAAASABIAAAV4YCWOZGkGaKqaVSAMQCwLQnAOj6ErzUTXpQDgQDgcGJTFDzgSEp4HRCKytDUBMKzAoIAsJACrSCjTGhINR5hELg8ECEZifS3HCgQEgj62xwZPAnwtbgMDBQU0g21Yh4iIi3aGkzBihH52lgEEmDIEli0qoigspSYhADs=)}
|
||||
.webix_tree_folder{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQfAPvjpP/24fPHVvnUdvzotdSiKv/23vvrw/LCS/C+RfnelvPMaf/88/nbi/rsyerYq/TLYv7y1v7wzeCsLO+8P86dJfvv0MuaIsydKPPOc+SqGKGEPe/AS+zVneWwLf///yH5BAEAAB8ALAAAAAASABIAAAWZ4CdeZGleYvpdA+O+zNUBqHoZOB4EceHUqVtuF+n9VCtdQCI5BC6FA3BkCEQkBALAACVMV9eDVhGJQGnIixigaAwiG6jie2G7BxDLpVJozG13EAICPxUeGRleQQMLgggJUhiHC3pBggKPFJETGZRAF5gJCRSaFxgTC55BCByioz+nEKojGgmtHBwPJAUCELo2J8FfSMTFxsUhADs=)}
|
||||
.webix_tree_folder_open{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQfAPXMWPK9N/fipOzLbPrVaP/89frqwv3tuvvprfLES+7PdP7xyP7z0vPAQfvtyMuaIv/32/735OSqFv3de+7ReP7lmf7gh/nv0v/67unFXfb29vK/PenFSaGEPfLnyv///yH5BAEAAB8ALAAAAAASABIAAAWS4Cc+ZGk+YvqZRVtgGiag6sNBThlFWnTQqQcE4sqRFj/VashsYR6HZI0JWSAjDwQCOGIgERULg/EQzJRQsGVCYHTK51qYTQDkFPj4iA4AJHIUgQoGQA8EdX4NhHgKAxeFfQkJGwGLeI6Fkg2UlQ8Dn5hBCZuchKChIxKkGw05Ga8DHlwkqg2tJ1xBtDlKvTUkviEAOw==)}
|
||||
.webix_tree_img{background:0 0;float:left;width:18px;height:22px}
|
||||
.webix_tree_img{background:0 0;float:left;width:18px;height:22px;background-position:0 0}
|
||||
.webix_tree_plus2{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQfAFSWrmi52FCPplORqVmet8HBwfn//02KoE+NpEyIn2a21E2Jn2u/3mzB4Vqguk6LomGtyWGuy27E5VqivG/H51OUrE+OpVyhu1eXr2CqxV6lwFaas06LoXHJ6lKTqgAAACH5BAEAAB8ALAAAAAASABIAAAVZ4CeOYkGeaJmuKpuaLgrHX7IcD2IJrs0hAk8FAGAlDoiBYUNwTIyPAcagyUAirAXCwOUGAoVwmHSwVAiGSIDRYB0EgIthLaG44RN1g9JxwR0QdDSDhIWGKyEAOw==);background-repeat:no-repeat}
|
||||
.webix_tree_plus3{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQfAFSWrmi52FCPplORqVmet8HBwfn//02KoE+NpEyIn2a21E2Jn2u/3mzB4Vqguk6LomGtyWGuy27E5VqivG/H51OUrE+OpVyhu1eXr2CqxV6lwFaas06LoXHJ6lKTqgAAACH5BAEAAB8ALAAAAAASABIAAAVb4CeOYkGeaJmuKpuaLgrHX7IcD2IJrs0hAk8FAGAlDoiBYUNwTIyPAcagyUAirAXCwOUGAoVwmHSwVAiGSIDRYB0EgIthLaG44RN1g9JxwR0QdDQtg4SFM4csIQA7)}
|
||||
.webix_tree_plus4{background-image:url(data:image/gif;base64,R0lGODlhEgASAMQfAFSWrmi52FCPplORqVmet/n//8HBwU2KoE+NpEyIn2a21E2Jn2u/3mzB4VqgumGtyWGuy27E5VqivE6Lom/H51OUrE+OpVyhu1eXr2CqxV6lwFaas06LoVKTqnHJ6gAAACH5BAEAAB8ALAAAAAASABIAAAVY4CeOZGmeaKqubEsmyzEhlqDCHCJ0FQCkiQNiUNgQHBLgZIApaDIPSGqBKFitgYBhuyUdLBVCARJgNFIHAeBSKEcoaLWE3KB4VGrHw+0yuEZ+fx+Bf4QmIQA7)}
|
||||
|
@ -308,9 +311,9 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_cal_next_button,.webix_cal_prev_button{cursor:pointer;position:absolute;top:17px;width:30px;height:28px;background-position:11.5px 4px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.webix_cal_prev_button{left:17px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAASUlEQVR42p2QMQoAQQgD79EZ0Mqn5xCu2cPdYgUbJ0rMMxXgLeiuKq8gsJAz8weQ0QiwJEfECnr4wdlEnwJ68+yyhReC+c85oRecj0Um+pmo9wAAAABJRU5ErkJggg==);background-repeat:no-repeat}
|
||||
.webix_cal_next_button{right:17px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAARElEQVR42qXPsQoAIAhF0T76PdDJT7cUmtQhcmk4N8QVQ9JXN2bmgWOgqp+BiCRG2AYAMoi3/LxYdyagAnhA6G93TrABZaJFJjrFY8IAAAAASUVORK5CYII=);background-repeat:no-repeat}
|
||||
.webix_view>.webix_cal_header{margin:0 17px 10px;height:auto}
|
||||
.webix_view>.webix_cal_header{margin:0 17px 10px 17px;height:auto}
|
||||
.webix_view>.webix_cal_header div{float:left;text-align:center;height:19px;font-size:11px;color:#1e2022;border-bottom:#cecece 1px solid;margin-bottom:7px}
|
||||
.webix_cal_body{margin:0 17px}
|
||||
.webix_cal_body{margin:0 17px 0 17px}
|
||||
.webix_cal_body .webix_cal_row{clear:both}
|
||||
.webix_cal_body .webix_cal_row>div{float:left;text-align:center;height:100%}
|
||||
.webix_cal_body .webix_cal_select,.webix_cal_body .webix_cal_select.webix_cal_today,.webix_cal_body .webix_selected{color:#1e2022;background:#ffdb8f}
|
||||
|
@ -325,30 +328,30 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_cal_block{float:left;text-align:center;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.webix_selected{background:#ffdb8f;color:#1e2022}
|
||||
.webix_cal_footer{text-align:center;font-size:12px;color:#444;margin:4px 17px;padding-top:2px;cursor:pointer}
|
||||
.webix_cal_icons{float:right;padding:4px}
|
||||
.webix_cal_icons{float:right;padding:4px 4px}
|
||||
.webix_cal_time{padding:2px 4px}
|
||||
.webix_cal_time_icons{float:left}
|
||||
.webix_cal_icons .webix_cal_icon{text-align:center;padding:2px 4px}
|
||||
.webix_cal_icon:hover,.webix_cal_month_name:hover,.webix_cal_time:hover{text-decoration:underline;color:#d6e8ff}
|
||||
.webix_cal_month_name.webix_readonly:hover{text-decoration:none;color:#1e2022;cursor:default}
|
||||
.webix_time_header{padding:17px 17px 1px}
|
||||
.webix_time_header{padding:17px 17px 1px 17px}
|
||||
.webix_time_header .webix_cal_hours,.webix_time_header .webix_cal_minutes{display:inline-block;font-size:14px;text-align:center;height:26px;line-height:22px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #a4bed4}
|
||||
.webix_time_header .webix_cal_minutes{padding-left:1px;border-left:none}
|
||||
.webix_time_header .webix_cal_hours{border-right:none!important}
|
||||
.webix_cal_body .webix_hours{float:left;border-right:1px solid #cecece;padding-right:1px}
|
||||
.webix_cal_body .webix_minutes{float:left;padding-left:1px}
|
||||
.webix_cal_block_empty{float:left;text-align:center}
|
||||
.webix_time_footer{text-align:center;font-size:12px;padding:7px 17px 0;cursor:pointer}
|
||||
.webix_cal_done{margin-top:3px;padding:2px 7px;font-size:12px;border-radius:6px;border:1px solid #a4bed4;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);float:right}
|
||||
.webix_time_footer{text-align:center;font-size:12px;padding:7px 17px 0 17px;cursor:pointer}
|
||||
.webix_cal_done{margin-top:3px;padding:2px 7px;font-size:12px;border-radius:6px;border:1px solid #a4bed4;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;float:right}
|
||||
.webix_cal_blurred_hours{background-color:#f7f7f7}
|
||||
.webix_property_line{clear:both;width:100%;min-height:24px;height:auto}
|
||||
.webix_property_line:nth-child(odd){background-color:#f7f7f7}
|
||||
.webix_property_label,.webix_property_value{height:24px;line-height:24px;padding-left:10px;float:left;border-bottom:1px solid #a4bed4;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}
|
||||
.webix_property_label{border-right:1px solid #a4bed4}
|
||||
.webix_property_label_line{padding-left:10px;font-family:Helvetica,Verdana;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);line-height:32px;line-height:23px;border-bottom:1px solid #ebebeb}
|
||||
.webix_property_label_line{padding-left:10px;font-family:Helvetica,Verdana;color:#1e2022;font-size:13px;font-weight:700;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;line-height:32px;line-height:23px;border-bottom:1px solid #ebebeb}
|
||||
.webix_property_label_line .webix_el_label,.webix_property_label_line .webix_inp_label{color:#1e2022}
|
||||
.webix_property_col_val{width:100%;height:100%;-moz-user-select:text;-webkit-user-select:text;user-select:text}
|
||||
.webix_property_col_ind{float:right;border:1px solid #a4bed4;border-radius:2px;width:30px;cursor:pointer;height:13px;margin:3px 10px 3px 0}
|
||||
.webix_property_col_ind{float:right;border:1px solid #a4bed4;border-radius:3px;width:16px;cursor:pointer;height:16px;margin:4px 10px 3px 0}
|
||||
.webix_property_value{text-overflow:ellipsis;white-space:nowrap}
|
||||
.webix_property_check{margin-top:5px}
|
||||
.webix_tooltip{display:none;position:absolute;z-index:10000;background-color:#fff;padding:5px 10px;border:1px solid #a4bed4;font-family:Helvetica,Verdana;font-size:13px;color:#1e2022;border-radius:0;box-shadow:1px 1px 0 0 #CCC}
|
||||
|
@ -377,16 +380,16 @@ div.webix_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=
|
|||
.webix_el_button button,.webix_el_button input,.webix_el_toggle button,.webix_el_toggle input,.webixbutton{border-radius:6px;border:1px solid #a4bed4;height:100%;width:100%;cursor:pointer;font-size:13px;font-family:Helvetica,Verdana;-webkit-appearance:none}
|
||||
.webix_el_button .webix_img_btn,.webix_el_button .webix_img_btn .webix_img_btn_text,.webix_el_button .webix_img_btn_top,.webix_el_button .webix_img_btn_top .webix_img_btn_text,.webix_el_toggle .webix_img_btn,.webix_el_toggle .webix_img_btn .webix_img_btn_text,.webix_el_toggle .webix_img_btn_top,.webix_el_toggle .webix_img_btn_top .webix_img_btn_text{color:#1e2022}
|
||||
.webix_el_button .webix_img_btn,.webix_el_button .webix_img_btn_top,.webix_el_toggle .webix_img_btn,.webix_el_toggle .webix_img_btn_top{border:0}
|
||||
.webixbutton,.webixtype_base,.webixtype_next,.webixtype_prev{color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);font-size:13px;font-family:Helvetica,Verdana;padding:0;border:0}
|
||||
.webixtype_form{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webixtype_form:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background:no-repeat #d6e8ff}
|
||||
.webix_el_button .webixtype_danger{background:#c10;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e7877e),color-stop(100%,#c10));background:-webkit-linear-gradient(#e7877e,#c10);background:-moz-linear-gradient(#e7877e,#c10);background:-ms-linear-gradient(top,#e7877e,#c10);background:-o-linear-gradient(top,#e7877e,#c10);border:none!important;color:#fff}
|
||||
.webixbutton,.webixtype_base,.webixtype_next,.webixtype_prev{color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);font-size:13px;font-family:Helvetica,Verdana;padding:0;border:0}
|
||||
.webixtype_form{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webixtype_form:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background:#d6e8ff;background-repeat:no-repeat}
|
||||
.webix_el_button .webixtype_danger{background:#c10;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e7877e),color-stop(100%,#c10));background-image:-webkit-linear-gradient(#e7877e,#c10);background-image:-moz-linear-gradient(#e7877e,#c10);background-image:-ms-linear-gradient(top,#e7877e,#c10);background-image:-o-linear-gradient(top,#e7877e,#c10);border:none!important;color:#fff}
|
||||
.webix_el_button .webix_el_box,.webix_el_toggle .webix_el_box{position:relative}
|
||||
.webix_el_button .webix_el_arrow,.webix_el_toggle .webix_el_arrow{position:absolute;z-index:1}
|
||||
.webixtype_next,.webixtype_prev{position:absolute;z-index:2;top:0}
|
||||
input.webixtype_prev{border-left-width:0;border-radius:0 6px 6px 0;-webkit-border-radius:0 6px 6px 0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}
|
||||
input.webixtype_next{border-right-width:0;border-radius:6px 0 0 6px;-webkit-border-radius:6px 0 0 6px;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}
|
||||
.webix_el_arrow{width:18px;height:18px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);border:1px solid #a4bed4}
|
||||
.webix_el_button .webix_el_arrow,.webix_el_toggle .webix_el_arrow{position:absolute}
|
||||
.webixtype_next,.webixtype_prev{position:absolute;z-index:1;top:0}
|
||||
input.webixtype_prev{border-left-width:0;border-radius:0;-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:6px;border-bottom-right-radius:6px}
|
||||
input.webixtype_next{border-right-width:0;border-radius:0;-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:0;border-bottom-right-radius:0}
|
||||
.webix_el_arrow{width:18px;height:18px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);border:1px solid #a4bed4}
|
||||
.webixtype_prev_arrow{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg)}
|
||||
.webixtype_next_arrow{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg)}
|
||||
.webix_img_btn_abs_top .webix_icon,.webix_img_btn_top .webix_icon{font-size:22px;position:absolute;top:8px;left:50%}
|
||||
|
@ -405,7 +408,7 @@ input.webixtype_next{border-right-width:0;border-radius:6px 0 0 6px;-webkit-bord
|
|||
.webix_img_btn_top{background-position:center top;vertical-align:top}
|
||||
.webix_img_btn_abs .webix_img_btn_text{bottom:8px}
|
||||
.webix_pressed .webix_img_btn,.webix_pressed .webix_img_btn_top{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background-color:rgba(0,0,0,.05)}
|
||||
.webix_control .webix_disabled_box .webix_el_arrow,.webix_control .webix_disabled_box .webix_img_btn,.webix_control .webix_disabled_box .webixtype_base,.webix_control .webix_disabled_box .webixtype_danger,.webix_control .webix_disabled_box .webixtype_form,.webix_control .webix_disabled_box .webixtype_next,.webix_control .webix_disabled_box .webixtype_prev{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background:-moz-linear-gradient(#fbfbfb,#e9e9e9);background:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_control .webix_disabled_box .webix_el_arrow,.webix_control .webix_disabled_box .webix_img_btn,.webix_control .webix_disabled_box .webixtype_base,.webix_control .webix_disabled_box .webixtype_danger,.webix_control .webix_disabled_box .webixtype_form,.webix_control .webix_disabled_box .webixtype_next,.webix_control .webix_disabled_box .webixtype_prev{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background-image:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background-image:-moz-linear-gradient(#fbfbfb,#e9e9e9);background-image:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background-image:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_control .webix_disabled_box .webix_img_btn_text{color:#aaa}
|
||||
.webix_control .webix_disabled_box .webix_image{opacity:.4}
|
||||
.webix_disabled_view.webix_control .webix_icon,.webix_disabled_view.webix_control .webix_icon_btn,.webix_layout_toolbar.webix_toolbar .webix_disabled_view.webix_control .webix_disabled_box .webix_img_btn_text,.webix_layout_toolbar.webix_toolbar .webix_disabled_view.webix_control .webix_icon,.webix_layout_toolbar.webix_toolbar .webix_disabled_view.webix_control .webix_icon_btn{color:#aaa}
|
||||
|
@ -415,31 +418,31 @@ input.webixtype_next{border-right-width:0;border-radius:6px 0 0 6px;-webkit-bord
|
|||
.webix_richtext_container .webix_template{padding:10px;overflow-x:auto;border:solid #ccc;border-width:0 1px 1px;border-radius:0 0 6px 6px}
|
||||
.webix_control{background:0 0}
|
||||
.webix_control button,.webix_control input,.webix_control textarea,.webix_el_label,.webix_inp_bottom_label,.webix_inp_label,.webix_inp_top_label{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana}
|
||||
.webix_el_box{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:2px;height:100%;width:100%;font-size:13px;overflow:hidden}
|
||||
.webix_el_box{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:2px 2px;height:100%;width:100%;font-size:13px;overflow:hidden}
|
||||
.webix_el_colorpicker input,.webix_el_combo input,.webix_el_datepicker input,.webix_el_search input,.webix_el_text input{height:100%;padding:0 10px;border:1px solid #a4bed4;color:#1e2022;font-size:13px;font-family:Helvetica,Verdana;-webkit-appearance:none;border-radius:0}
|
||||
.webix_inp_label,.webix_inp_top_label,.webix_label_right{color:#1e2022;text-transform:none;font-size:13px}
|
||||
.webix_inp_label{float:left;padding-top:1px;padding-left:2px;padding-right:7.5px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}
|
||||
.webix_inp_top_label{float:none;padding:2px 2px 0}
|
||||
.webix_inp_top_label{float:none;padding:2px 2px;padding-bottom:0}
|
||||
.webix_inp_bottom_label{font-size:11px;color:#2a2d30}
|
||||
.webix_label_right{padding-left:7.5px}
|
||||
.webix_el_checkbox .webix_label_right{display:inline-block;padding-top:2px}
|
||||
.webix_el_label{color:#1e2022;line-height:30px;padding:2px}
|
||||
.webix_el_label{color:#1e2022;line-height:30px;padding:2px 2px}
|
||||
.webix_toolbar .webix_el_label{padding-left:10px;text-transform:none}
|
||||
.webix_el_select select{height:100%;font-size:13px;font-family:Helvetica,Verdana;border:1px solid #a4bed4}
|
||||
body:not(:-moz-handler-blocked) .webix_el_select select{padding:.2em}
|
||||
.webix_all_segments,.webix_el_group{height:100%;white-space:nowrap}
|
||||
.webix_inp_counter_next,.webix_inp_counter_prev,.webix_inp_counter_value{border:1px solid #a4bed4;cursor:pointer;-webkit-appearance:none;width:20px;height:100%;vertical-align:top}
|
||||
.webix_inp_counter_value{font-size:13px;width:50px;color:#1e2022;text-align:center;border-left-width:0;border-right-width:0;-webkit-appearance:none;border-radius:0}
|
||||
.webix_inp_counter_prev{padding-left:6px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);-webkit-border-radius:6px 0 0 6px;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-radius:6px 0 0 6px}
|
||||
.webix_inp_counter_next{padding-left:6px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);-webkit-border-radius:0 6px 6px 0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-radius:0 6px 6px 0}
|
||||
.webix_el_textarea textarea{border:1px solid #a4bed4;height:100%;margin:0;padding:5px 10px;color:#1e2022;resize:none;font-size:13px;font-family:Helvetica,Verdana}
|
||||
.webix_inp_counter_prev{padding-left:6px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:0;border-bottom-right-radius:0}
|
||||
.webix_inp_counter_next{padding-left:6px;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:6px;border-bottom-right-radius:6px}
|
||||
.webix_el_textarea textarea{border:1px solid #a4bed4;height:100%;margin:0;padding:5px;color:#1e2022;resize:none;font-size:13px;font-family:Helvetica,Verdana;padding-left:10px;padding-right:10px}
|
||||
.webix_el_textarea .webix_inp_label{padding-top:8.5px}
|
||||
.webix_segment_0,.webix_segment_1{border:1px solid #a4bed4;border-right-width:0;height:100%}
|
||||
.webix_segment_0{-webkit-border-radius:6px 0 0 6px;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-radius:6px 0 0 6px}
|
||||
.webix_segment_N{border:1px solid #a4bed4;height:100%;-webkit-border-radius:0 6px 6px 0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-radius:0 6px 6px 0}
|
||||
.webix_segment_N:first-child{-webkit-border-radius:6px;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-radius:6px}
|
||||
.webix_segment_0,.webix_segment_1,.webix_segment_N{-webkit-appearance:none;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background:-webkit-linear-gradient(#fff,#e6e6e6);background:-moz-linear-gradient(#fff,#e6e6e6);background:-ms-linear-gradient(top,#fff,#e6e6e6);background:-o-linear-gradient(top,#fff,#e6e6e6);font-size:13px;font-family:Helvetica,Verdana;cursor:pointer;padding:0}
|
||||
.webix_segment_0.webix_selected,.webix_segment_1.webix_selected,.webix_segment_N.webix_selected{color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_segment_0{-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:0;border-bottom-right-radius:0}
|
||||
.webix_segment_N{border:1px solid #a4bed4;height:100%;-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:6px;border-bottom-right-radius:6px}
|
||||
.webix_segment_N:first-child{-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:6px;border-bottom-right-radius:6px}
|
||||
.webix_segment_0,.webix_segment_1,.webix_segment_N{-webkit-appearance:none;color:#1e2022;background:#e6e6e6;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#e6e6e6));background-image:-webkit-linear-gradient(#fff,#e6e6e6);background-image:-moz-linear-gradient(#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);font-size:13px;font-family:Helvetica,Verdana;cursor:pointer;padding:0}
|
||||
.webix_segment_0.webix_selected,.webix_segment_1.webix_selected,.webix_segment_N.webix_selected{background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_inp_static{border:1px solid #a4bed4;background:#fff;overflow:hidden;padding:0 10px;height:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;float:left}
|
||||
.webix_inp_static .webix_placeholder{color:#666d73}
|
||||
.webix_el_colorpicker,.webix_el_combo,.webix_el_datepicker,.webix_el_richselect,.webix_el_search{font-size:13px}
|
||||
|
@ -465,15 +468,15 @@ body:not(:-moz-handler-blocked) .webix_el_select select{padding:.2em}
|
|||
.webix_disabled_view.webix_control .webix_image{-webkit-filter:grayscale(100%);filter:grayscale(100%)}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_input_icon,.webix_view.webix_control .webix_disabled_box button,.webix_view.webix_control .webix_disabled_box label{color:#aaa}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_inp_static,.webix_view.webix_control .webix_disabled_box input,.webix_view.webix_control .webix_disabled_box select,.webix_view.webix_control .webix_disabled_box textarea{color:#aaa;background:#eee}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_inp_counter_next,.webix_view.webix_control .webix_disabled_box .webix_inp_counter_prev,.webix_view.webix_control .webix_disabled_box .webix_segment_0,.webix_view.webix_control .webix_disabled_box .webix_segment_1,.webix_view.webix_control .webix_disabled_box .webix_segment_N{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background:-moz-linear-gradient(#fbfbfb,#e9e9e9);background:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_inp_counter_next,.webix_view.webix_control .webix_disabled_box .webix_inp_counter_prev,.webix_view.webix_control .webix_disabled_box .webix_segment_0,.webix_view.webix_control .webix_disabled_box .webix_segment_1,.webix_view.webix_control .webix_disabled_box .webix_segment_N{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background-image:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background-image:-moz-linear-gradient(#fbfbfb,#e9e9e9);background-image:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background-image:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_disabled_top_label{color:#aaa}
|
||||
label.webix_required:after{padding-left:4px;content:"*";color:red}
|
||||
label.webix_required:after,legend.webix_required:after{padding-left:4px;content:"*";color:red}
|
||||
.webix_multicombo .webix_inp_static{padding:0 3px}
|
||||
.webix_el_text .webix_multicombo_input{background-color:transparent;border:0;float:left;vertical-align:middle;padding:0;color:#1e2022;font-size:13px;font-family:Helvetica,Verdana;margin-left:7px}
|
||||
.webix_el_text .webix_multicombo_input:focus{border:0;box-shadow:none}
|
||||
.webix_multicombo_listbox{width:auto;line-height:1;margin:0;padding:0;list-style:none}
|
||||
.webix_multicombo_tag,.webix_multicombo_value{padding:0 5px 0 7px;background-color:#f2f2f2;display:inline-block;margin:3px;float:left;border-radius:6px}
|
||||
.webix_multicombo_tag{min-width:15px;text-align:center;padding:0 5px}
|
||||
.webix_multicombo_tag{min-width:15px;text-align:center;padding:0 5px 0 5px}
|
||||
.webix_multicombo_delete{margin-left:10px;padding:0 5px;color:#000;cursor:pointer}
|
||||
.webix_multilist .webix_selected{background:#f2f2f2;color:#1e2022}
|
||||
.webix_checksuggest_select_all{border:none;border-bottom:1px solid #ebebeb;border-color:#ebebeb;margin-bottom:1px}
|
||||
|
@ -485,13 +488,13 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.webix_tab_filler{display:table-cell;background:0 0;font-size:1px;border-bottom:1px solid #a4bed4;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_tab_filler:first-child{border-right:1px solid #a4bed4}
|
||||
.webix_item_tab:first-child{border-left:1px solid #a4bed4}
|
||||
.webix_item_tab{display:table-cell;text-align:center;vertical-align:middle;overflow:hidden;cursor:pointer;border:1px solid #a4bed4;border-left-width:0;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);-webkit-border-radius:0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-radius:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_item_tab{display:table-cell;text-align:center;vertical-align:middle;overflow:hidden;cursor:pointer;border:1px solid #a4bed4;border-left-width:0;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webixtype_bottom .webix_item_tab{border-radius:0}
|
||||
.webix_item_tab.webix_selected{border-bottom-width:0;background:#fff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e5f1ff),color-stop(100%,#fff));background:-webkit-linear-gradient(#e5f1ff,#fff);background:-moz-linear-gradient(#e5f1ff,#fff);background:-ms-linear-gradient(top,#e5f1ff,#fff);background:-o-linear-gradient(top,#e5f1ff,#fff)}
|
||||
.webixtype_bottom .webix_item_tab.webix_selected{border-bottom-width:1px;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background:-webkit-linear-gradient(#ffebc2,#ffdb8f);background:-moz-linear-gradient(#ffebc2,#ffdb8f);background:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_item_tab.webix_selected{border-bottom-width:0;background:#fff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e5f1ff),color-stop(100%,#fff));background-image:-webkit-linear-gradient(#e5f1ff,#fff);background-image:-moz-linear-gradient(#e5f1ff,#fff);background-image:-ms-linear-gradient(top,#e5f1ff,#fff);background-image:-o-linear-gradient(top,#e5f1ff,#fff)}
|
||||
.webixtype_bottom .webix_item_tab.webix_selected{border-bottom-width:1px;background-size:100% 100%;background-position:0 0;color:#1e2022;background:#ffdb8f;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#ffebc2),color-stop(100%,#ffdb8f));background-image:-webkit-linear-gradient(#ffebc2,#ffdb8f);background-image:-moz-linear-gradient(#ffebc2,#ffdb8f);background-image:-ms-linear-gradient(top,#ffebc2,#ffdb8f);background-image:-o-linear-gradient(top,#ffebc2,#ffdb8f)}
|
||||
.webix_before_all_tabs{width:100%}
|
||||
.webix_after_all_tabs{width:100%;border-left:1px solid #a4bed4;border-right:1px solid #a4bed4;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_item_tab{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background:-moz-linear-gradient(#fbfbfb,#e9e9e9);background:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_view.webix_control .webix_disabled_box .webix_item_tab{color:#aaa!important;background:#e9e9e9;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#e9e9e9));background-image:-webkit-linear-gradient(#fbfbfb,#e9e9e9);background-image:-moz-linear-gradient(#fbfbfb,#e9e9e9);background-image:-ms-linear-gradient(top,#fbfbfb,#e9e9e9);background-image:-o-linear-gradient(top,#fbfbfb,#e9e9e9);border-color:#d5d5d5!important}
|
||||
.webix_el_tabbar .webixtype_icon .webix_img_btn{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0 auto;text-align:center}
|
||||
.webix_el_tabbar .webixtype_icon .webix_img_btn .webix_icon_btn{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0 3px}
|
||||
.webix_el_tabbar .webixtype_icon .webix_item_tab,.webix_el_tabbar .webixtype_iconTop .webix_item_tab,.webix_el_tabbar .webixtype_image .webix_item_tab{padding:2px 0;border-radius:0}
|
||||
|
@ -505,17 +508,17 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.webix_menu .webix_list_item .webix_submenu_icon,.webix_menu-x .webix_list_item .webix_submenu_icon{float:right;text-align:right;position:relative;margin-left:4px}
|
||||
.webix_menu-x .webix_list_item:first-child{margin-left:0}
|
||||
.webix_menu-x .webix_submenu_icon{top:13px}
|
||||
.webix_menu-x{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webix_menu-x{background-color:#fff;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_menu-x .webix_list_item{display:inline-block;line-height:30px;-moz-background-size:1px 100%,100% 100%,1px 100%;background-size:1px 100%,100% 100%,1px 100%;background-color:transparent;margin:1px 0;background-position:0 0,1px 0,100% 0;background-repeat:no-repeat;background-image:-webkit-gradient(linear,left top,left bottom,#f0f6ff,#fff,#f0f6ff),-webkit-gradient(linear,left top,left bottom,transparent,transparent),-webkit-gradient(linear,left top,left bottom,#f0f6ff,#a4bed4,#f0f6ff);background-image:-webkit-linear-gradient(#f0f6ff,#fff,#f0f6ff),-webkit-linear-gradient(transparent,transparent),-webkit-linear-gradient(#f0f6ff,#a4bed4,#f0f6ff);background-image:-moz-linear-gradient(#f0f6ff,#fff,#f0f6ff),-moz-linear-gradient(transparent,transparent),-moz-linear-gradient(#f0f6ff,#a4bed4,#f0f6ff);background-image:-ms-linear-gradient(top,#f0f6ff,#fff,#f0f6ff),-ms-linear-gradient(transparent,transparent),-ms-linear-gradient(top,#f0f6ff,#a4bed4,#f0f6ff);background-image:-o-linear-gradient(top,#f0f6ff,#fff,#f0f6ff),-o-linear-gradient(transparent,transparent),-o-linear-gradient(top,#f0f6ff,#a4bed4,#f0f6ff)}
|
||||
.webix_menu-x .webix_list_item:last-child{background-size:1px 100%,100% 100%,1px 100%;background-repeat:no-repeat;background-image:-webkit-gradient(linear,left top,left bottom,#f0f6ff,#fff,#f0f6ff),-webkit-gradient(linear,left top,left bottom,transparent,transparent),-webkit-gradient(linear,left top,left bottom,transparent,transparent);background-image:-webkit-linear-gradient(#f0f6ff,#fff,#f0f6ff),-webkit-linear-gradient(transparent,transparent),-webkit-linear-gradient(transparent,transparent);background-image:-moz-linear-gradient(#f0f6ff,#fff,#f0f6ff),-moz-linear-gradient(transparent,transparent),-moz-linear-gradient(transparent,transparent);background-image:-ms-linear-gradient(top,#f0f6ff,#fff,#f0f6ff),-ms-linear-gradient(transparent,transparent),-ms-linear-gradient(transparent,transparent);background-image:-o-linear-gradient(top,#f0f6ff,#fff,#f0f6ff),-o-linear-gradient(transparent,transparent),-o-linear-gradient(transparent,transparent);border-right:0}
|
||||
.webix_menu{background:#fff;border:1px solid #a4bed4;border-radius:0}
|
||||
.webix_menu .webix_list_item{display:block}
|
||||
.webix_menu .webix_context_separator{height:3px;padding:1px 3px 0}
|
||||
.webix_menu .webix_context_separator{height:3px;padding:1px 3px 0 3px}
|
||||
.webix_menu .webix_context_separator .sep_line{height:1px;border-top:1px solid #a4bed4}
|
||||
.webix_menu .webix_submenu_icon{top:11px}
|
||||
.webix_menu .webix_context_spacer{height:28px}
|
||||
.webix_menu_link{color:inherit;text-decoration:none;display:block;height:100%}
|
||||
.webix_layout_toolbar,.webix_toolbar.webix_layout_subbar{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.webix_layout_toolbar,.webix_toolbar.webix_layout_subbar{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_toolbar .webix_layout_clean,.webix_toolbar .webix_layout_line,.webix_toolbar .webix_layout_toolbar{background:0 0}
|
||||
.webix_el_button .webix_hidden_upload,.webix_hidden_upload{height:1px;width:1px;border:0!important;font-size:1px;position:absolute;top:0;left:0;z-index:-1}
|
||||
.webix_upload_client,.webix_upload_error,.webix_upload_server{width:60px;text-align:center;float:right}
|
||||
|
@ -530,29 +533,42 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.webix_fieldset fieldset{border:1px solid #81a5c4;margin:0;padding:5px 8px}
|
||||
.webix_fieldset legend{color:#1e2022;font-size:12px}
|
||||
.webix_forminput fieldset{border:none;margin:0;padding:0}
|
||||
.webix_forminput legend{color:#1e2022;line-height:30px;padding:2px 7.5px 2px 2px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana;float:left}
|
||||
.webix_slider_box{position:relative;padding:13px 10px 0;height:100%;float:left;border-radius:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:-11px}
|
||||
.webix_slider_box .webix_slider_left{height:10px;float:left;width:100px;border:1px solid #b5cadc;-webkit-border-radius:5px 0 0 5px;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:5px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-radius:5px 0 0 5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_slider_box .webix_slider_right{height:10px;float:left;width:100px;background:#fff;-webkit-border-radius:0 5px 5px 0;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:5px;border-radius:0 5px 5px 0;border:1px solid #b5cadc;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_forminput legend{color:#1e2022;line-height:30px;padding:2px 5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Verdana;float:left;padding-right:7.5px}
|
||||
.webix_slider_box{position:relative;padding:0 10px;height:100%;padding-top:13px;float:left;border-radius:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:-11px}
|
||||
.webix_slider_box .webix_slider_left{height:10px;float:left;width:100px;border:1px solid #b5cadc;-webkit-border-top-left-radius:5px;-webkit-border-bottom-left-radius:5px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:5px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;border-top-left-radius:5px;border-bottom-left-radius:5px;border-top-right-radius:0;border-bottom-right-radius:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_slider_box .webix_slider_right{height:10px;float:left;width:100px;background:#fff;-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:5px;-webkit-border-bottom-right-radius:5px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:5px;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:5px;border-bottom-right-radius:5px;border:1px solid #b5cadc;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.webix_slider_box .webix_slider_handle{z-index:1;position:absolute;width:14px;height:14px;border-radius:8px}
|
||||
.webix_slider_box .webix_slider_left{background:#f5f9ff}
|
||||
.webix_slider_box .webix_slider_handle{border:1px solid #a4bed4;-moz-box-shadow:inset 0 1px 1px 1px #fff;-webkit-box-shadow:inset 0 1px 1px 1px #fff;box-shadow:inset 0 1px 1px #fff;background:#fafcff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#d6e8ff),color-stop(100%,#fafcff));background:-webkit-linear-gradient(#d6e8ff,#fafcff);background:-moz-linear-gradient(#d6e8ff,#fafcff);background:-ms-linear-gradient(top,#d6e8ff,#fafcff);background:-o-linear-gradient(top,#d6e8ff,#fafcff);top:10px}
|
||||
.webix_slider_box .webix_slider_handle{border:1px solid #a4bed4;-moz-box-shadow:inset 0 1px 1px 1px #fff;-webkit-box-shadow:inset 0 1px 1px 1px #fff;box-shadow:inset 0 1px 1px #fff;background:#fafcff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#d6e8ff),color-stop(100%,#fafcff));background-image:-webkit-linear-gradient(#d6e8ff,#fafcff);background-image:-moz-linear-gradient(#d6e8ff,#fafcff);background-image:-ms-linear-gradient(top,#d6e8ff,#fafcff);background-image:-o-linear-gradient(top,#d6e8ff,#fafcff);top:10px}
|
||||
.webix_rangeslider .webix_slider_box .webix_slider_left{position:absolute}
|
||||
.webix_rangeslider .webix_slider_box .webix_slider_active{z-index:1}
|
||||
.webix_rangeslider .webix_slider_box .webix_slider_right{border-radius:5px}
|
||||
.webix_rangeslider .webix_slider_title_box{position:relative;float:left;width:1px}
|
||||
.webix_rangeslider .webix_slider_title.webix_slider_move{position:absolute}
|
||||
.webix_rangeslider.webix_slider_vertical .webix_slider_box .webix_slider_right{-webkit-border-top-left-radius:5px;-webkit-border-bottom-left-radius:5px;-webkit-border-top-right-radius:5px;-webkit-border-bottom-right-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:5px;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:5px;border-top-left-radius:5px;border-bottom-left-radius:5px;border-top-right-radius:5px;border-bottom-right-radius:5px}
|
||||
.webix_rangeslider.webix_slider_vertical .webix_slider_title.webix_slider_move{display:block;position:relative}
|
||||
.webix_slider_alt .webix_slider_box .webix_slider_left,.webix_slider_alt .webix_slider_box .webix_slider_right{border:1px solid #e1e1e1}
|
||||
.webix_slider_alt .webix_slider_box .webix_slider_handle{width:11px;margin:0 2px;height:14px;border-radius:2px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTJCMjdFNENBRTg4MTFFMjk2NjJGMTJENjkyNDA2NTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTJCMjdFNERBRTg4MTFFMjk2NjJGMTJENjkyNDA2NTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5MkIyN0U0QUFFODgxMUUyOTY2MkYxMkQ2OTI0MDY1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5MkIyN0U0QkFFODgxMUUyOTY2MkYxMkQ2OTI0MDY1OSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Powz/icAAAAaSURBVHjaYmBgYDBjgAA4zcSABQysIECAAQBn+ACx2PqtbAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:3px center}
|
||||
.webix_slider_alt .webix_slider_box .webix_slider_left{background:#f0f6ff}
|
||||
.webix_slider_alt .webix_slider_box .webix_slider_right{background:#eee}
|
||||
.webix_slider_alt .webix_slider_box .webix_slider_handle{background-color:#f5f9ff;top:10px}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_left,.webix_slider_vertical .webix_slider_box .webix_slider_right{width:10px;float:none}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_left{-webkit-border-radius:0 0 5px 5px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:5px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:5px;border-radius:0 0 5px 5px}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_right{-webkit-border-radius:5px 5px 0 0;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:0;border-radius:5px 5px 0 0}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_left{-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:5px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:5px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:5px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:5px;border-top-left-radius:0;border-bottom-left-radius:5px;border-top-right-radius:0;border-bottom-right-radius:5px}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_right{-webkit-border-top-left-radius:5px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:5px;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:0;border-top-left-radius:5px;border-bottom-left-radius:0;border-top-right-radius:5px;border-bottom-right-radius:0}
|
||||
.webix_slider_vertical .webix_slider_box .webix_slider_handle{left:7px}
|
||||
.webix_slider_vertical .webix_slider_title{padding-top:1px;text-align:left}
|
||||
.webix_slider_vertical.webix_slider_alt .webix_slider_handle{height:11px;width:14px;left:5px;background-position:4px center}
|
||||
.webix_slider_title{text-align:center}
|
||||
.webix_slider_title.webix_slider_move{position:relative;text-align:left;display:inline-block;width:auto}
|
||||
.webix_slider_title.webix_slider_move{position:relative;text-align:left;display:inline-block;width:auto;white-space:nowrap}
|
||||
.webix_el_box .webix_switch_box{margin-top:4px}
|
||||
.webix_switch_toggle{position:absolute;visibility:hidden}
|
||||
.webix_switch_box{display:block;position:relative;cursor:pointer;height:24px;width:60px;background-color:#f1f1f1;border:1px solid #a4bed4;border-radius:60px;box-sizing:border-box;transition:background-color .4s ease;color:#666;text-align:center;float:left}
|
||||
.webix_el_switch .webix_label_right{display:inline-block;padding-top:3px;margin-top:4px}
|
||||
.webix_switch_handle{height:22px;width:22px;border-radius:100%;box-shadow:0 1px 5px rgba(0,0,0,.3);border:1px solid #eee;position:absolute;top:0;background-color:#fff;transition:left .3s ease;cursor:pointer;box-sizing:border-box}
|
||||
.webix_switch_box:active .webix_switch_handle,.webix_switch_handle:focus{box-shadow:0 0 2px 2px rgba(0,0,0,.2)}
|
||||
.webix_switch_text{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;padding:1px 0 0 18px;display:inline-block;box-sizing:border-box;width:100%}
|
||||
.webix_switch_on .webix_switch_text{padding:1px 18px 0 0}
|
||||
.webix_switch_box.webix_switch_on{color:#fff}
|
||||
.webix_progress_bottom,.webix_progress_top{width:100%;position:absolute;top:0;left:0;height:6px;overflow:hidden;z-index:20}
|
||||
.webix_progress_bottom{bottom:0;top:auto;height:17px}
|
||||
.webix_progress_bottom .webix_progress_state,.webix_progress_top .webix_progress_state{width:0;height:6px;background:#ffdb8f;-moz-transition:width 3s;transition:width 3s}
|
||||
|
@ -562,7 +578,7 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.webix_gage{height:100%;width:100%;transform:rotate(180deg)}
|
||||
.webix_gage_label{font-size:.9em;text-align:center;margin-top:10px}
|
||||
.webix_gage_placeholder{margin-top:-20px}
|
||||
.webix_gage_info{text-align:center;font-size:.7em;position:relative;margin:0 auto 10px}
|
||||
.webix_gage_info{text-align:center;font-size:.7em;position:relative;margin:0 auto 10px auto}
|
||||
.webix_gage_min_range{left:-74px}
|
||||
.webix_gage_max_range{right:-74px}
|
||||
.webix_gage_max_range,.webix_gage_min_range{display:inline-block;margin-top:20px;position:absolute;text-align:center;width:150px}
|
||||
|
@ -571,22 +587,190 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.webix_gage_gradient_point_animated{transition:transform 1.3s linear}
|
||||
.webix_gage_animated{stroke:#0f0;animation:gage_dash 1.3s linear forwards;transition:stroke 1.3s linear,stroke-dasharray 1.3s linear}
|
||||
.webix_gage_animated_first_load{stroke:#0f0;animation:gage_dash 1.3s linear forwards;transition:stroke 1.3s linear}
|
||||
@keyframes gage_dash{to{stroke-dashoffset:0}}
|
||||
@keyframes gage_dash{to{stroke-dashoffset:0}
|
||||
}
|
||||
.webix_bullet_name{width:100}
|
||||
.webix_bullet_header{font-weight:700;font-size:15px}
|
||||
.webix_bullet_subheader{font-size:15px}
|
||||
.webix_bullet_scale{font-size:12px;font-weight:700}
|
||||
.webix_organogram canvas{position:absolute}
|
||||
.webix_organogram_item{position:absolute;z-index:1;text-align:center;border-radius:4px;background-color:#e3f2fd;border:1px solid #bbdefb;padding:7px 7px 10px;box-sizing:border-box}
|
||||
.webix_organogram_item{position:absolute;z-index:1;text-align:center;border-radius:4px;background-color:#e3f2fd;border:1px solid #bbdefb;padding:7px 7px 10px 7px;box-sizing:border-box}
|
||||
.webix_organogram_item.webix_selected{background-color:#ffdb8f;border-color:#ffdb8f}
|
||||
.webix_organogram_list{border-radius:4px;position:absolute;z-index:1;height:auto;border:1px solid #ddd;box-sizing:border-box}
|
||||
.webix_organogram_list .webix_organogram_list_item{border:none;text-align:left;position:static;padding:5px;border-radius:0;box-sizing:border-box}
|
||||
.webix_icon,.webix_icon_btn,.webix_input_icon{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transform:translate(0,0)}
|
||||
.webix_icon,.webix_input_icon{font-size:17px;display:inline-block;width:20px}
|
||||
.webix_input_icon{float:right;font-size:19px;color:#888}
|
||||
.webix_icon_button{background-color:transparent;border:none;padding:0;cursor:pointer;position:relative}
|
||||
.webix_icon_button .webix_icon{font-size:20px;height:23px;width:21px;display:inline-block;text-align:center;color:#606060}
|
||||
.webix_icon_btn{font-size:17px;display:inline-block;text-align:center;width:24px;color:#606060}
|
||||
.webix_el_iconBbutton .webix_icon_btn{text-align:center;width:100%;padding:5px 0}
|
||||
.webix_el_icon{cursor:pointer}
|
||||
.webix_badge{background-color:#ff8839;color:#fff;border-radius:50%;font-size:12px;height:22px;min-width:22px;box-sizing:border-box;padding:0 4px;text-align:center;line-height:21px;position:absolute;right:0;top:0}
|
||||
.webix_list_item .webix_badge{position:static;float:right;margin:4px -5px 0 10px}
|
||||
.webixtype_base .webix_badge{top:50%;margin-top:-11px;margin-right:8px}
|
||||
.webix_treemap{background-color:#f5f5f5}
|
||||
.webix_treemap .webix_scroll_cont{position:relative;height:100%;width:100%}
|
||||
.webix_treemap_item{position:absolute;color:#444;overflow:hidden;text-align:left;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:3px 5px;border-width:0 1px 1px 0;border-style:solid;border-color:rgba(0,0,0,.2);background:0 0;cursor:pointer}
|
||||
.webix_treemap_level_top{z-index:1;border-color:rgba(0,0,0,.4)}
|
||||
.webix_treemap_item_bottom{border-bottom-width:0}
|
||||
.webix_treemap_item_right{border-right-width:0}
|
||||
.webix_treemap_item:hover{box-shadow:inset 0 0 5px #666}
|
||||
.webix_treemap_item.webix_selected{border-color:#ffdb8f;box-shadow:inset 0 0 1px 2px #ffdb8f}
|
||||
.webix_treemap_header{width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:0 10px;border-bottom:1px solid #a4bed4}
|
||||
.webix_treemap_header_item{cursor:pointer}
|
||||
.webix_treemap_header_item:last-child{cursor:default}
|
||||
.webix_treemap_reset{float:right;width:25px;text-align:center}
|
||||
.webix_treemap_reset:before{content:"\f00d";color:#1e2022;font-family:FontAwesome;font-size:16px;display:block;cursor:pointer}
|
||||
.webix_treemap_path_icon{width:20px;text-align:center}
|
||||
.webix_barcode{position:relative}
|
||||
.webix_barcode .webix_canvas_text{font-size:13px;padding:0 2px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.portlet_drag{position:absolute;z-index:1;top:5px;right:5px;width:18px;opacity:.5;cursor:pointer}
|
||||
.portlet_in_drag{opacity:.4}
|
||||
.portlet_marker,.portlet_markerbottom,.portlet_markerleft,.portlet_markerright,.portlet_markertop{opacity:.5;background:#9169BE;position:absolute;z-index:2;transition:top .5s,left .5s,width .5s,height .5s;top:0;left:0;width:100%;height:100%}
|
||||
.portlet_markertop{height:50%}
|
||||
.portlet_markerbottom{height:50%;top:50%}
|
||||
.portlet_markerleft{width:50%}
|
||||
.portlet_markerright{width:50%;left:50%}
|
||||
.panel_icon{position:absolute;z-index:100;top:5px;right:5px;line-height:normal;font-size:13px;width:18px;opacity:.5;cursor:pointer}
|
||||
.panel_target{position:absolute;background:rgba(120,120,120,.84);box-shadow:0 0 10px 5px #666;z-index:3}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_left{border-width:0 1px 0 0;box-shadow:2px 0 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_left.webix_animate{transition:left .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_right{left:auto;border-width:0 0 0 1px;box-shadow:-2px 0 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_right.webix_animate{transition:right .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_top{border-width:0 0 1px 0;box-shadow:0 2px 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_top .webix_win_body{position:relative}
|
||||
.webix_sidemenu_top .webix_win_body>.webix_view{position:absolute;top:auto;left:0;bottom:0}
|
||||
.webix_sidemenu_top.webix_animate,.webix_sidemenu_top.webix_animate .webix_win_body{transition:height .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_bottom{border-width:1px 0 0 0;top:auto;box-shadow:0 -2px 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_bottom.webix_animate,.webix_sidemenu_bottom.webix_animate .webix_win_body{transition:height .6s}
|
||||
.webix_sidebar{background:#ECEFF1}
|
||||
.webix_sidebar .webix_tree_item{color:#454545;height:35px;line-height:35px}
|
||||
.webix_sidebar .webix_scroll_cont>.webix_tree_leaves{padding:0}
|
||||
.webix_sidebar .webix_tree_leaves .webix_tree_leaves{margin-left:0}
|
||||
.webix_sidebar_expanded .webix_tree_item:hover,.webix_sidebar_selected{background-color:rgba(0,0,0,.02)}
|
||||
.webix_sidebar .webix_tree_item.webix_selected,.webix_sidebar .webix_tree_item.webix_selected span{background-color:#27ae60;padding-right:0}
|
||||
.webix_sidebar .webix_tree_branch_1 .webix_tree_item{padding-left:40px}
|
||||
.webix_sidebar .webix_tree_branch_1>.webix_tree_item{height:40px;line-height:40px;padding-left:0}
|
||||
.webix_sidebar .webix_tree_branch_1{border-bottom:1px solid #e5e5e5}
|
||||
.webix_sidebar .webix_tree_item span,.webix_sidebar .webix_tree_item.webix_selected span{margin:0;padding:0}
|
||||
.webix_sidebar_icon{width:40px;text-align:center}
|
||||
.webix_sidebar_dir_icon{float:right;line-height:inherit}
|
||||
.webix_sidebar_popup{border:none!important;box-shadow:2px 3px 3px #ddd}
|
||||
.webix_sidebar_popup,.webix_sidebar_popup .webix_list_item{border-radius:0}
|
||||
.webix_sidebar_popup_right{box-shadow:-1px 3px 3px #ddd}
|
||||
.webix_sidebar_popup_list.webix_sidebar_popup_left .webix_icon{float:right;line-height:inherit;width:7px}
|
||||
.webix_sidebar_popup_title{background:#ECEFF1}
|
||||
.webix_sidebar_popup_title.webix_selected{border-left-color:#27ae60;background:#27ae60}
|
||||
.webix_sidebar_popup_title .webix_template{line-height:40px;padding:0 10px;border:1px solid #E5E5E5;border-left:none}
|
||||
.webix_sidebar_selected.webix_sidebar_popup_title .webix_template{background:rgba(0,0,0,.03);border-left:none}
|
||||
.webix_sidebar_popup_list .webix_list_item{border-left:1px solid #E5E5E5;border-right:1px solid #E5E5E5}
|
||||
.webix_sidebar_popup_list .webix_list_item:first-child{border-top:1px solid #E5E5E5}
|
||||
.webix_sidebar_popup_list .webix_list_item:hover{background:#f6f9fb}
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected:hover{background:#27ae60}
|
||||
.webix_menu .webix_list_item.webix_sidebar_selected{background:rgba(0,0,0,.02)}
|
||||
.webix_menu .webix_list_item.webix_sidebar_selected:hover{background:rgba(0,0,0,.02)!important}
|
||||
.webix_view.webix_pdf{background-color:#404040;overflow:auto;-webkit-overflow-scrolling:touch}
|
||||
.webix_pdf .canvas_wrapper{margin:0 auto;box-shadow:5px 5px 15px #1c1c1c;width:100%;height:100%}
|
||||
.webix_toolbar.pdf_bar{background-color:#474747}
|
||||
.webix_toolbar.pdf_bar .webix_icon_btn{font-size:15px}
|
||||
.webix_toolbar.pdf_bar .webix_img_btn:focus,.webix_toolbar.pdf_bar .webix_img_btn:hover{background-color:#404040}
|
||||
.webix_toolbar.pdf_bar .webix_template{background-color:#3498db;color:#fff;line-height:2em}
|
||||
.webix_toolbar.pdf_bar .webix_el_box input,.webix_toolbar.pdf_bar .webix_inp_static{background-color:#5c5c5c;color:#fff;border-color:#404040}
|
||||
.webix_toolbar.pdf_bar .webix_el_box input:focus,.webix_toolbar.pdf_bar .webix_inp_static:focus{border-color:#333}
|
||||
.webix_toolbar.pdf_bar .webix_el_box .webix_input_icon{color:#fff}
|
||||
.webix_view.webix_popup.pdf_opt_list{box-shadow:5px 5px 15px #1c1c1c;border:none}
|
||||
.pdf_opt_list .webix_list{background-color:#404040;color:#fff}
|
||||
.pdf_opt_list .webix_list .webix_list_item{border-color:#474747;line-height:1.5em}
|
||||
.pdf_opt_list .webix_list .webix_list_item.webix_selected,.pdf_opt_list .webix_list .webix_list_item:hover{color:#404040;background-color:#fff}
|
||||
.webix_dbllist .webix_list{background:#ededed}
|
||||
.webix_dbllist .webix_list_item{background:#fff;margin:3px 4px 0 4px;box-sizing:border-box}
|
||||
.webix_dbllist .webix_list_item.webix_selected{color:#FFF;background:#27ae60}
|
||||
.webix_dbllist button{width:45%;height:30px;margin-top:5px;background:#fff;border-radius:6px;border:1px solid #a4bed4;cursor:pointer;font-size:13px;font-family:Helvetica,Verdana}
|
||||
.webix_dbllist button:active{box-shadow:inset 1px 1px 0 silver}
|
||||
.webix_dbllist button .webix_icon{color:#888;font-size:26px}
|
||||
.webix_dbllist button:first-child{margin-top:32px;margin-right:5%}
|
||||
.webix_dbllist button:last-child{margin-left:5%}
|
||||
.webix_dbllist .bottom_label{font-size:10px;text-transform:uppercase;background:#ededed;padding-left:13px}
|
||||
.webix_invalid .webix_list{background:#f8e2e2}
|
||||
.webix_toolbar .webix_el_label,.webix_toolbar .webix_inp_label{color:#1e2022}
|
||||
.webix_ss_sort_asc{position:absolute;float:right;right:3px;top:8px;width:7px;height:13px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR4nGNgQAKGxib/GbABkIS7b8B/DAUwCRiGK0CXwFBAb1DfP/U/LszwHwi2X7qFgUEArBtdAVwCBmAKMCSQFSDzAWXXaOHsXeqkAAAAAElFTkSuQmCC)}
|
||||
.webix_ss_sort_desc{position:absolute;right:3px;top:8px;width:7px;height:13px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR42mNgQAL1/VP/M2ADIIntF2/9x1AAlrh0C47hCmA60DFYwX88gIFGwNDY5D8uDFbg7hvwHx2jmIBTAlkB0e4BAEjlaNtBWJPnAAAAAElFTkSuQmCC)}
|
||||
.webix_group_back .webix_arrow_icon{color:#1e2022}
|
||||
.webix_menu-x .webix_list_item:active,.webix_menu-x .webix_list_item:focus,.webix_menu-x .webix_list_item:hover{background-color:rgba(255,255,255,.4)!important}
|
||||
.webix_menu .webix_list_item:active,.webix_menu .webix_list_item:hover{background-color:rgba(0,0,0,.05)!important}
|
||||
.webix_list_item .webix_submenu_icon{width:0;height:0;border-width:4px;border-style:solid}
|
||||
.webix_menu-x .webix_list_item .webix_submenu_icon{border-color:#375975 transparent transparent transparent}
|
||||
.webix_menu .webix_list_item .webix_submenu_icon{border-color:transparent transparent transparent #375975}
|
||||
.webix_popup_title{color:#1e2022!important;background:#e3e3e3!important;font-size:15px!important;font-weight:700;border-bottom:1px solid #dedede!important;text-shadow:none!important}
|
||||
.webix_modal_box{background:#ebebeb!important;border:1px solid #a4bed4!important}
|
||||
.confirmButton{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.confirmButtonActive{background:#fff}
|
||||
.webix_item_tab{font-size:13px}
|
||||
.buttonStyle{font-size:13px;font-family:Helvetica,Verdana}
|
||||
.activeShadow{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}
|
||||
.webix_img_btn_abs:active+input,.webix_inp_counter_next:active,.webix_inp_counter_prev:active,.webixtype_base:active{background:#f5f5f5;box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background-repeat:none}
|
||||
.webix_icon_button:active,.webix_img_btn:active,.webix_img_btn_top:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background-color:rgba(0,0,0,.05)}
|
||||
.webix_pressed .webix_img_btn_abs+input,.webix_pressed .webixtype_base{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background:#f5f5f5!important}
|
||||
.webix_slider_vertical .webix_slider_box{margin-top:-8px}
|
||||
.webix_rangeslider .webix_slider_title_box{height:17px}
|
||||
.webix_switch_box.webix_switch_on{background-color:#a4bed4}
|
||||
.webix_switch_text{line-height:21px}
|
||||
.webix_accordionitem_label .webix_icon{font-size:19px;width:25px}
|
||||
.webix_accordionitem.vertical>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAARUlEQVR42o2PAQYAMAwD9+iEFvTpnZYZU7EQRa4kaxKAXD9y9yTZluCBALRJpATNrIG6rAdjjmBVeCuB6EyAYkNEiDE33yMJRSaycR8/AAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.vertical.collapsed>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAASElEQVR42n2PMQoAMAgD++gEdPLpFkshS9oDEcxlcA1V1euNcpI9k5m2MPfrqABCBS8KBptAR8QJZks0kGjgjMQn/oc/AKy4Acp9RSZl+HEYAAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAASUlEQVR42p2QMQoAQQgD79EZ0Mqn5xCu2cPdYgUbJ0rMMxXgLeiuKq8gsJAz8weQ0QiwJEfECnr4wdlEnwJ68+yyhReC+c85oRecj0Um+pmo9wAAAABJRU5ErkJggg==);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal:last-child>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAARElEQVR42qXPsQoAIAhF0T76PdDJT7cUmtQhcmk4N8QVQ9JXN2bmgWOgqp+BiCRG2AYAMoi3/LxYdyagAnhA6G93TrABZaJFJjrFY8IAAAAASUVORK5CYII=);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal.collapsed:last-child>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAASElEQVR42n2PMQoAMAgD++gEdPLpFkshS9oDEcxlcA1V1euNcpI9k5m2MPfrqABCBS8KBptAR8QJZks0kGjgjMQn/oc/AKy4Acp9RSZl+HEYAAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal.collapsed>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAARUlEQVR42o2PAQYAMAwD9+iEFvTpnZYZU7EQRa4kaxKAXD9y9yTZluCBALRJpATNrIG6rAdjjmBVeCuB6EyAYkNEiDE33yMJRSaycR8/AAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_progress_bottom,.webix_progress_top{background:#f7f7f7;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f2f2f2),color-stop(50%,#f7f7f7),color-stop(100%,#f2f2f2));background-image:-webkit-linear-gradient(top,#f2f2f2 0,#f7f7f7 50%,#f2f2f2 100%);background-image:-moz-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%);background-image:-ms-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%);background-image:-o-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%);background-position:0 1px;background-repeat:repeat-x}
|
||||
.webix_daterange .webix_range_timepicker .webix_cal_time{padding:5px 15px}
|
||||
.webix_daterange .webix_range_footer .webix_template{padding:10px 0}
|
||||
.webix_cal_range{background-color:#fff4dc}
|
||||
.webix_item_tab .webix_icon{width:30px;font-size:19px}
|
||||
.webix_tab_more_icon{border-bottom:1px solid #a4bed4}
|
||||
.webix_skin_mark{height:110px}
|
||||
.webix_sparklines{padding:1px 0;box-sizing:border-box}
|
||||
.webix_sparklines svg{box-sizing:border-box}
|
||||
.webix_sparklines_line{stroke:#3498db;stroke-width:1;fill:transparent;stroke-linecap:round}
|
||||
.webix_sparklines_item{fill:#3498db;stroke-width:1}
|
||||
.webix_sparklines_bar{fill:#6dbcf0}
|
||||
.webix_sparklines_bar_negative{fill:#d86c79}
|
||||
.webix_sparklines_area{fill:#e5eef4}
|
||||
.webix_sparklines_origin{stroke:#888;stroke-width:1}
|
||||
.webix_sparklines_event_area{fill:transparent}
|
||||
.webix_sparklines_area_chart .webix_sparklines_event_area:hover,.webix_sparklines_line_chart .webix_sparklines_event_area:hover,.webix_sparklines_splinearea_chart .webix_sparklines_event_area:hover{fill:rgba(220,220,220,.4);stroke:rgba(255,255,255,.6)}
|
||||
.webix_sparklines_bar_chart .webix_sparklines_event_area:hover,.webix_sparklines_pie_chart .webix_sparklines_event_area:hover{fill:rgba(255,255,255,.3)}
|
||||
.webix_ui_print{display:none}
|
||||
body.webix_print{margin-top:0}
|
||||
@media print{body.webix_print{overflow:visible!important;background-color:none!important}
|
||||
body.webix_print>*{display:none}
|
||||
body.webix_print *{visibility:hidden}
|
||||
.webix_ui_print{display:block!important;margin:0!important;visibility:visible!important}
|
||||
.webix_ui_print *{visibility:visible!important}
|
||||
.webix_print_noscroll{height:auto!important;width:auto!important}
|
||||
.webix_print_noscroll,.webix_print_noscroll .webix_scroll_cont{overflow:visible!important}
|
||||
.webix_print_pagebreak{page-break-after:always}
|
||||
.webix_print_footer,.webix_print_header{display:block!important;margin:20px 0;text-align:center;height:auto!important;visibility:visible!important}
|
||||
.webix_print_footer *,.webix_print_header *{visibility:visible!important}
|
||||
.webix_table_print{display:table;visibility:visible!important;table-layout:fixed;width:100%;border:1px solid #ebebeb;margin-bottom:20px;position:initial}
|
||||
.webix_table_print td{overflow:hidden}
|
||||
.webix_table_print tr{page-break-inside:avoid}
|
||||
.webix_table_print .webix_cell{display:table-cell!important;border-right:1px solid #ebebeb;border-bottom:1px solid #ebebeb;padding:0 10px;white-space:nowrap}
|
||||
.webix_table_print .webix_header_cell{display:table-cell;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:#e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff));background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-position:0 1px;background-repeat:repeat-x;border-right:1px solid #a4bed4;border-bottom:1px solid #a4bed4}
|
||||
.webix_table_print .webix_footer_cell{display:table-cell;background:#fafafa;border-right:1px solid #ebebeb;border-top:1px solid #ebebeb;border-bottom:1px solid #ebebeb}
|
||||
.webix_table_print .webix_cell.webix_dtable_span{position:initial!important;white-space:normal}
|
||||
.webix_table_print .webix_rotate{transform-origin:center 40%!important;-webkit-transform-origin:center 40%!important}
|
||||
.webix_table_print.borderless,.webix_table_print.borderless .webix_cell{border:none}
|
||||
.webix_table_print.webix_view.webix_list-x{white-space:normal}
|
||||
.webix_table_print.webix_view.webix_list-x .webix_list_item{display:table-cell}
|
||||
}
|
||||
/*!
|
||||
* Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.7.0);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0) format('embedded-opentype'),url(../fonts/fontawesome-webfont.woff2?v=4.7.0) format('woff2'),url(../fonts/fontawesome-webfont.woff?v=4.7.0) format('woff'),url(../fonts/fontawesome-webfont.ttf?v=4.7.0) format('truetype'),url(../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular) format('svg');font-weight:400;font-style:normal}
|
||||
.fa,.webix_icon,.webix_icon_btn,.webix_input_icon{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transform:translate(0,0)}
|
||||
.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transform:translate(0,0)}
|
||||
.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}
|
||||
.fa-2x{font-size:2em}
|
||||
.fa-3x{font-size:3em}
|
||||
|
@ -597,7 +781,7 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.fa-ul>li{position:relative}
|
||||
.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}
|
||||
.fa-li.fa-lg{left:-1.85714286em}
|
||||
.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}
|
||||
.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}
|
||||
.fa-pull-left{float:left}
|
||||
.fa-pull-right{float:right}
|
||||
.fa.fa-pull-left{margin-right:.3em}
|
||||
|
@ -609,9 +793,11 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}
|
||||
.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}
|
||||
@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}
|
||||
100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}
|
||||
100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}
|
||||
}
|
||||
@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}
|
||||
100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}
|
||||
100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}
|
||||
}
|
||||
.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}
|
||||
.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}
|
||||
.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}
|
||||
|
@ -1300,140 +1486,6 @@ label.webix_required:after{padding-left:4px;content:"*";color:red}
|
|||
.fa-meetup:before{content:"\f2e0"}
|
||||
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
|
||||
.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
|
||||
.webix_icon,.webix_input_icon{font-size:17px;display:inline-block;width:20px}
|
||||
.webix_input_icon{float:right;font-size:19px;color:#888}
|
||||
.webix_icon_button{background-color:transparent;border:none;padding:0;cursor:pointer;position:relative}
|
||||
.webix_icon_button .webix_icon{font-size:20px;height:23px;width:21px;display:inline-block;text-align:center;color:#606060}
|
||||
.webix_icon_btn{font-size:17px;display:inline-block;text-align:center;width:24px;color:#606060}
|
||||
.webix_el_iconBbutton .webix_icon_btn{text-align:center;width:100%;padding:5px 0}
|
||||
.webix_el_icon{cursor:pointer}
|
||||
.webix_badge{background-color:#ff8839;color:#fff;border-radius:50%;font-size:12px;height:22px;min-width:22px;box-sizing:border-box;padding:0 4px;text-align:center;line-height:21px;position:absolute;right:0;top:0}
|
||||
.webix_list_item .webix_badge{position:static;float:right;margin:4px -5px 0 10px}
|
||||
.webixtype_base .webix_badge{top:50%;margin-top:-11px;margin-right:8px}
|
||||
.webix_treemap{background-color:#f5f5f5}
|
||||
.webix_treemap .webix_scroll_cont{position:relative;height:100%;width:100%}
|
||||
.webix_treemap_item{position:absolute;color:#444;overflow:hidden;text-align:left;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:3px 5px;border-width:0 1px 1px 0;border-style:solid;border-color:rgba(0,0,0,.2);background:0 0}
|
||||
.webix_treemap_level_top{z-index:1;border-color:rgba(0,0,0,.4)}
|
||||
.webix_treemap_item_bottom{border-bottom-width:0}
|
||||
.webix_treemap_item_right{border-right-width:0}
|
||||
.webix_treemap_item:hover{box-shadow:inset 0 0 5px #666}
|
||||
.webix_treemap_item.webix_selected{border-color:#ffdb8f;box-shadow:inset 0 0 1px 2px #ffdb8f}
|
||||
.webix_treemap_header{width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:0 10px;border-bottom:1px solid #a4bed4}
|
||||
.webix_treemap_header_item{cursor:pointer}
|
||||
.webix_treemap_header_item:last-child{cursor:default}
|
||||
.webix_treemap_reset{float:right;width:25px;text-align:center}
|
||||
.webix_treemap_reset:before{content:"\f00d";color:#1e2022;font-family:FontAwesome;font-size:16px;display:block;cursor:pointer}
|
||||
.webix_treemap_path_icon{width:20px;text-align:center}
|
||||
.webix_barcode{position:relative}
|
||||
.webix_barcode .webix_canvas_text{font-size:13px;padding:0 2px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
.portlet_drag{position:absolute;z-index:1;top:5px;right:5px;width:18px;opacity:.5;cursor:pointer}
|
||||
.portlet_in_drag{opacity:.4}
|
||||
.portlet_marker,.portlet_markerbottom,.portlet_markerleft,.portlet_markerright,.portlet_markertop{opacity:.5;background:#9169BE;position:absolute;transition:top .5s,left .5s,width .5s,height .5s;top:0;left:0;width:100%;height:100%}
|
||||
.portlet_markertop{height:50%}
|
||||
.portlet_markerbottom{height:50%;top:50%}
|
||||
.portlet_markerleft{width:50%}
|
||||
.portlet_markerright{width:50%;left:50%}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_left{border-width:0 1px 0 0;box-shadow:2px 0 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_left.webix_animate{transition:left .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_right{left:auto;border-width:0 0 0 1px;box-shadow:-2px 0 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_right.webix_animate{transition:right .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_top{border-width:0 0 1px;box-shadow:0 2px 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_top .webix_win_body{position:relative}
|
||||
.webix_sidemenu_top .webix_win_body>.webix_view{position:absolute;top:auto;left:0;bottom:0}
|
||||
.webix_sidemenu_top.webix_animate,.webix_sidemenu_top.webix_animate .webix_win_body{transition:height .6s}
|
||||
.webix_popup.webix_sidemenu.webix_sidemenu_bottom{border-width:1px 0 0;top:auto;box-shadow:0 -2px 2px rgba(0,0,0,.05)}
|
||||
.webix_sidemenu_bottom.webix_animate,.webix_sidemenu_bottom.webix_animate .webix_win_body{transition:height .6s}
|
||||
.webix_view.webix_pdf{background-color:#404040;overflow:auto;-webkit-overflow-scrolling:touch}
|
||||
.webix_pdf .canvas_wrapper{margin:0 auto;box-shadow:5px 5px 15px #1c1c1c;width:100%;height:100%}
|
||||
.webix_toolbar.pdf_bar{background-color:#474747}
|
||||
.webix_toolbar.pdf_bar .webix_icon_btn{font-size:15px}
|
||||
.webix_toolbar.pdf_bar .webix_img_btn:focus,.webix_toolbar.pdf_bar .webix_img_btn:hover{background-color:#404040}
|
||||
.webix_toolbar.pdf_bar .webix_template{background-color:#3498db;color:#fff;line-height:2em}
|
||||
.webix_toolbar.pdf_bar .webix_el_box input,.webix_toolbar.pdf_bar .webix_inp_static{background-color:#5c5c5c;color:#fff;border-color:#404040}
|
||||
.webix_toolbar.pdf_bar .webix_el_box input:focus,.webix_toolbar.pdf_bar .webix_inp_static:focus{border-color:#333}
|
||||
.webix_toolbar.pdf_bar .webix_el_box .webix_input_icon{color:#fff}
|
||||
.webix_view.webix_popup.pdf_opt_list{box-shadow:5px 5px 15px #1c1c1c;border:none}
|
||||
.pdf_opt_list .webix_list{background-color:#404040;color:#fff}
|
||||
.pdf_opt_list .webix_list .webix_list_item{border-color:#474747;line-height:1.5em}
|
||||
.pdf_opt_list .webix_list .webix_list_item.webix_selected,.pdf_opt_list .webix_list .webix_list_item:hover{color:#404040;background-color:#fff}
|
||||
.webix_dbllist .webix_list{background:#ededed}
|
||||
.webix_dbllist .webix_list_item{background:#fff;margin:3px 4px 0;box-sizing:border-box}
|
||||
.webix_dbllist .webix_list_item.webix_selected{color:#FFF;background:#27ae60}
|
||||
.webix_dbllist button{width:45%;height:30px;margin-top:5px;background:#fff;border-radius:6px;border:1px solid #a4bed4;cursor:pointer;font-size:13px;font-family:Helvetica,Verdana}
|
||||
.webix_dbllist button:active{box-shadow:inset 1px 1px 0 silver}
|
||||
.webix_dbllist button .webix_icon{color:#888;font-size:26px}
|
||||
.webix_dbllist button:first-child{margin-top:32px;margin-right:5%}
|
||||
.webix_dbllist button:last-child{margin-left:5%}
|
||||
.webix_dbllist .bottom_label{font-size:10px;text-transform:uppercase;background:#ededed;padding-left:13px}
|
||||
.webix_invalid .webix_list{background:#f8e2e2}
|
||||
.webix_toolbar .webix_el_label,.webix_toolbar .webix_inp_label{color:#1e2022}
|
||||
.webix_ss_sort_asc{position:absolute;float:right;right:3px;top:8px;width:7px;height:13px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR4nGNgQAKGxib/GbABkIS7b8B/DAUwCRiGK0CXwFBAb1DfP/U/LszwHwi2X7qFgUEArBtdAVwCBmAKMCSQFSDzAWXXaOHsXeqkAAAAAElFTkSuQmCC)}
|
||||
.webix_ss_sort_desc{position:absolute;right:3px;top:8px;width:7px;height:13px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR42mNgQAL1/VP/M2ADIIntF2/9x1AAlrh0C47hCmA60DFYwX88gIFGwNDY5D8uDFbg7hvwHx2jmIBTAlkB0e4BAEjlaNtBWJPnAAAAAElFTkSuQmCC)}
|
||||
.webix_group_back .webix_arrow_icon{color:#1e2022}
|
||||
.webix_menu-x .webix_list_item:active,.webix_menu-x .webix_list_item:focus,.webix_menu-x .webix_list_item:hover{background-color:rgba(255,255,255,.4)!important}
|
||||
.webix_menu .webix_list_item:active,.webix_menu .webix_list_item:hover{background-color:rgba(0,0,0,.05)!important}
|
||||
.webix_list_item .webix_submenu_icon{width:0;height:0;border-width:4px;border-style:solid}
|
||||
.webix_menu-x .webix_list_item .webix_submenu_icon{border-color:#375975 transparent transparent}
|
||||
.webix_menu .webix_list_item .webix_submenu_icon{border-color:transparent transparent transparent #375975}
|
||||
.webix_popup_title{color:#1e2022!important;background:#e3e3e3!important;font-size:15px!important;font-weight:700;border-bottom:1px solid #dedede!important;text-shadow:none!important}
|
||||
.webix_modal_box{background:#ebebeb!important;border:1px solid #a4bed4!important}
|
||||
.confirmButton{color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%)}
|
||||
.confirmButtonActive{background:#fff}
|
||||
.webix_item_tab{font-size:13px}
|
||||
.buttonStyle{font-size:13px;font-family:Helvetica,Verdana}
|
||||
.activeShadow{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}
|
||||
.webix_img_btn_abs:active+input,.webix_inp_counter_next:active,.webix_inp_counter_prev:active,.webixtype_base:active{background:none #f5f5f5;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}
|
||||
.webix_icon_button:active,.webix_img_btn:active,.webix_img_btn_top:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background-color:rgba(0,0,0,.05)}
|
||||
.webix_pressed .webix_img_btn_abs+input,.webix_pressed .webixtype_base{box-shadow:inset 0 3px 5px rgba(0,0,0,.125);background:#f5f5f5!important}
|
||||
.webix_slider_vertical .webix_slider_box{margin-top:-8px}
|
||||
.webix_accordionitem_label .webix_icon{font-size:19px;width:25px}
|
||||
.webix_accordionitem.vertical>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAARUlEQVR42o2PAQYAMAwD9+iEFvTpnZYZU7EQRa4kaxKAXD9y9yTZluCBALRJpATNrIG6rAdjjmBVeCuB6EyAYkNEiDE33yMJRSaycR8/AAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.vertical.collapsed>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAASElEQVR42n2PMQoAMAgD++gEdPLpFkshS9oDEcxlcA1V1euNcpI9k5m2MPfrqABCBS8KBptAR8QJZks0kGjgjMQn/oc/AKy4Acp9RSZl+HEYAAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAASUlEQVR42p2QMQoAQQgD79EZ0Mqn5xCu2cPdYgUbJ0rMMxXgLeiuKq8gsJAz8weQ0QiwJEfECnr4wdlEnwJ68+yyhReC+c85oRecj0Um+pmo9wAAAABJRU5ErkJggg==);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal:last-child>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAARElEQVR42qXPsQoAIAhF0T76PdDJT7cUmtQhcmk4N8QVQ9JXN2bmgWOgqp+BiCRG2AYAMoi3/LxYdyagAnhA6G93TrABZaJFJjrFY8IAAAAASUVORK5CYII=);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal.collapsed:last-child>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAASElEQVR42n2PMQoAMAgD++gEdPLpFkshS9oDEcxlcA1V1euNcpI9k5m2MPfrqABCBS8KBptAR8QJZks0kGjgjMQn/oc/AKy4Acp9RSZl+HEYAAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_accordionitem.horizontal.collapsed>.webix_accordionitem_header .webix_accordionitem_button{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAARUlEQVR42o2PAQYAMAwD9+iEFvTpnZYZU7EQRa4kaxKAXD9y9yTZluCBALRJpATNrIG6rAdjjmBVeCuB6EyAYkNEiDE33yMJRSaycR8/AAAAAElFTkSuQmCC);background-repeat:no-repeat}
|
||||
.webix_progress_bottom,.webix_progress_top{background:0 1px repeat-x #f7f7f7;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f2f2f2),color-stop(50%,#f7f7f7),color-stop(100%,#f2f2f2)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#f2f2f2 0,#f7f7f7 50%,#f2f2f2 100%);background-image:-moz-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%);background-image:-ms-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%);background-image:-o-linear-gradient(top,#f2f2f2 0,#f7f7f7 60%,#f2f2f2 100%)}
|
||||
.webix_daterange .webix_range_timepicker .webix_cal_time{padding:5px 15px}
|
||||
.webix_daterange .webix_range_footer .webix_template{padding:10px 0}
|
||||
.webix_cal_range{background-color:#fff4dc}
|
||||
.webix_item_tab .webix_icon{width:30px;font-size:19px}
|
||||
.webix_tab_more_icon{border-bottom:1px solid #a4bed4}
|
||||
.webix_skin_mark{height:110px}
|
||||
.webix_sparklines{padding:1px 0;box-sizing:border-box}
|
||||
.webix_sparklines svg{box-sizing:border-box}
|
||||
.webix_sparklines_line{stroke:#3498db;stroke-width:1;fill:transparent;stroke-linecap:round}
|
||||
.webix_sparklines_item{fill:#3498db;stroke-width:1}
|
||||
.webix_sparklines_bar{fill:#6dbcf0}
|
||||
.webix_sparklines_bar_negative{fill:#d86c79}
|
||||
.webix_sparklines_area{fill:#e5eef4}
|
||||
.webix_sparklines_origin{stroke:#888;stroke-width:1}
|
||||
.webix_sparklines_event_area{fill:transparent}
|
||||
.webix_sparklines_area_chart .webix_sparklines_event_area:hover,.webix_sparklines_line_chart .webix_sparklines_event_area:hover,.webix_sparklines_splinearea_chart .webix_sparklines_event_area:hover{fill:rgba(220,220,220,.4);stroke:rgba(255,255,255,.6)}
|
||||
.webix_sparklines_bar_chart .webix_sparklines_event_area:hover,.webix_sparklines_pie_chart .webix_sparklines_event_area:hover{fill:rgba(255,255,255,.3)}
|
||||
.webix_ui_print{display:none}
|
||||
body.webix_print{margin-top:0}
|
||||
@media print{body.webix_print{overflow:visible!important;background-color:none!important}
|
||||
body.webix_print>*{display:none}
|
||||
body.webix_print *{visibility:hidden}
|
||||
.webix_ui_print{display:block!important;margin:0!important;visibility:visible!important}
|
||||
.webix_ui_print *{visibility:visible!important}
|
||||
.webix_print_noscroll{height:auto!important;width:auto!important}
|
||||
.webix_print_noscroll,.webix_print_noscroll .webix_scroll_cont{overflow:visible!important}
|
||||
.webix_print_pagebreak{page-break-after:always}
|
||||
.webix_print_footer,.webix_print_header{display:block!important;margin:20px 0;text-align:center;height:auto!important;visibility:visible!important}
|
||||
.webix_print_footer *,.webix_print_header *{visibility:visible!important}
|
||||
.webix_table_print{display:table;visibility:visible!important;table-layout:fixed;width:100%;border:1px solid #ebebeb;margin-bottom:20px;position:initial}
|
||||
.webix_table_print td{overflow:hidden}
|
||||
.webix_table_print tr{page-break-inside:avoid}
|
||||
.webix_table_print .webix_cell{display:table-cell!important;border-right:1px solid #ebebeb;border-bottom:1px solid #ebebeb;padding:0 10px;white-space:nowrap}
|
||||
.webix_table_print .webix_header_cell{display:table-cell;color:#1e2022!important;box-shadow:0 1px 1px #fff inset;background:0 1px repeat-x #e5f1ff;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#eaf3ff),color-stop(50%,#e5f1ff),color-stop(100%,#d6e8ff)) 0 1px repeat-x;background-image:-webkit-linear-gradient(top,#eaf3ff 0,#e5f1ff 50%,#d6e8ff 100%);background-image:-moz-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-ms-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);background-image:-o-linear-gradient(top,#eaf3ff 0,#e5f1ff 60%,#d6e8ff 100%);border-right:1px solid #a4bed4;border-bottom:1px solid #a4bed4}
|
||||
.webix_table_print .webix_footer_cell{display:table-cell;background:#fafafa;border-right:1px solid #ebebeb;border-top:1px solid #ebebeb;border-bottom:1px solid #ebebeb}
|
||||
.webix_table_print .webix_cell.webix_dtable_span{position:initial!important;white-space:normal}
|
||||
.webix_table_print .webix_rotate{transform-origin:center 40%!important;-webkit-transform-origin:center 40%!important}
|
||||
.webix_table_print.borderless,.webix_table_print.borderless .webix_cell{border:none}
|
||||
.webix_table_print.webix_view.webix_list-x{white-space:normal}
|
||||
.webix_table_print.webix_view.webix_list-x .webix_list_item{display:table-cell}}
|
||||
.webix_strong{font-weight:700;white-space:nowrap}
|
||||
.webix_light{color:#666d73}
|
||||
.webix_debug div{border:1px solid orange;background-color:#FF9;color:#000}
|
||||
|
|
|
@ -24,12 +24,43 @@
|
|||
font-size: 125%;
|
||||
color: DarkRed;
|
||||
}
|
||||
.right_footer2 {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
font-size: 150%;
|
||||
color: DarkRed;
|
||||
}
|
||||
.right_footer3 {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
color: DarkBlue;
|
||||
}
|
||||
.footer3 {
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
color: DarkBlue;
|
||||
}
|
||||
|
||||
.lbl_partner {
|
||||
font-weight: bold;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.link_default {
|
||||
font-weight: bold;
|
||||
color: #610B0B;
|
||||
text-decoration: none;
|
||||
}
|
||||
.link_default:hover {text-decoration:underline;}
|
||||
|
||||
.link_forum {
|
||||
font-weight: bold;
|
||||
color: #610B0B;
|
||||
text-decoration: none;
|
||||
}
|
||||
.link_forum:hover {text-decoration:underline;}
|
||||
|
||||
.delete {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
|
@ -37,6 +68,10 @@
|
|||
color: red;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
color: red;
|
||||
}
|
||||
|
||||
|
||||
.cmd_close_partner div button {
|
||||
background-color: red !important;
|
||||
|
@ -67,3 +102,17 @@
|
|||
font-size: 1.5vw;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.table_sg .webix_hcell{
|
||||
background: #A64C4C;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
.table_sg .webix_column{
|
||||
font-style: italic;
|
||||
background: #FFF8DC;
|
||||
}
|
||||
.table_sg .webix_column > div{
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,519 @@
|
|||
@page{
|
||||
size: Letter;
|
||||
margin: 0.5cm;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
thead {display: table-header-group;}
|
||||
body {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.emisor-cintilla{
|
||||
background-color: #975759;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fiscales-emisor{
|
||||
color: #7d1916;
|
||||
}
|
||||
|
||||
.fiscales-emisor .telefono, .fiscales-emisor .correo, .fiscales-emisor .web{
|
||||
color: #333;
|
||||
}
|
||||
|
||||
header .titulo-vertical{
|
||||
background-color: #dbc5c6;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.receptor .nombre{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.receptor .rfc{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.receptor .direccion{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.receptor .estado{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.cfdi .folio span{
|
||||
color: #ed483d;
|
||||
}
|
||||
|
||||
.cfdi .tipo span{
|
||||
color: #ed483d;
|
||||
}
|
||||
|
||||
.cfdi .folio-fiscal span{
|
||||
color: #ed483d;
|
||||
}
|
||||
|
||||
.conceptos th{
|
||||
background-color: #975759;
|
||||
}
|
||||
|
||||
.conceptos td.clave, .conceptos td.unidad, .conceptos td.valor-unitario{
|
||||
background-color: #dbc5c6;
|
||||
}
|
||||
|
||||
.conceptos td.descripcion, .conceptos td.cantidad, .conceptos td.importe{
|
||||
background-color: #f0e7e7;
|
||||
}
|
||||
|
||||
table.subtotal th{
|
||||
background-color: #dbc5c6;
|
||||
}
|
||||
|
||||
table.subtotal td{
|
||||
background-color: #f0e7e7;
|
||||
}
|
||||
|
||||
.sello .cadenas-sello .cadena div {
|
||||
background-color: #dbc5c6;
|
||||
color: #7d1916;
|
||||
}
|
||||
|
||||
.rfc-pac {
|
||||
background-color: #dbc5c6;
|
||||
color: #7d1916;
|
||||
}
|
||||
|
||||
.cancelada{
|
||||
color: #ed3833;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Avenir Next';
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot');
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.eot?#iefix') format('embedded-opentype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff2') format('woff2'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.woff') format('woff'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.ttf') format('truetype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Regular.svg#AvenirNextLTPro-Regular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Avenir Next';
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot');
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.eot?#iefix') format('embedded-opentype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff2') format('woff2'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.woff') format('woff'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.ttf') format('truetype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-Bold.svg#AvenirNextLTPro-Bold') format('svg');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Avenir Next';
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-It.eot');
|
||||
src: url('/static/fonts/avenir_next/AvenirNextLTPro-It.eot?#iefix') format('embedded-opentype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-It.woff2') format('woff2'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-It.woff') format('woff'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-It.ttf') format('truetype'),
|
||||
url('/static/fonts/avenir_next/AvenirNextLTPro-It.svg#AvenirNextLTPro-It') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
/*
|
||||
font-family: 'Avenir Next';
|
||||
*/
|
||||
}
|
||||
|
||||
#plantilla {
|
||||
border: 1px solid #fff;
|
||||
border-color: rgb(204,204,204);
|
||||
background: #fff;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 19.5cm;
|
||||
height: 25.9cm;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cancelada{
|
||||
-ms-transform: rotate(320deg);
|
||||
-webkit-transform: rotate(320deg);
|
||||
transform: rotate(320deg);
|
||||
color: #ed3833;
|
||||
font-size: 100px;
|
||||
font-weight: bold;
|
||||
left: 18%;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 30%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.cancelada div{
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.emisor-cintilla{
|
||||
background-color: #975759;
|
||||
color: #fff;
|
||||
font-size: 7pt;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.datos-emisor .logo{
|
||||
margin-left: 20px;
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
.datos-emisor .fiscales-emisor{
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fiscales-emisor{
|
||||
color: #7d1916;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.fiscales-emisor .nombre{
|
||||
font-size: 18px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.fiscales-emisor .rfc{
|
||||
font-size: 16px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.fiscales-emisor .regimen{
|
||||
font-size: 12px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.fiscales-emisor .telefono, .fiscales-emisor .correo, .fiscales-emisor .web{
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 15px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.fiscales-emisor img{
|
||||
margin-left: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.clear{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
header .titulo-vertical{
|
||||
background-color: #dbc5c6;
|
||||
-ms-transform: rotate(270deg);
|
||||
-webkit-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
left: -31px;
|
||||
line-height: 35px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 35px;
|
||||
width: 105px;
|
||||
}
|
||||
|
||||
header .receptor{
|
||||
box-sizing: border-box;
|
||||
float: left;
|
||||
font-size: 10px;
|
||||
height: 106px;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 45px;
|
||||
padding-top: 5px;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.receptor .nombre{
|
||||
color: #000;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.receptor .rfc{
|
||||
color: #000;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.receptor .direccion,
|
||||
.receptor .estado{
|
||||
color: #000;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.receptor img{
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.receptor .correo,
|
||||
.receptor .telefono{
|
||||
float: right;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.receptor .uso-cfdi{
|
||||
color: #000;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
float: left;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
header .cfdi{
|
||||
box-sizing: border-box;
|
||||
float: right;
|
||||
font-size: 10px;
|
||||
height: 100px;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 45px;
|
||||
padding-top: 5px;
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
.cfdi .folio, .cfdi .tipo{
|
||||
color: #000;
|
||||
float: left;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.cfdi .folio span, .cfdi .tipo span{
|
||||
color: #ed483d;
|
||||
}
|
||||
|
||||
.cfdi .folio span{
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.cfdi .tipo span{
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.cfdi .folio-fiscal{
|
||||
color: #000;
|
||||
font-size: 9px;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cfdi .folio-fiscal span{
|
||||
color: #ed483d;
|
||||
}
|
||||
|
||||
.cfdi .fecha-emision, .cfdi .fecha-certificacion, .cfdi .lugar-expedicion{
|
||||
color: #333;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.conceptos{
|
||||
margin-bottom: 10px;
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.conceptos th{
|
||||
background-color: #975759;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.conceptos .clave{
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.conceptos .descripcion{
|
||||
width: 45%;
|
||||
}
|
||||
.conceptos .descripcion div{
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.conceptos .unidad{
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
.conceptos .cantidad{
|
||||
width: 9%;
|
||||
}
|
||||
|
||||
.conceptos .valor-unitario{
|
||||
width: 13%;
|
||||
}
|
||||
|
||||
.conceptos .importe{
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.conceptos td{
|
||||
background-color: #975759;
|
||||
color: #000;
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.conceptos td.clave, .conceptos td.unidad, .conceptos td.valor-unitario{
|
||||
background-color: #dbc5c6;
|
||||
}
|
||||
|
||||
.conceptos td.descripcion, .conceptos td.cantidad, .conceptos td.importe{
|
||||
background-color: #f0e7e7;
|
||||
}
|
||||
|
||||
.conceptos td.valor-unitario, .conceptos td.importe{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.total-letras{
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
margin: 5px 0;
|
||||
width: 63%;
|
||||
}
|
||||
|
||||
table.subtotal{
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: right;
|
||||
width: 37%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.subtotal th{
|
||||
background-color: #f0e7e7;
|
||||
width: 60%;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
table.subtotal td{
|
||||
background-color: #dbc5c6;
|
||||
width: 40%;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
.condiciones-pago{
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.notas{
|
||||
float: left;
|
||||
font-size: 11px;
|
||||
margin: 20px 0;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.formapago-metodopago, .moneda-tipocambio, .tiporelacion, .relacionados{
|
||||
float: left;
|
||||
font-size: 11px;
|
||||
line-height: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.factura-info{
|
||||
float: left;
|
||||
font-size: 11px;
|
||||
line-height: 13px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.tipocomite, .tipoproceso, .idcontabilidad{
|
||||
float: right;
|
||||
font-size: 10px;
|
||||
line-height: 12px;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.sello{
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.sello .cbb{
|
||||
border: 1px solid #000;
|
||||
height: auto;
|
||||
margin-top: 10px;
|
||||
margin-right: 1px;
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.sello .cadenas-sello{
|
||||
color: #000;
|
||||
float: right;
|
||||
font-size: 8px;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
width: 79%;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.sello .cadenas-sello .cadena{
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.sello .cadenas-sello .cadena div{
|
||||
font-weight: normal;
|
||||
background-color: #dbc5c6;
|
||||
color: #7d1916;
|
||||
}
|
||||
|
||||
.cadena-original{
|
||||
color: #000;
|
||||
float: right;
|
||||
font-size: 8px;
|
||||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
width: 99%;
|
||||
margin: 5px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.cadena-original div{
|
||||
font-weight: normal;
|
||||
background-color: #dbc5c6;
|
||||
color: #7d1916;
|
||||
}
|
||||
|
||||
.rfc-pac{
|
||||
background-color: #dbc5c6;
|
||||
color: #7d1916;
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
|
||||
/* SideBar*/
|
||||
.webix_sidebar{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item {
|
||||
color: #454545;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.webix_sidebar .webix_scroll_cont > .webix_tree_leaves {
|
||||
padding: 0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_leaves .webix_tree_leaves {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.webix_sidebar_selected,
|
||||
.webix_sidebar_expanded .webix_tree_item:hover{
|
||||
background-color: rgba(0,0,0,0.02);
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected,
|
||||
.webix_sidebar .webix_tree_item.webix_selected span{
|
||||
background-color: #27ae60;
|
||||
padding-right:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1 .webix_tree_item{
|
||||
padding-left:40px;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1>.webix_tree_item{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left:0;
|
||||
}
|
||||
.webix_sidebar .webix_tree_branch_1{
|
||||
border-bottom:1px solid #e5e5e5;
|
||||
}
|
||||
.webix_sidebar .webix_tree_item.webix_selected span,
|
||||
.webix_sidebar .webix_tree_item span{
|
||||
margin:0;
|
||||
padding:0px;
|
||||
}
|
||||
.webix_sidebar_icon{
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webix_sidebar_dir_icon{
|
||||
float: right;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/*SubMenu (Popup) */
|
||||
.webix_sidebar_popup{
|
||||
border:none !important;
|
||||
box-shadow: 2px 3px 3px #ddd;
|
||||
}
|
||||
.webix_sidebar_popup, .webix_sidebar_popup .webix_list_item{
|
||||
border-radius:0;
|
||||
}
|
||||
.webix_sidebar_popup_right{
|
||||
box-shadow: -1px 3px 3px #ddd;
|
||||
}
|
||||
/*SubMenu: title*/
|
||||
.webix_sidebar_popup_title{
|
||||
background: #ECEFF1;
|
||||
}
|
||||
.webix_sidebar_popup_title.webix_selected{
|
||||
border-left-color: #27ae60;
|
||||
background: #27ae60;
|
||||
}
|
||||
.webix_sidebar_popup_title .webix_template{
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #E5E5E5;
|
||||
border-left:none;
|
||||
}
|
||||
.webix_sidebar_selected.webix_sidebar_popup_title .webix_template{
|
||||
background: rgba(0,0,0,0.03);
|
||||
border-left: none;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item{
|
||||
border-left: 1px solid #E5E5E5;
|
||||
border-right: 1px solid #E5E5E5;
|
||||
}
|
||||
/*SubMenu: list*/
|
||||
.webix_sidebar_popup_list .webix_list_item:first-child{
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
.webix_sidebar_popup_list .webix_list_item:hover{
|
||||
background: #f6f9fb;
|
||||
}
|
||||
|
||||
.webix_sidebar_popup_list .webix_list_item.webix_selected:hover{
|
||||
background: #27ae60;
|
||||
}
|
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 191 KiB |
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 754 B After Width: | Height: | Size: 380 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
|
@ -4,12 +4,48 @@ var gi = null
|
|||
function configuracion_inicial(){
|
||||
webix.ajax().get('/values/admin', function(text, data){
|
||||
var values = data.json()
|
||||
$$('cmd_ir_al_admin').show(values)
|
||||
show('cmd_ir_al_admin', values)
|
||||
})
|
||||
webix.ajax().get('/values/main', function(text, data){
|
||||
webix.ajax().sync().get('/values/main', function(text, data){
|
||||
var values = data.json()
|
||||
$$('lbl_title_main').setValue(values.empresa)
|
||||
var pos = 4
|
||||
if(values.escuela){
|
||||
var node = {
|
||||
id: 'app_school',
|
||||
icon: 'graduation-cap',
|
||||
value: 'Escuela'}
|
||||
$$('main_sidebar').add(node, pos)
|
||||
pos += 1
|
||||
}
|
||||
if(values.nomina){
|
||||
var node = {
|
||||
id: 'app_nomina',
|
||||
icon: 'users',
|
||||
value: 'Nómina'}
|
||||
$$('main_sidebar').add(node, pos)
|
||||
pos += 1
|
||||
}
|
||||
if(values.punto_de_venta){
|
||||
var node = {
|
||||
id: 'app_tickets',
|
||||
icon: 'money',
|
||||
value: 'Punto de venta'}
|
||||
$$('main_sidebar').add(node, pos)
|
||||
}
|
||||
|
||||
$$('cmd_update_timbres').define('badge', values.timbres)
|
||||
$$('cmd_update_timbres').refresh()
|
||||
add_config({'key': 'decimales_precios', 'value': values.decimales_precios})
|
||||
add_config({'key': 'used_cfdi_pays', 'value': values.pagos})
|
||||
add_config({'key': 'multi_currency', 'value': values.multi_currency})
|
||||
add_config({'key': 'pays_data_bank', 'value': values.pays_data_bank})
|
||||
add_config({'key': 'show_filter_by_day', 'value': values.show_filter_by_day})
|
||||
|
||||
})
|
||||
|
||||
get_way_payment()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,68 +60,22 @@ var controllers = {
|
|||
$$('menu_user').attachEvent('onMenuItemClick', menu_user_click);
|
||||
configuracion_inicial()
|
||||
|
||||
//~ Partner
|
||||
$$('cmd_new_partner').attachEvent('onItemClick', cmd_new_partner_click);
|
||||
$$('cmd_new_contact').attachEvent('onItemClick', cmd_new_contact_click);
|
||||
$$('cmd_edit_partner').attachEvent('onItemClick', cmd_edit_partner_click);
|
||||
$$('cmd_delete_partner').attachEvent('onItemClick', cmd_delete_partner_click);
|
||||
$$('cmd_save_partner').attachEvent('onItemClick', cmd_save_partner_click);
|
||||
$$('cmd_cancel_partner').attachEvent('onItemClick', cmd_cancel_partner_click);
|
||||
$$('cmd_cancel_contact').attachEvent('onItemClick', cmd_cancel_contact_click);
|
||||
$$('codigo_postal').attachEvent('onKeyPress', postal_code_key_press);
|
||||
$$('codigo_postal').attachEvent('onTimedKeyPress', postal_code_key_up);
|
||||
$$('colonia').attachEvent('onFocus', colonia_on_focus)
|
||||
$$("tipo_persona").attachEvent( "onChange", opt_tipo_change)
|
||||
$$("es_cliente").attachEvent( "onChange", is_client_change)
|
||||
$$("es_proveedor").attachEvent( "onChange", is_supplier_change)
|
||||
$$("rfc").attachEvent( "onBlur", rfc_lost_focus)
|
||||
$$('multi').attachEvent('onViewChange', multi_change)
|
||||
//~ Products
|
||||
$$("cmd_new_product").attachEvent("onItemClick", cmd_new_product_click)
|
||||
$$("cmd_edit_product").attachEvent("onItemClick", cmd_edit_product_click)
|
||||
$$("cmd_delete_product").attachEvent("onItemClick", cmd_delete_product_click)
|
||||
$$("cmd_save_product").attachEvent("onItemClick", cmd_save_product_click)
|
||||
$$("cmd_cancel_product").attachEvent("onItemClick", cmd_cancel_product_click)
|
||||
$$("chk_automatica").attachEvent("onChange", chk_automatica_change)
|
||||
$$("valor_unitario").attachEvent("onChange", valor_unitario_change)
|
||||
$$("clave_sat").attachEvent('onSearchIconClick', clave_sat_icon_click)
|
||||
//~ Invoices
|
||||
$$('cmd_new_invoice').attachEvent("onItemClick", cmd_new_invoice_click)
|
||||
$$('cmd_refacturar').attachEvent("onItemClick", cmd_refacturar_click)
|
||||
$$('cmd_delete_invoice').attachEvent("onItemClick", cmd_delete_invoice_click)
|
||||
$$('cmd_timbrar').attachEvent('onItemClick', cmd_timbrar_click)
|
||||
$$('cmd_close_invoice').attachEvent('onItemClick', cmd_close_invoice_click)
|
||||
$$('search_client_id').attachEvent('onKeyPress', search_client_id_key_press)
|
||||
$$('grid_clients_found').attachEvent('onValueSuggest', grid_clients_found_click)
|
||||
$$('search_product_id').attachEvent('onKeyPress', search_product_id_key_press)
|
||||
$$('grid_products_found').attachEvent('onValueSuggest', grid_products_found_click)
|
||||
$$('grid_details').attachEvent('onItemClick', grid_details_click)
|
||||
$$('grid_details').attachEvent('onHeaderClick', grid_details_header_click)
|
||||
$$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start)
|
||||
$$('grid_details').attachEvent('onBeforeEditStop', grid_details_before_edit_stop)
|
||||
$$('cmd_invoice_timbrar').attachEvent('onItemClick', cmd_invoice_timbrar_click)
|
||||
$$('cmd_invoice_sat').attachEvent('onItemClick', cmd_invoice_sat_click)
|
||||
$$('cmd_invoice_cancelar').attachEvent('onItemClick', cmd_invoice_cancelar_click)
|
||||
$$('grid_invoices').attachEvent('onItemClick', grid_invoices_click)
|
||||
$$('filter_year').attachEvent('onChange', filter_year_change)
|
||||
$$('filter_month').attachEvent('onChange', filter_month_change)
|
||||
$$('filter_dates').attachEvent('onChange', filter_dates_change)
|
||||
$$('cmd_prefactura').attachEvent('onItemClick', cmd_prefactura_click)
|
||||
$$('cmd_cfdi_relacionados').attachEvent('onItemClick', cmd_cfdi_relacionados_click)
|
||||
$$('lst_metodo_pago').attachEvent('onChange', lst_metodo_pago_change)
|
||||
$$('lst_serie').attachEvent('onChange', lst_serie_change)
|
||||
|
||||
var tb_invoice = $$('tv_invoice').getTabbar()
|
||||
tb_invoice.attachEvent('onChange', tb_invoice_change)
|
||||
$$('prefilter_year').attachEvent('onChange', prefilter_year_change)
|
||||
$$('prefilter_month').attachEvent('onChange', prefilter_month_change)
|
||||
$$('cmd_delete_preinvoice').attachEvent('onItemClick', cmd_delete_preinvoice_click)
|
||||
$$('cmd_facturar_preinvoice').attachEvent('onItemClick', cmd_facturar_preinvoice_click)
|
||||
$$('cmd_update_timbres').attachEvent('onItemClick', cmd_update_timbres_click)
|
||||
$$('grid_preinvoices').attachEvent('onItemClick', grid_preinvoices_click)
|
||||
|
||||
webix.extend($$('grid_invoices'), webix.ProgressBar)
|
||||
|
||||
partners_controllers.init()
|
||||
products_controllers.init()
|
||||
bancos_controllers.init()
|
||||
invoices_controllers.init()
|
||||
controllers_school.init()
|
||||
nomina_controllers.init()
|
||||
tickets_controllers.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,23 +105,6 @@ function get_partners(){
|
|||
}
|
||||
|
||||
|
||||
function get_products(){
|
||||
var grid = $$('grid_products')
|
||||
webix.ajax().get('/products', {}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
grid.clearAll();
|
||||
if (values.ok){
|
||||
grid.parse(values.rows, 'json');
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function menu_user_click(id, e, node){
|
||||
if (id == 1){
|
||||
window.location = '/logout';
|
||||
|
@ -143,16 +116,19 @@ function menu_user_click(id, e, node){
|
|||
function current_dates(){
|
||||
var fy = $$('filter_year')
|
||||
var fm = $$('filter_month')
|
||||
var fd = $$('filter_day')
|
||||
var pfy = $$('prefilter_year')
|
||||
var pfm = $$('prefilter_month')
|
||||
var d = new Date()
|
||||
|
||||
fy.blockEvent()
|
||||
fm.blockEvent()
|
||||
fd.blockEvent()
|
||||
pfy.blockEvent()
|
||||
pfm.blockEvent()
|
||||
|
||||
fm.setValue(d.getMonth() + 1)
|
||||
fd.setValue(d.getDate())
|
||||
pfm.setValue(d.getMonth() + 1)
|
||||
webix.ajax().sync().get('/values/filteryears', function(text, data){
|
||||
var values = data.json()
|
||||
|
@ -164,12 +140,14 @@ function current_dates(){
|
|||
|
||||
fy.unblockEvent()
|
||||
fm.unblockEvent()
|
||||
fd.unblockEvent()
|
||||
pfy.unblockEvent()
|
||||
pfm.unblockEvent()
|
||||
}
|
||||
|
||||
|
||||
function multi_change(prevID, nextID){
|
||||
|
||||
if(nextID == 'app_partners'){
|
||||
active = $$('multi_partners').getActiveId()
|
||||
if(active == 'partners_home'){
|
||||
|
@ -194,11 +172,36 @@ function multi_change(prevID, nextID){
|
|||
return
|
||||
}
|
||||
|
||||
if(nextID == 'app_school'){
|
||||
active = $$('multi_school').getActiveId()
|
||||
if(active == 'school_home'){
|
||||
init_config_school()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(nextID == 'app_nomina'){
|
||||
active = $$('multi_nomina').getActiveId()
|
||||
if(active == 'nomina_home'){
|
||||
default_config_nomina()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(nextID == 'app_tickets'){
|
||||
active = $$('multi_tickets').getActiveId()
|
||||
if(active == 'tickets_home'){
|
||||
configuracion_inicial_ticket()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(nextID == 'app_invoices'){
|
||||
active = $$('multi_invoices').getActiveId()
|
||||
if(active == 'invoices_home'){
|
||||
current_dates()
|
||||
get_invoices()
|
||||
validar_timbrar()
|
||||
}
|
||||
gi = $$('grid_invoices')
|
||||
return
|
||||
|
@ -216,3 +219,12 @@ function get_taxes(){
|
|||
$$("grid_product_taxes").parse(values, 'json')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_update_timbres_click(){
|
||||
webix.ajax().get('/values/timbres', function(text, data){
|
||||
var value = data.json()
|
||||
$$('cmd_update_timbres').define('badge', value)
|
||||
$$('cmd_update_timbres').refresh()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,627 @@
|
|||
var query = []
|
||||
var cfg_nomina = new Object()
|
||||
|
||||
|
||||
var nomina_controllers = {
|
||||
init: function(){
|
||||
$$('cmd_nomina_import').attachEvent('onItemClick', cmd_nomina_import_click)
|
||||
$$('cmd_empleados').attachEvent('onItemClick', cmd_empleados_click)
|
||||
$$('cmd_close_empleados').attachEvent('onItemClick', cmd_close_empleados_click)
|
||||
$$('cmd_delete_empleado').attachEvent('onItemClick', cmd_delete_empleado_click)
|
||||
$$('cmd_import_empleados').attachEvent('onItemClick', cmd_import_empleados_click)
|
||||
$$('cmd_nomina_without_stamp').attachEvent('onItemClick', cmd_nomina_without_stamp_click)
|
||||
$$('cmd_nomina_delete').attachEvent('onItemClick', cmd_nomina_delete_click)
|
||||
$$('cmd_nomina_timbrar').attachEvent('onItemClick', cmd_nomina_timbrar_click)
|
||||
$$('cmd_nomina_sat').attachEvent('onItemClick', cmd_nomina_sat_click)
|
||||
$$('cmd_nomina_log').attachEvent('onItemClick', cmd_nomina_log_click)
|
||||
$$('cmd_nomina_download').attachEvent('onItemClick', cmd_nomina_download_click)
|
||||
$$('cmd_nomina_cancel').attachEvent('onItemClick', cmd_nomina_cancel_click)
|
||||
$$('grid_nomina').attachEvent('onItemClick', grid_nomina_click)
|
||||
$$('filter_year_nomina').attachEvent('onChange', filter_year_nomina_change)
|
||||
$$('filter_month_nomina').attachEvent('onChange', filter_month_nomina_change)
|
||||
$$('filter_dates_nomina').attachEvent('onChange', filter_dates_nomina_change)
|
||||
$$('grid_nomina').attachEvent('onSelectChange', grid_nomina_on_select_change)
|
||||
webix.extend($$('grid_nomina'), webix.ProgressBar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function default_config_nomina(){
|
||||
current_dates_nomina()
|
||||
get_nomina()
|
||||
}
|
||||
|
||||
|
||||
function current_dates_nomina(){
|
||||
var fy = $$('filter_year_nomina')
|
||||
var fm = $$('filter_month_nomina')
|
||||
var d = new Date()
|
||||
|
||||
fy.blockEvent()
|
||||
fm.blockEvent()
|
||||
|
||||
fm.setValue(d.getMonth() + 1)
|
||||
webix.ajax().sync().get('/values/filteryearsnomina', function(text, data){
|
||||
var values = data.json()
|
||||
fy.getList().parse(values)
|
||||
fy.setValue(d.getFullYear())
|
||||
})
|
||||
|
||||
fy.unblockEvent()
|
||||
fm.unblockEvent()
|
||||
}
|
||||
|
||||
|
||||
function get_nomina(filters){
|
||||
var grid = $$('grid_nomina')
|
||||
grid.showProgress({type: 'icon'})
|
||||
|
||||
|
||||
webix.ajax().get('/nomina', filters, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok){
|
||||
grid.clearAll();
|
||||
grid.parse(values.rows, 'json');
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_import_click(){
|
||||
win_import_nomina.init()
|
||||
$$('win_import_nomina').show()
|
||||
}
|
||||
|
||||
|
||||
function cmd_import_template_nomina_click(){
|
||||
var form = $$('form_upload_nomina')
|
||||
|
||||
var values = form.getValues()
|
||||
|
||||
if(!$$('lst_upload_nomina').count()){
|
||||
$$('win_import_nomina').close()
|
||||
return
|
||||
}
|
||||
|
||||
if($$('lst_upload_nomina').count() > 1){
|
||||
msg = 'Selecciona solo un archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var template = $$('up_nomina').files.getItem($$('up_nomina').files.getFirstId())
|
||||
|
||||
if(template.type.toLowerCase() != 'ods'){
|
||||
msg = 'Archivo inválido.\n\nSe requiere un archivo ODS'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de importar este archivo?'
|
||||
webix.confirm({
|
||||
title: 'Importar Nómina',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
$$('up_nomina').send()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function up_nomina_upload_complete(response){
|
||||
if(response.status != 'server'){
|
||||
msg = 'Ocurrio un error al subir el archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
msg = 'Archivo subido correctamente.\n\nComenzando importación.'
|
||||
msg_ok(msg)
|
||||
$$('win_import_nomina').close()
|
||||
|
||||
webix.ajax().get('/nomina', {opt: 'import'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al importar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok){
|
||||
msg_ok(values.msg)
|
||||
get_nomina()
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_employees(){
|
||||
webix.ajax().get('/employees', {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok){
|
||||
$$('grid_employees').clearAll();
|
||||
$$('grid_employees').parse(values.rows, 'json');
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_empleados_click(){
|
||||
get_employees()
|
||||
$$('multi_nomina').setValue('nomina_empleados')
|
||||
}
|
||||
|
||||
|
||||
function cmd_close_empleados_click(){
|
||||
$$('multi_nomina').setValue('nomina_home')
|
||||
}
|
||||
|
||||
|
||||
function cmd_import_empleados_click(){
|
||||
win_import_employees.init()
|
||||
$$('win_import_employees').show()
|
||||
}
|
||||
|
||||
function cmd_import_employees_click(){
|
||||
var form = $$('form_upload_employees')
|
||||
|
||||
var values = form.getValues()
|
||||
|
||||
if(!$$('lst_upload_employees').count()){
|
||||
$$('win_import_employees').close()
|
||||
return
|
||||
}
|
||||
|
||||
if($$('lst_upload_employees').count() > 1){
|
||||
msg = 'Selecciona solo un archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var template = $$('up_employees').files.getItem($$('up_employees').files.getFirstId())
|
||||
|
||||
if(template.type.toLowerCase() != 'ods'){
|
||||
msg = 'Archivo inválido.\n\nSe requiere un archivo ODS'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de importar este archivo?'
|
||||
webix.confirm({
|
||||
title: 'Importar Empleados',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
$$('up_employees').send()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function up_employees_upload_complete(response){
|
||||
if(response.status != 'server'){
|
||||
msg = 'Ocurrio un error al subir el archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
msg = 'Archivo subido correctamente.\n\nComenzando importación.'
|
||||
msg_ok(msg)
|
||||
$$('win_import_employees').close()
|
||||
|
||||
webix.ajax().get('/employees', {opt: 'import'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al importar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok){
|
||||
msg_ok(values.msg)
|
||||
get_employees()
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function delete_empleado(id){
|
||||
webix.ajax().del('/employees', {id: id}, function(text, xml, xhr){
|
||||
var msg = 'Empleado eliminado correctamente'
|
||||
if(xhr.status == 200){
|
||||
$$('grid_employees').remove(id);
|
||||
msg_ok(msg)
|
||||
}else{
|
||||
msg = 'El Empleado tiene recibos timbrados'
|
||||
msg_error(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_delete_empleado_click(){
|
||||
var row = $$('grid_employees').getSelectedItem()
|
||||
|
||||
if (row == undefined){
|
||||
msg = 'Selecciona un Empleado'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de eliminar al Empleado?<BR><BR>'
|
||||
msg += row['nombre_completo'] + ' (' + row['rfc'] + ')'
|
||||
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
|
||||
webix.confirm({
|
||||
title: 'Eliminar Empleado',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
delete_empleado(row['id'])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_without_stamp_click(){
|
||||
get_nomina()
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_delete_click(){
|
||||
var rows = $$('grid_nomina').getSelectedItem()
|
||||
|
||||
if (rows == undefined){
|
||||
msg = 'Selecciona al menos un registro'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
var ids = []
|
||||
if(Array.isArray(rows)){
|
||||
for(var i in rows){
|
||||
ids.push(rows[i].id)
|
||||
}
|
||||
}else{
|
||||
ids.push(rows.id)
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de eliminar los recibos seleccionado?<BR><BR>'
|
||||
msg += 'ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
|
||||
msg += 'Solo se eliminan recibos no timbrados'
|
||||
webix.confirm({
|
||||
title: 'Eliminar Nomina',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
delete_nomina(ids)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function delete_nomina(ids){
|
||||
webix.ajax().del('/nomina', {id: ids}, function(text, xml, xhr){
|
||||
var msg = 'Registros eliminados correctamente'
|
||||
if (xhr.status == 200){
|
||||
get_nomina()
|
||||
msg_ok(msg)
|
||||
} else {
|
||||
msg = 'No se pudo eliminar.'
|
||||
msg_error(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_timbrar_click(){
|
||||
get_nomina()
|
||||
|
||||
msg = 'Se enviarán a timbrar todos los recibos sin timbrar<BR><BR>'
|
||||
msg += '¿Estás seguro de continuar?<BR><BR>'
|
||||
webix.confirm({
|
||||
title: 'Enviar a timbrar',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
timbrar_nomina()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function timbrar_nomina(){
|
||||
webix.ajax().get('/nomina', {opt: 'stamp'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al timbrar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if(values.ok){
|
||||
cmd_update_timbres_click()
|
||||
get_nomina()
|
||||
msg_ok(values.msg_ok)
|
||||
}
|
||||
if(values.error){
|
||||
webix.alert({
|
||||
title: 'Error al Timbrar',
|
||||
text: values.msg_error,
|
||||
type: 'alert-error'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function send_mail(row){
|
||||
if(!row.uuid){
|
||||
msg_error('La nómina no esta timbrada')
|
||||
return
|
||||
}
|
||||
var data = {'opt': 'send_mail', 'id': row.id}
|
||||
|
||||
msg = '¿Estás seguro de enviar por correo este Recibo de Nómina?'
|
||||
webix.confirm({
|
||||
title: 'Enviar Recibo de Nómina',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
webix.ajax().post('/nomina', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function grid_nomina_click(id, e, node){
|
||||
var row = this.getItem(id)
|
||||
|
||||
if(id.column == 'xml'){
|
||||
location = '/doc/nomxml/' + row.id
|
||||
}else if(id.column == 'pdf'){
|
||||
window.open('/doc/nompdf/' + row.id, '_blank')
|
||||
}else if(id.column == 'email'){
|
||||
send_mail(row)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function filter_year_nomina_change(nv, ov){
|
||||
var fm = $$('filter_month_nomina')
|
||||
filters = {'opt': 'yearmonth', 'year': nv, 'month': fm.getValue()}
|
||||
get_nomina(filters)
|
||||
}
|
||||
|
||||
|
||||
function filter_month_nomina_change(nv, ov){
|
||||
var fy = $$('filter_year_nomina')
|
||||
filters = {'opt': 'yearmonth', 'year': fy.getValue(), 'month': nv}
|
||||
get_nomina(filters)
|
||||
}
|
||||
|
||||
|
||||
function filter_dates_nomina_change(range){
|
||||
if(range.start != null && range.end != null){
|
||||
filters = {'opt': 'dates', 'range': range}
|
||||
get_nomina(filters)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_cancel_click(){
|
||||
var row = $$('grid_nomina').getSelectedItem()
|
||||
|
||||
if(row == undefined){
|
||||
msg = 'Selecciona un registro'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(Array.isArray(row)){
|
||||
msg = 'Selecciona solo un registro'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(row['estatus'] != 'Timbrado'){
|
||||
msg = 'Solo se pueden cancelar recibos timbrados'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
win_invoice_cancel_nomina.init()
|
||||
$$('win_invoice_cancel_nomina').show()
|
||||
}
|
||||
|
||||
|
||||
function cmd_win_cancel_nomina_close_click(){
|
||||
$$('win_invoice_cancel_nomina').close()
|
||||
}
|
||||
|
||||
|
||||
function cmd_invoice_cancel_nomina_click(){
|
||||
var reason = $$('lst_reasons_cancel').getValue()
|
||||
var uuid = $$('txt_cancel_uuid').getValue()
|
||||
|
||||
if(!reason){
|
||||
msg = 'Selecciona un motivo para esta cancelación'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
if(reason=='01' & !uuid){
|
||||
msg = 'Debes de capturar el UUID que reemplaza a este CFDI'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
$$('win_invoice_cancel_nomina').close()
|
||||
send_cancel_nomina(reason, uuid)
|
||||
}
|
||||
|
||||
|
||||
function send_cancel_nomina(reason, uuid){
|
||||
var grid = $$('grid_nomina')
|
||||
var row = grid.getSelectedItem()
|
||||
var data = new Object()
|
||||
data['opt'] = 'cancel'
|
||||
data['id'] = row.id
|
||||
data['args'] = {reason: reason, uuid: uuid}
|
||||
|
||||
webix.ajax().sync().post('nomina', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
grid.updateItem(row.id, values.row)
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_log_click(){
|
||||
location = '/doc/nomlog/0'
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_download_click(){
|
||||
var grid = $$('grid_nomina')
|
||||
|
||||
if(!grid.count()){
|
||||
msg = 'Sin documentos a descargar'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var ids = []
|
||||
grid.eachRow(function(row){
|
||||
var r = grid.getItem(row)
|
||||
ids.push(r.id)
|
||||
})
|
||||
|
||||
var filters = {'by': 'download', 'ids': ids}
|
||||
|
||||
webix.ajax().response('blob').get('/nomina', filters, function(text, data){
|
||||
webix.html.download(data, 'nomina.zip');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function grid_nomina_on_select_change(){
|
||||
var g = $$('grid_nomina')
|
||||
var rows = g.getSelectedItem(true)
|
||||
var total = 0
|
||||
|
||||
for (i = 0; i < rows.length; i++) {
|
||||
if(typeof(rows[i].total) == 'string'){
|
||||
total += rows[i].total.to_float()
|
||||
}else{
|
||||
total += rows[i].total
|
||||
}
|
||||
}
|
||||
g.getColumnConfig('empleado').footer[0].text = webix.i18n.priceFormat(total)
|
||||
g.refreshColumns()
|
||||
}
|
||||
|
||||
|
||||
function cmd_nomina_sat_click(){
|
||||
var g = $$('grid_nomina')
|
||||
|
||||
if(g.count() == 0){
|
||||
return
|
||||
}
|
||||
|
||||
var row = g.getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un recibo de nómina')
|
||||
return
|
||||
}
|
||||
if (row instanceof Array){
|
||||
msg_error('Selecciona solo un recibo de nómina')
|
||||
return
|
||||
}
|
||||
|
||||
if(!row.uuid){
|
||||
msg_error('La factura no esta timbrada, solo es posible consultar \
|
||||
el estatus en el SAT de facturas timbradas')
|
||||
return
|
||||
}
|
||||
|
||||
var options = {opt: 'status_sat', id: row.id}
|
||||
webix.ajax().get('/nomina', options, function(text, data){
|
||||
var value = data.json()
|
||||
if(value == 'Vigente'){
|
||||
msg_ok(value)
|
||||
}else if(value == 'uncancel'){
|
||||
ask_invoice_uncancel(row.id)
|
||||
}else{
|
||||
msg_error(value)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +1,66 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 of the License, or
|
||||
//~ (at your option) any later version.
|
||||
//~
|
||||
//~ This program is distributed in the hope that it will be useful,
|
||||
//~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//~ GNU General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var cfg_partners = new Object()
|
||||
|
||||
|
||||
var partners_controllers = {
|
||||
init: function(){
|
||||
$$('cmd_new_partner').attachEvent('onItemClick', cmd_new_partner_click);
|
||||
//~ $$('cmd_new_contact').attachEvent('onItemClick', cmd_new_contact_click);
|
||||
$$('cmd_edit_partner').attachEvent('onItemClick', cmd_edit_partner_click);
|
||||
$$('cmd_delete_partner').attachEvent('onItemClick', cmd_delete_partner_click);
|
||||
$$('cmd_save_partner').attachEvent('onItemClick', cmd_save_partner_click);
|
||||
$$('cmd_cancel_partner').attachEvent('onItemClick', cmd_cancel_partner_click);
|
||||
//~ $$('cmd_cancel_contact').attachEvent('onItemClick', cmd_cancel_contact_click);
|
||||
//~ $$('cmd_partner_zero').attachEvent('onItemClick', cmd_partner_zero_click);
|
||||
$$('codigo_postal').attachEvent('onKeyPress', postal_code_key_press);
|
||||
$$('codigo_postal').attachEvent('onTimedKeyPress', postal_code_key_up);
|
||||
$$('colonia').attachEvent('onFocus', colonia_on_focus)
|
||||
$$("tipo_persona").attachEvent( "onChange", opt_tipo_change)
|
||||
$$("es_cliente").attachEvent( "onChange", is_client_change)
|
||||
$$("es_proveedor").attachEvent( "onChange", is_supplier_change)
|
||||
$$("rfc").attachEvent( "onBlur", rfc_lost_focus)
|
||||
$$('multi').attachEvent('onViewChange', multi_change)
|
||||
$$('grid_partners').attachEvent('onItemDblClick', grid_partners_double_click)
|
||||
//~ $$('grid_partners').attachEvent('onSelectChange', grid_partners_on_select_change)
|
||||
|
||||
$$('partner_balance').attachEvent('onChange', partner_balance_on_change)
|
||||
$$('cmd_partner_add_account_bank').attachEvent('onItemClick', cmd_partner_add_account_bank_click)
|
||||
$$('grid_partner_account_bank').attachEvent('onItemClick', grid_partner_account_bank_click)
|
||||
default_config_partners()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function default_config_partners(){
|
||||
webix.ajax().get('/config', {'fields': 'partners'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
cfg_partners = values
|
||||
//~ show('cmd_partner_zero', cfg_partners['chk_config_change_balance_partner'])
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get_condicion_pago(){
|
||||
|
@ -14,8 +77,12 @@ function get_condicion_pago(){
|
|||
|
||||
|
||||
function cmd_new_partner_click(id, e, node){
|
||||
$$('form_partner').clearValidation()
|
||||
$$('form_partner_account_bank').clearValidation()
|
||||
|
||||
$$('form_partner').setValues({
|
||||
id: 0, pais: 'México', tipo_persona: 1, es_activo: true})
|
||||
id: 0, pais: 'México', tipo_persona: 1, es_activo: true,
|
||||
partner_balance: 0.00})
|
||||
$$('forma_pago').getList().load('/values/formapago')
|
||||
get_condicion_pago()
|
||||
$$('grid_partners').clearSelection()
|
||||
|
@ -25,6 +92,10 @@ function cmd_new_partner_click(id, e, node){
|
|||
get_uso_cfdi_to_table()
|
||||
query = table_usocfdi.chain().find({fisica: true}).data()
|
||||
$$('lst_uso_cfdi_socio').getList().parse(query)
|
||||
$$('partner_balance').define('readonly', !cfg_partners['chk_config_change_balance_partner'])
|
||||
get_partner_banks()
|
||||
get_partner_accounts_bank(0)
|
||||
get_sat_regimenes()
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,10 +105,12 @@ function cmd_new_contact_click(id, e, node){
|
|||
}
|
||||
|
||||
|
||||
function cmd_edit_partner_click(id, e, node){
|
||||
function cmd_edit_partner_click(){
|
||||
var msg = ''
|
||||
var row = $$('grid_partners').getSelectedItem()
|
||||
|
||||
$$('form_partner_account_bank').clearValidation()
|
||||
|
||||
if (row == undefined){
|
||||
msg = 'Selecciona un Socio de Negocio'
|
||||
msg_error(msg)
|
||||
|
@ -51,14 +124,20 @@ function cmd_edit_partner_click(id, e, node){
|
|||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
|
||||
$$('form_partner').clearValidation()
|
||||
$$('form_partner').setValues(values)
|
||||
$$('forma_pago').getList().load('/values/formapago')
|
||||
|
||||
$$('partner_balance').define('readonly', !cfg_partners['chk_config_change_balance_partner'])
|
||||
get_uso_cfdi_to_table()
|
||||
|
||||
if(values.tipo_persona == 1){
|
||||
query = table_usocfdi.chain().find({fisica: true}).data()
|
||||
get_sat_regimenes()
|
||||
}else if(values.tipo_persona == 2){
|
||||
query = table_usocfdi.chain().find({moral: true}).data()
|
||||
get_sat_regimenes(true)
|
||||
}else{
|
||||
query = [{id: 'P01', value: 'Por definir'}]
|
||||
}
|
||||
|
@ -69,12 +148,17 @@ function cmd_edit_partner_click(id, e, node){
|
|||
if(values.es_proveedor){
|
||||
$$('cuenta_proveedor').enable()
|
||||
}
|
||||
get_partner_accounts_bank(row['id'])
|
||||
pause(250)
|
||||
$$('lst_receptor_regimenes_fiscales').select(values.regimenes)
|
||||
}
|
||||
})
|
||||
|
||||
$$('multi_partners').setValue('partners_new')
|
||||
$$('tab_partner').setValue('Datos Fiscales')
|
||||
};
|
||||
get_partner_banks()
|
||||
|
||||
}
|
||||
|
||||
|
||||
function cmd_delete_partner_click(id, e, node){
|
||||
|
@ -132,12 +216,21 @@ function cmd_save_partner_click(id, e, node){
|
|||
|
||||
var values = form.getValues();
|
||||
|
||||
if(values.codigo_postal && values.codigo_postal.length != 5){
|
||||
msg = 'Longitud inválida del C.P.'
|
||||
if(!values.rfc){
|
||||
msg = 'Captura el RFC'
|
||||
msg_error(msg)
|
||||
$$('tab_partner').setValue('Datos Fiscales')
|
||||
return
|
||||
}
|
||||
|
||||
if(values.tipo_persona != 4){
|
||||
if(values.codigo_postal && values.codigo_postal.length != 5){
|
||||
msg = 'Longitud inválida del C.P.'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!values.es_cliente && !values.es_proveedor){
|
||||
msg = 'Selecciona si es cliente, proveedor o ambos'
|
||||
msg_error(msg)
|
||||
|
@ -145,6 +238,26 @@ function cmd_save_partner_click(id, e, node){
|
|||
return
|
||||
}
|
||||
|
||||
if(values.tipo_persona == 4){
|
||||
if(values.pais && values.pais.length != 3){
|
||||
msg = 'Longitud de país inválida'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var ids_regimenes = $$('lst_receptor_regimenes_fiscales').getSelectedId()
|
||||
if(values.tipo_persona < 3){
|
||||
if(!ids_regimenes){
|
||||
msg = 'Selecciona al menos un Regimen Fiscal'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
values['accounts'] = $$('grid_partner_account_bank').data.getRange()
|
||||
values['regimenes'] = ids_regimenes
|
||||
|
||||
webix.ajax().post('/partners', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico';
|
||||
|
@ -155,7 +268,7 @@ function cmd_save_partner_click(id, e, node){
|
|||
if (values.ok) {
|
||||
update_grid_partner(values)
|
||||
} else {
|
||||
msg_error(msg)
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -244,20 +357,31 @@ function opt_tipo_change(new_value, old_value){
|
|||
$$("nombre").define("value", "")
|
||||
$$("pais").define("readonly", true)
|
||||
$$("pais").define("value", PAIS)
|
||||
$$('id_fiscal').define('value', '')
|
||||
show('id_fiscal', new_value == 4)
|
||||
|
||||
$$('lst_receptor_regimenes_fiscales').clearAll()
|
||||
var regimen_616 = {id: 11, value: '[616] Sin obligaciones fiscales'}
|
||||
|
||||
if (new_value == 1 || new_value == 2){
|
||||
$$("rfc").define("value", "");
|
||||
$$("rfc").define("readonly", false);
|
||||
$$("rfc").define("value", "")
|
||||
$$("rfc").define("readonly", false)
|
||||
moral = false
|
||||
if(new_value == 2){
|
||||
moral = true
|
||||
}
|
||||
get_sat_regimenes(moral)
|
||||
} else if (new_value == 3) {
|
||||
$$("rfc").define("value", RFC_PUBLICO);
|
||||
$$("nombre").define("value", PUBLICO);
|
||||
$$("rfc").define("readonly", true);
|
||||
$$("rfc").define("value", RFC_PUBLICO)
|
||||
$$("nombre").define("value", PUBLICO)
|
||||
$$("rfc").define("readonly", true)
|
||||
$$('lst_receptor_regimenes_fiscales').parse(regimen_616)
|
||||
} else if (new_value == 4) {
|
||||
$$("rfc").define("value", RFC_EXTRANJERO);
|
||||
$$("rfc").define("readonly", true);
|
||||
$$("pais").define("readonly", false);
|
||||
$$("pais").define("value", "");
|
||||
$$("rfc").define("value", RFC_EXTRANJERO)
|
||||
$$("rfc").define("readonly", true)
|
||||
$$("pais").define("readonly", false)
|
||||
$$("pais").define("value", "")
|
||||
$$('lst_receptor_regimenes_fiscales').parse(regimen_616)
|
||||
}
|
||||
|
||||
$$("nombre").refresh();
|
||||
|
@ -275,10 +399,12 @@ function opt_tipo_change(new_value, old_value){
|
|||
}else if (new_value == 2){
|
||||
query = table_usocfdi.chain().find({moral: true}).data()
|
||||
}else{
|
||||
query = [{id: 'P01', value: 'Por definir'}]
|
||||
query = [{id: 'S01', value: '[S01] Sin efectos fiscales. '}]
|
||||
}
|
||||
$$('lst_uso_cfdi_socio').getList().parse(query)
|
||||
$$('lst_uso_cfdi_socio').refresh()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -295,9 +421,9 @@ function is_client_change(new_value, old_value){
|
|||
function is_supplier_change(new_value, old_value){
|
||||
var value = Boolean(new_value)
|
||||
if (value){
|
||||
$$("cuenta_proveedor").enable();
|
||||
$$("cuenta_proveedor").enable()
|
||||
} else {
|
||||
$$("cuenta_proveedor").disable();
|
||||
$$("cuenta_proveedor").disable()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,3 +468,201 @@ function multi_partners_change(prevID, nextID){
|
|||
//~ webix.message(prevID)
|
||||
//~ webix.message(nextID)
|
||||
}
|
||||
|
||||
|
||||
function grid_partners_double_click(id, e, node){
|
||||
//~ if(id.column!='saldo_cliente'){
|
||||
cmd_edit_partner_click()
|
||||
//~ }
|
||||
}
|
||||
|
||||
|
||||
function partner_balance_on_change(new_value, old_value){
|
||||
if(!isFinite(new_value)){
|
||||
this.config.value = old_value
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmd_partner_add_account_bank_click(){
|
||||
var form = $$('form_partner_account_bank')
|
||||
|
||||
if (!form.validate()){
|
||||
msg = 'Valores inválidos'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues()
|
||||
var id_partner = $$('form_partner').getValues().id
|
||||
|
||||
var account = {
|
||||
id_partner: id_partner,
|
||||
delete: '-',
|
||||
banco: $$('lst_partner_bank').getText(),
|
||||
cuenta: values.partner_account.trim(),
|
||||
clabe: values.partner_clabe.trim(),
|
||||
}
|
||||
|
||||
if(!account.cuenta){
|
||||
msg = 'La cuenta es requerida'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(!account.cuenta.is_number()){
|
||||
msg = 'Solo digitos en la cuenta'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(account.cuenta.length < 10){
|
||||
msg = 'Longitud incorrecta de la cuenta'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(!account.clabe){
|
||||
msg = 'La CLABE es requerida'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(account.clabe.length != 18){
|
||||
msg = 'La CLABE debe ser de 18 digitos'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(!account.clabe.is_number()){
|
||||
msg = 'Solo digitos en la CLABE'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var grid = $$('grid_partner_account_bank')
|
||||
|
||||
if(id_partner){
|
||||
partner_new_account_bank(account, grid)
|
||||
}else{
|
||||
grid.add(account)
|
||||
}
|
||||
|
||||
form.setValues({})
|
||||
}
|
||||
|
||||
|
||||
function get_partner_banks(){
|
||||
webix.ajax().get('/satbancos', {opt: 'active'}, function(text, data){
|
||||
var values = data.json()
|
||||
$$('lst_partner_bank').getList().parse(values)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function partner_new_account_bank(account, grid){
|
||||
webix.ajax().post('/socioscb', {opt: 'new', values: account}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al guardar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
account['id'] = values.id
|
||||
grid.add(account)
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_partner_accounts_bank(id_partner){
|
||||
var grid = $$('grid_partner_account_bank')
|
||||
grid.clearAll()
|
||||
|
||||
if(id_partner){
|
||||
var data = {opt: 'by_partner', id_partner: id_partner}
|
||||
webix.ajax().get('/socioscb', data, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
grid.parse(values)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function grid_partner_account_bank_click(id, e, node){
|
||||
if(id.column != 'delete'){
|
||||
return
|
||||
}
|
||||
var id_partner = $$('form_partner').getValues().id
|
||||
var grid = $$('grid_partner_account_bank')
|
||||
|
||||
var msg = '¿Estás seguro de eliminar la cuenta de banco seleccionada?<BR><BR>'
|
||||
msg += 'ESTA ACCION NO SE PUEDE DESHACER'
|
||||
webix.confirm({
|
||||
title: 'Eliminar cuenta de banco',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
if(id_partner){
|
||||
partner_delete_account_bank(id.row)
|
||||
}else{
|
||||
grid.remove(id.row)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function partner_delete_account_bank(row){
|
||||
var grid = $$('grid_partner_account_bank')
|
||||
|
||||
webix.ajax().post('/socioscb', {opt: 'delete', values: {id: row}}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al eliminar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
grid.remove(row)
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_sat_regimenes(morales=false){
|
||||
var data = {opt: 'actives', morales: morales}
|
||||
webix.ajax().sync().get('/satregimenes', data, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
$$('lst_receptor_regimenes_fiscales').clearAll()
|
||||
$$('lst_receptor_regimenes_fiscales').parse(values)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,80 @@
|
|||
var cfg_products = new Object()
|
||||
var gis_admin = false
|
||||
|
||||
|
||||
function products_default_config(){
|
||||
webix.ajax().get('/config', {'fields': 'main_products'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
cfg_products['inventario'] = values.chk_llevar_inventario
|
||||
cfg_products['predial'] = values.chk_config_cuenta_predial
|
||||
cfg_products['codigo_barras'] = values.chk_config_codigo_barras
|
||||
cfg_products['con_impuestos'] = values.chk_config_precio_con_impuestos
|
||||
cfg_products['default_unit'] = values.default_unidad
|
||||
cfg_products['default_tax'] = values.default_tax
|
||||
if(cfg_products['inventario']){
|
||||
$$('grid_products').showColumn('existencia')
|
||||
}
|
||||
//~ show('cant_by_packing', values.chk_use_packing)
|
||||
show('cmd_show_exists', values.chk_multi_stock)
|
||||
}
|
||||
})
|
||||
|
||||
webix.ajax().get('/users', {'opt': 'is_admin'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al consultar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
gis_admin = values.is_admin
|
||||
if(values.is_admin){
|
||||
$$('cmd_add_inventory').show()
|
||||
//~ $$('cmd_products_add').show()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
var products_controllers = {
|
||||
init: function(){
|
||||
$$('cmd_new_product').attachEvent('onItemClick', cmd_new_product_click)
|
||||
$$("cmd_edit_product").attachEvent("onItemClick", cmd_edit_product_click)
|
||||
$$("cmd_delete_product").attachEvent("onItemClick", cmd_delete_product_click)
|
||||
$$("cmd_save_product").attachEvent("onItemClick", cmd_save_product_click)
|
||||
$$("cmd_cancel_product").attachEvent("onItemClick", cmd_cancel_product_click)
|
||||
$$("cmd_import_products").attachEvent("onItemClick", cmd_import_products_click)
|
||||
$$("cmd_add_inventory").attachEvent("onItemClick", cmd_add_inventory_click)
|
||||
$$("cmd_products_add").attachEvent("onItemClick", cmd_products_add_click)
|
||||
$$('cmd_add_products_from_xml').attachEvent('onItemClick', cmd_add_products_from_xml_click)
|
||||
$$('cmd_show_exists').attachEvent('onItemClick', cmd_show_exists_click)
|
||||
$$('cmd_save_products_add').attachEvent('onItemClick', cmd_save_products_add_click)
|
||||
$$('cmd_close_products_add').attachEvent('onItemClick', cmd_close_products_add_click)
|
||||
$$("chk_automatica").attachEvent("onChange", chk_automatica_change)
|
||||
$$("valor_unitario").attachEvent("onChange", valor_unitario_change)
|
||||
$$('precio_con_impuestos').attachEvent('onChange', precio_con_impuestos_change)
|
||||
$$('precio_con_impuestos').attachEvent('onTimedKeyPress', precio_con_impuestos_key_up);
|
||||
$$("chk_inventario").attachEvent("onChange", chk_inventario_change)
|
||||
$$('grid_products').attachEvent('onItemDblClick', cmd_edit_product_click)
|
||||
products_default_config()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function configurar_producto(){
|
||||
show('cuenta_predial', cfg_products['predial'])
|
||||
show('codigo_barras', cfg_products['codigo_barras'])
|
||||
show('precio_con_impuestos', cfg_products['con_impuestos'])
|
||||
show('chk_inventario', cfg_products['inventario'])
|
||||
show('txt_existencia', cfg_products['inventario'])
|
||||
show('txt_minimo', cfg_products['inventario'])
|
||||
}
|
||||
|
||||
|
||||
function get_categorias(){
|
||||
|
@ -8,20 +85,45 @@ function get_categorias(){
|
|||
}
|
||||
|
||||
|
||||
function get_products(){
|
||||
var grid = $$('grid_products')
|
||||
webix.ajax().get('/products', {}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
grid.clearAll();
|
||||
if (values.ok){
|
||||
grid.parse(values.rows, 'json');
|
||||
grid.refresh()
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function cmd_new_product_click(id, e, node){
|
||||
get_taxes()
|
||||
$$('unidad').getList().load('/values/unidades')
|
||||
configurar_producto()
|
||||
$$('form_product').setValues({
|
||||
id: 0, es_activo_producto: true})
|
||||
add_config({'key': 'id_product', 'value': ''})
|
||||
get_new_key()
|
||||
get_taxes()
|
||||
get_categorias()
|
||||
$$('unidad').setValue(cfg_products['default_unit'])
|
||||
$$('grid_product_taxes').select(cfg_products['default_tax'])
|
||||
$$('grid_products').clearSelection()
|
||||
$$('unidad').getList().load('/values/unidades')
|
||||
$$("multi_products").setValue("product_new")
|
||||
}
|
||||
|
||||
|
||||
function cmd_edit_product_click(id, e, node){
|
||||
function cmd_edit_product_click(){
|
||||
get_taxes()
|
||||
$$('unidad').getList().load('/values/unidades')
|
||||
configurar_producto()
|
||||
|
||||
var grid = $$('grid_products')
|
||||
var row = grid.getSelectedItem()
|
||||
if(row == undefined){
|
||||
|
@ -29,13 +131,11 @@ function cmd_edit_product_click(id, e, node){
|
|||
return
|
||||
}
|
||||
|
||||
get_taxes()
|
||||
$$('categoria').getList().load('/values/categorias')
|
||||
$$('unidad').getList().load('/values/unidades')
|
||||
|
||||
webix.ajax().get('/products', {id:row['id']}, {
|
||||
webix.ajax().get('/products', {id: row['id']}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error()
|
||||
msg_error(text)
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
|
@ -116,6 +216,7 @@ function update_grid_products(values){
|
|||
msg = 'Producto actualizado correctamente'
|
||||
$$("grid_products").updateItem(values.row['id'], values.row)
|
||||
}
|
||||
$$('grid_products').refresh()
|
||||
$$('multi_products').setValue('products_home')
|
||||
msg_ok(msg)
|
||||
}
|
||||
|
@ -131,19 +232,32 @@ function cmd_save_product_click(id, e, node){
|
|||
}
|
||||
|
||||
var rows = $$('grid_product_taxes').getSelectedId(true, true)
|
||||
if (rows.length == 0){
|
||||
msg_error('Selecciona un impuesto')
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues();
|
||||
|
||||
if (!validate_sat_key_product(values.clave_sat, false)){
|
||||
if(!validate_sat_key_product(values.clave_sat, false)){
|
||||
msg_error('La clave SAT no existe')
|
||||
return
|
||||
}
|
||||
|
||||
if(values.descripcion.length > 1000){
|
||||
msg_error('Descripción con ' + values.descripcion.length + 'caracteres, captura solo 1000 caracteres')
|
||||
return
|
||||
}
|
||||
|
||||
if(values['objeto_impuesto']=='01' && rows.length > 0){
|
||||
msg = 'Si Objeto de Impuestos = 01, no debes seleccionar ningún impuesto'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
if(values['objeto_impuesto']=='02' && rows.length == 0){
|
||||
msg = 'Si Objeto de Impuestos = 02, debes de seleccionar al menos un impuesto'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
values['taxes'] = JSON.stringify(rows)
|
||||
|
||||
webix.ajax().sync().post('products', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
|
@ -162,9 +276,7 @@ function cmd_save_product_click(id, e, node){
|
|||
|
||||
|
||||
function cmd_cancel_product_click(id, e, node){
|
||||
|
||||
$$("multi_products").setValue("products_home")
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -189,6 +301,20 @@ function chk_automatica_change(new_value, old_value){
|
|||
}
|
||||
|
||||
|
||||
function chk_inventario_change(new_value, old_value){
|
||||
var value = Boolean(new_value)
|
||||
if(value){
|
||||
$$('txt_existencia').enable()
|
||||
$$('txt_minimo').enable()
|
||||
}else{
|
||||
$$('txt_existencia').disable()
|
||||
$$('txt_minimo').disable()
|
||||
$$('txt_existencia').setValue(0)
|
||||
$$('txt_minimo').setValue(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function get_new_key(){
|
||||
webix.ajax().get('/values/newkey', {
|
||||
error: function(text, data, xhr) {
|
||||
|
@ -211,6 +337,655 @@ function valor_unitario_change(new_value, old_value){
|
|||
}
|
||||
|
||||
|
||||
function clave_sat_icon_click(){
|
||||
show('Buscar SAT')
|
||||
function precio_con_impuestos_change(new_value, old_value){
|
||||
if(!isFinite(new_value)){
|
||||
this.config.value = old_value
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function calcular_sin_impuestos(value, taxes){
|
||||
var vu = $$('valor_unitario')
|
||||
var precio = value
|
||||
|
||||
taxes.forEach(function(tax){
|
||||
var tasa = 1.00 + tax.tasa.to_float()
|
||||
if(tax.tipo == 'T' && tax.name == 'IVA'){
|
||||
precio = (value / tasa).round(DECIMALES)
|
||||
}
|
||||
})
|
||||
vu.setValue(precio)
|
||||
}
|
||||
|
||||
function precio_con_impuestos_key_up(){
|
||||
var value = this.getValue()
|
||||
|
||||
if(!value){
|
||||
return
|
||||
}
|
||||
|
||||
var taxes = $$('grid_product_taxes').getSelectedItem(true)
|
||||
if (taxes.length == 0){
|
||||
msg = 'Selecciona al menos un impuesto'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(!isFinite(value)){
|
||||
msg = 'Captura un valor válido'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
calcular_sin_impuestos(parseFloat(value), taxes)
|
||||
}
|
||||
|
||||
|
||||
function cmd_import_products_click(){
|
||||
win_import_products.init()
|
||||
$$('win_import_products').show()
|
||||
}
|
||||
|
||||
|
||||
function cmd_upload_products_click(){
|
||||
var form = $$('form_upload_products')
|
||||
|
||||
var values = form.getValues()
|
||||
|
||||
if(!$$('lst_upload_products').count()){
|
||||
$$('win_import_products').close()
|
||||
return
|
||||
}
|
||||
|
||||
if($$('lst_upload_products').count() > 1){
|
||||
msg = 'Selecciona solo un archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var template = $$('up_products').files.getItem($$('up_products').files.getFirstId())
|
||||
|
||||
if(template.type.toLowerCase() != 'ods'){
|
||||
msg = 'Archivo inválido.\n\nSe requiere un archivo ODS'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de importar este archivo?'
|
||||
webix.confirm({
|
||||
title: 'Importar Productos',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
$$('up_products').send()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function up_products_upload_complete(response){
|
||||
if(response.status != 'server'){
|
||||
msg = 'Ocurrio un error al subir el archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
msg = 'Archivo subido correctamente.\n\nComenzando importación.'
|
||||
msg_ok(msg)
|
||||
$$('win_import_products').close()
|
||||
|
||||
webix.ajax().post('/products', {opt: 'import'}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg = 'Error al importar'
|
||||
msg_error(msg)
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok){
|
||||
get_products()
|
||||
webix.alert({
|
||||
title: 'Importación terminada',
|
||||
text: values.msg,
|
||||
})
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//~ Add inventory
|
||||
function cmd_add_inventory_click(id, e, node){
|
||||
var row = $$('grid_products').getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un Producto')
|
||||
return
|
||||
}
|
||||
|
||||
win_add_inventory.init()
|
||||
$$('txt_add_id').setValue(row.id)
|
||||
$$('txt_add_key').setValue(row.clave)
|
||||
$$('txt_add_unit').setValue(row.unidad)
|
||||
$$('txt_add_description').setValue(row.descripcion)
|
||||
$$('lst_warehouses').getList().load('/warehouse?opt=for_select')
|
||||
$$('win_add_inventory').show()
|
||||
}
|
||||
|
||||
|
||||
//~ Show details inventory
|
||||
function cmd_show_exists_click(id, e, node){
|
||||
var row = $$('grid_products').getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un Producto')
|
||||
return
|
||||
}
|
||||
win_show_exists.init()
|
||||
$$('txt_id_product').setValue(row.id)
|
||||
$$('grid_warehouse_exists').load('warehouseproduct?opt=by_product&id=' + row.id)
|
||||
|
||||
if(gis_admin){
|
||||
$$('lst_warehouse_target').getList().load('/warehouse?opt=for_select')
|
||||
}else{
|
||||
$$('lbl_title_move').hide()
|
||||
$$('txt_cant_to_move').hide()
|
||||
$$('lst_warehouse_target').hide()
|
||||
$$('cmd_warehouse_move').hide()
|
||||
}
|
||||
|
||||
$$('win_show_exists').show()
|
||||
}
|
||||
|
||||
|
||||
function cmd_warehouse_move_click(id, e, node){
|
||||
var id_product = $$('txt_id_product').getValue()
|
||||
var row = $$('grid_warehouse_exists').getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un Almacen origen')
|
||||
return
|
||||
}
|
||||
var warehouse_source = row.id
|
||||
var cant_to_move = $$('txt_cant_to_move').getValue()
|
||||
var warehouse_target = $$('lst_warehouse_target').getValue()
|
||||
|
||||
if(!cant_to_move){
|
||||
msg_error('La cantidad no puede ser cero')
|
||||
return
|
||||
}
|
||||
|
||||
if(cant_to_move > row.exists){
|
||||
msg_error('La cantidad a mover no puede ser mayor a la existencia')
|
||||
return
|
||||
}
|
||||
|
||||
if (warehouse_target == ''){
|
||||
msg_error('Selecciona un Almacen destino')
|
||||
return
|
||||
}
|
||||
|
||||
if (warehouse_source == warehouse_target){
|
||||
msg_error('Los almacenes origen y destino deben ser diferentes')
|
||||
return
|
||||
}
|
||||
|
||||
var values = {
|
||||
id_product: id_product,
|
||||
cant: cant_to_move,
|
||||
source: warehouse_source,
|
||||
target: warehouse_target
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de hacer este movimiento?'
|
||||
webix.confirm({
|
||||
title: 'Movimiento de Almacen',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
_warehouse_movement(values)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function _warehouse_movement(args){
|
||||
var values = {
|
||||
opt: 'warehouse_movement',
|
||||
values: args,
|
||||
}
|
||||
|
||||
webix.ajax().sync().post('inventoryentries', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
$$('txt_cant_to_move').setValue(0)
|
||||
$$('lst_warehouse_target').setValue('')
|
||||
$$('grid_warehouse_exists').load('warehouseproduct?opt=by_product&id=' + args.id_product)
|
||||
$$('grid_warehouse_exists').clearSelection()
|
||||
msg_ok('Movimiento realizado correctamente')
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_win_show_exists_close_click(id, e, node){
|
||||
$$('win_show_exists').close()
|
||||
}
|
||||
|
||||
|
||||
//~ Add products
|
||||
function cmd_products_add_click(id, e, node){
|
||||
$$("multi_products").setValue("product_add")
|
||||
cfg_products['partner_id'] = 0
|
||||
cfg_products['partner_rfc'] = ''
|
||||
}
|
||||
|
||||
//~ Close add products
|
||||
function cmd_close_products_add_click(id, e, node){
|
||||
var grid = $$('grid_partner_products')
|
||||
|
||||
$$('multi_invoices').setValue('products_home')
|
||||
$$('lbl_partner').setValue('')
|
||||
grid.clearAll()
|
||||
}
|
||||
|
||||
|
||||
function _add_entries_inventory(data){
|
||||
var grid = $$('grid_partner_products')
|
||||
var values = {
|
||||
opt: 'create',
|
||||
values: data,
|
||||
}
|
||||
|
||||
webix.ajax().sync().post('inventoryentries', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
get_products()
|
||||
$$('multi_invoices').setValue('products_home')
|
||||
$$('lbl_partner').setValue('')
|
||||
grid.clearAll()
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//~ Save add products
|
||||
function cmd_save_products_add_click(id, e, node){
|
||||
var grid = $$('grid_partner_products')
|
||||
var count = 0
|
||||
var products = []
|
||||
var validate_import = false
|
||||
var validate_cant = false
|
||||
|
||||
grid.eachRow(function(row){
|
||||
var r = grid.getItem(row)
|
||||
if(r.select){
|
||||
var p = {}
|
||||
count += 1
|
||||
p.id_product = r.id_product
|
||||
p.key = r.key
|
||||
p.key_sat = r.key_sat1
|
||||
p.description = r.description1
|
||||
p.unit = r.unit
|
||||
p.unit_value = r.unit_value1
|
||||
p.cant = r.cant1
|
||||
products.push(p)
|
||||
|
||||
if(p.unit_value < parseFloat(r.unit_value)){
|
||||
validate_import = true
|
||||
}
|
||||
if(p.cant > r.cant){
|
||||
validate_cant = true
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
if(!count){
|
||||
msg = 'Selecciona al menos un registro'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(validate_import){
|
||||
msg = 'El Valor Unitario no puede ser menor al Valor Unitario del proveedor'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if(validate_cant){
|
||||
msg = 'La Cantidad no puede ser mayor a la Cantidad del proveedor'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var data = {
|
||||
partner: cfg_products['partner'],
|
||||
products: products,
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de ingresar estos productos? <br/><br/>\
|
||||
Esta acción no se puede deshacer.'
|
||||
webix.confirm({
|
||||
title: 'Agregar entrada',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
_add_entries_inventory(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//~ Import from xml
|
||||
function cmd_add_products_from_xml_click(){
|
||||
win_add_products_from_xml.init()
|
||||
$$('win_add_products_from_xml').show()
|
||||
}
|
||||
|
||||
//~ Upload XML
|
||||
function cmd_upload_products_from_xml_click(){
|
||||
var form = $$('form_upload_products_from_xml')
|
||||
var values = form.getValues()
|
||||
var list = $$('lst_up_products_from_xml')
|
||||
var upload = $$('up_products_from_xml')
|
||||
|
||||
if(!list.count()){
|
||||
$$('win_add_products_from_xml').close()
|
||||
return
|
||||
}
|
||||
|
||||
if(list.count() > 1){
|
||||
msg = 'Selecciona solo un archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var template = upload.files.getItem(upload.files.getFirstId())
|
||||
|
||||
if(template.type.toLowerCase() != 'xml'){
|
||||
msg = 'Archivo inválido.\n\nSe requiere un archivo XML'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de importar este archivo? <br/><br/>\
|
||||
Si hay datos previos seran reemplazados.'
|
||||
webix.confirm({
|
||||
title: 'Importar Productos',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
upload.send()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function up_products_from_xml_upload_complete(response){
|
||||
if(response.status != 'server'){
|
||||
msg = 'Ocurrio un error al subir el archivo'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
$$('win_add_products_from_xml').close()
|
||||
|
||||
if(response.error){
|
||||
msg_error(response.error)
|
||||
return
|
||||
}
|
||||
|
||||
var grid = $$('grid_partner_products')
|
||||
var data = response.data
|
||||
cfg_products['partner'] = data.emisor
|
||||
//~ cfg_products['xml'] = data.xml
|
||||
|
||||
var html = '<span class="webix_icon fa-user"></span><span class="lbl_partner">'
|
||||
html += data.emisor.nombre + ' (' + data.emisor.rfc + ')</span>'
|
||||
$$('lbl_partner').setValue(html)
|
||||
|
||||
grid.clearAll()
|
||||
grid.parse(data.conceptos, 'json')
|
||||
grid.refresh()
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get_partner_product(grid, row){
|
||||
grid.refresh(row.id)
|
||||
|
||||
var partner_id = cfg_products['partner'].id
|
||||
var filters = {
|
||||
opt: 'product',
|
||||
partner: cfg_products['partner'],
|
||||
product_key: row.key,
|
||||
}
|
||||
|
||||
if(!partner_id){
|
||||
msg = 'El Proveedor no esta dado de alta'
|
||||
msg_ok(msg)
|
||||
return
|
||||
}
|
||||
|
||||
webix.ajax().get('/partnerproducts', filters, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Ocurrio un error, consulta a soporte técnico.')
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
row['id_product'] = values.row.id_product
|
||||
row['key_sat1'] = values.row.key_sat1
|
||||
row['description1'] = values.row.description1
|
||||
row['unit_value1'] = values.row.unit_value1
|
||||
grid.refresh(row.id)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function grid_partner_products_select(row_id, state){
|
||||
var grid = $$('grid_partner_products')
|
||||
var row = grid.getItem(row_id)
|
||||
|
||||
if(state){
|
||||
row['key_sat1'] = row.key_sat
|
||||
row['description1'] = row.description
|
||||
row['cant1'] = row.cant
|
||||
row['unit_value1'] = 0.0
|
||||
get_partner_product(grid, row)
|
||||
}else{
|
||||
row['key_sat1'] = ''
|
||||
row['description1'] = ''
|
||||
row['cant1'] = ''
|
||||
grid.refresh(row_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmd_add_inventory_cancel_click(id, e, node){
|
||||
$$('win_add_inventory').close()
|
||||
}
|
||||
|
||||
|
||||
function cmd_add_inventory_save_click(id, e, node){
|
||||
var product_id = $$('txt_add_id').getValue()
|
||||
//~ var product_key = $$('txt_add_key').getValue()
|
||||
var new_cant = $$('txt_new_cant').getValue()
|
||||
var warehouse = $$('lst_warehouses').getValue()
|
||||
|
||||
if(new_cant<=0) {
|
||||
msg = 'La cantidad no puede ser cero'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if($$('lst_warehouses').isVisible()){
|
||||
if(!warehouse){
|
||||
msg = 'Selecciona un almacen'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
msg = '¿Estas seguro de guardar esta entrada? <br/><br/>\
|
||||
Esta acción no se puede deshacer'
|
||||
|
||||
webix.confirm({
|
||||
title: 'Agregar entrada',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
add_product_stock(product_id, new_cant, warehouse)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function add_product_stock(product_id, new_cant, warehouse){
|
||||
var data = {
|
||||
product_id: product_id,
|
||||
cant: new_cant,
|
||||
warehouse: warehouse,
|
||||
}
|
||||
_add_entries_inventory_manual(product_id, data)
|
||||
$$('win_add_inventory').close()
|
||||
}
|
||||
|
||||
|
||||
function _add_entries_inventory_manual(row_id, data){
|
||||
var grid = $$('grid_products')
|
||||
var values = {
|
||||
opt: 'create_manual',
|
||||
values: data,
|
||||
}
|
||||
|
||||
webix.ajax().sync().post('inventoryentries', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
grid.updateItem(row_id, values.row)
|
||||
grid.refresh()
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_adjust_stock_click(id, e, node){
|
||||
var id_product = $$('txt_id_product').getValue()
|
||||
var row = $$('grid_warehouse_exists').getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un Almacen origen')
|
||||
return
|
||||
}
|
||||
var warehouse_source = row.id
|
||||
var cant_to_adjust = $$('txt_cant_to_adjust').getValue()
|
||||
|
||||
if(cant_to_adjust == 0){
|
||||
msg_error('La cantidad a ajustar no puede ser cero')
|
||||
return
|
||||
}
|
||||
|
||||
if(cant_to_adjust > row.exists){
|
||||
msg_error('La cantidad a ajustar no puede ser mayor a la existencia')
|
||||
return
|
||||
}
|
||||
|
||||
var values = {
|
||||
id_product: id_product,
|
||||
cant: cant_to_adjust,
|
||||
storage: warehouse_source,
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de hacer este ajuste?'
|
||||
webix.confirm({
|
||||
title: 'Ajuste de Almacen',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
_adjust_stock(values)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function _adjust_stock(args){
|
||||
var grid = $$('grid_products')
|
||||
var row = grid.getSelectedItem()
|
||||
|
||||
var values = {
|
||||
opt: 'adjust_stock',
|
||||
values: args,
|
||||
}
|
||||
|
||||
webix.ajax().sync().post('warehouseproduct', values, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
$$('txt_cant_to_adjust').setValue(0)
|
||||
$$('grid_warehouse_exists').load('warehouseproduct?opt=by_product&id=' + args.id_product)
|
||||
$$('grid_warehouse_exists').clearSelection()
|
||||
|
||||
grid.updateItem(row['id'], values.row)
|
||||
grid.refresh()
|
||||
|
||||
msg_ok('Ajuste realizado correctamente')
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
|
||||
|
||||
var controllers_school = {
|
||||
init: function(){
|
||||
$$('cmd_new_student').attachEvent('onItemClick', cmd_new_student_click)
|
||||
$$('cmd_edit_student').attachEvent('onItemClick', cmd_edit_student_click)
|
||||
$$('cmd_delete_student').attachEvent('onItemClick', cmd_delete_student_click)
|
||||
$$('cmd_save_student').attachEvent('onItemClick', cmd_save_student_click)
|
||||
$$('cmd_cancel_student').attachEvent('onItemClick', cmd_cancel_student_click)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function get_school_groups(){
|
||||
webix.ajax().get('/values/schoolgroups', {
|
||||
error: function(text, data, xhr) {
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
$$('student_grupo').define('suggest', values)
|
||||
$$('student_grupo').refresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function init_config_school(){
|
||||
get_students()
|
||||
get_school_groups()
|
||||
}
|
||||
|
||||
|
||||
function cmd_new_student_click(){
|
||||
$$('form_student').setValues({})
|
||||
$$('grid_students').clearSelection()
|
||||
$$('multi_school').setValue('new_student')
|
||||
}
|
||||
|
||||
|
||||
function cmd_edit_student_click(){
|
||||
var row = $$('grid_students').getSelectedItem()
|
||||
|
||||
if (row == undefined){
|
||||
msg = 'Selecciona un Alumno'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
webix.ajax().get('/students', {id: row['id']}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error()
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
$$('form_student').setValues(values)
|
||||
}
|
||||
})
|
||||
|
||||
$$('multi_school').setValue('new_student')
|
||||
}
|
||||
|
||||
|
||||
function delete_student(id){
|
||||
webix.ajax().del('/students', {id: id}, function(text, xml, xhr){
|
||||
msg = 'Alumno eliminado correctamente'
|
||||
if (xhr.status == 200){
|
||||
$$('grid_students').remove(id);
|
||||
msg_ok(msg)
|
||||
} else {
|
||||
msg = 'No se pudo eliminar.'
|
||||
msg_error(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_delete_student_click(){
|
||||
var row = $$('grid_students').getSelectedItem()
|
||||
|
||||
if (row == undefined){
|
||||
msg = 'Selecciona un Alumno'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de eliminar al Alumno?<BR><BR>'
|
||||
msg += row['nombre'] + ' ' + row['paterno'] + ' (' + row['rfc'] + ')'
|
||||
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
|
||||
webix.confirm({
|
||||
title:'Eliminar Alumno',
|
||||
ok:'Si',
|
||||
cancel:'No',
|
||||
type:'confirm-error',
|
||||
text:msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
delete_student(row['id'])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_cancel_student_click(){
|
||||
$$('multi_school').setValue('school_home')
|
||||
}
|
||||
|
||||
|
||||
function cmd_save_student_click(){
|
||||
msg = ''
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues();
|
||||
opt = 'add'
|
||||
if(values.id){
|
||||
opt = 'edit'
|
||||
}
|
||||
|
||||
webix.ajax().post('/students', {opt: opt, values: values}, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico';
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
form.setValues({})
|
||||
$$('multi_school').setValue('school_home')
|
||||
get_students()
|
||||
} else {
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get_students(){
|
||||
webix.ajax().get('/students', {}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json()
|
||||
$$('grid_students').clearAll()
|
||||
$$('grid_students').parse(values)
|
||||
}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,903 @@
|
|||
var query = []
|
||||
var msg = ''
|
||||
var cfg_ticket = new Object()
|
||||
var last_forma_pago = ''
|
||||
|
||||
|
||||
var tickets_controllers = {
|
||||
init: function(){
|
||||
$$('cmd_nuevo_ticket').attachEvent('onItemClick', cmd_nuevo_ticket_click)
|
||||
$$('cmd_ticket_from_ticket').attachEvent('onItemClick', cmd_ticket_from_ticket_click)
|
||||
$$('cmd_ticket_to_invoice').attachEvent('onItemClick', cmd_ticket_to_invoice_click)
|
||||
$$('cmd_ticket_report_pdf').attachEvent('onItemClick', cmd_ticket_report_pdf_click)
|
||||
$$('cmd_ticket_report_xls').attachEvent('onItemClick', cmd_ticket_report_xls_click)
|
||||
$$('cmd_generar_ticket').attachEvent('onItemClick', cmd_generar_ticket_click)
|
||||
$$('cmd_cerrar_ticket').attachEvent('onItemClick', cmd_cerrar_ticket_click)
|
||||
$$('cmd_new_invoice_from_ticket').attachEvent('onItemClick', cmd_new_invoice_from_ticket_click)
|
||||
$$('cmd_close_ticket_invoice').attachEvent('onItemClick', cmd_cerrar_ticket_click)
|
||||
$$('cmd_cancelar_ticket').attachEvent('onItemClick', cmd_cancelar_ticket_click)
|
||||
$$('cmd_move_tickets_right').attachEvent('onItemClick', cmd_move_tickets_right_click)
|
||||
$$('cmd_move_tickets_left').attachEvent('onItemClick', cmd_move_tickets_left_click)
|
||||
$$('cmd_ticket_notes').attachEvent('onItemClick', cmd_ticket_notes_click)
|
||||
$$('tsearch_product_key').attachEvent('onKeyPress', tsearch_product_key_press)
|
||||
$$('grid_tickets').attachEvent('onItemClick', grid_tickets_click)
|
||||
$$('grid_tdetails').attachEvent('onItemClick', grid_ticket_details_click)
|
||||
$$('grid_tdetails').attachEvent('onBeforeEditStop', grid_tickets_details_before_edit_stop)
|
||||
$$('gt_productos_found').attachEvent('onValueSuggest', gt_productos_found_click)
|
||||
$$('cmd_ticket_filter_today').attachEvent('onItemClick', cmd_ticket_filter_today_click)
|
||||
$$('filter_year_ticket').attachEvent('onChange', filter_year_ticket_change)
|
||||
$$('filter_month_ticket').attachEvent('onChange', filter_month_ticket_change)
|
||||
$$('filter_dates_ticket').attachEvent('onChange', filter_dates_ticket_change)
|
||||
$$('chk_is_invoice_day').attachEvent('onChange', chk_is_invoice_day_change)
|
||||
$$('grid_tickets_active').attachEvent('onItemDblClick', grid_tickets_active_double_click)
|
||||
$$('grid_tickets_invoice').attachEvent('onItemDblClick', grid_tickets_invoice_double_click)
|
||||
$$('tsearch_client_key').attachEvent('onKeyPress', tsearch_client_key_press)
|
||||
$$('grid_ticket_clients_found').attachEvent('onValueSuggest', grid_ticket_clients_found_click)
|
||||
$$('grid_tdetails').attachEvent('onAfterRender', grid_tdetails_render)
|
||||
|
||||
webix.extend($$('grid_tickets'), webix.ProgressBar)
|
||||
webix.extend($$('grid_tickets_active'), webix.ProgressBar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function current_dates_tickets(){
|
||||
var fy = $$('filter_year_ticket')
|
||||
var fm = $$('filter_month_ticket')
|
||||
var d = new Date()
|
||||
|
||||
fy.blockEvent()
|
||||
fm.blockEvent()
|
||||
|
||||
fm.setValue(d.getMonth() + 1)
|
||||
webix.ajax().sync().get('/values/filteryearsticket', function(text, data){
|
||||
var values = data.json()
|
||||
fy.getList().parse(values)
|
||||
fy.setValue(d.getFullYear())
|
||||
})
|
||||
|
||||
fy.unblockEvent()
|
||||
fm.unblockEvent()
|
||||
}
|
||||
|
||||
|
||||
function get_tickets(filters){
|
||||
if(filters == undefined){
|
||||
filters = {'opt': 'today'}
|
||||
}
|
||||
|
||||
var grid = $$('grid_tickets')
|
||||
grid.showProgress({type: 'icon'})
|
||||
|
||||
webix.ajax().get('/tickets', filters, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
grid.clearAll();
|
||||
if (values.ok){
|
||||
grid.parse(values.rows, 'json')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_filter_today_click(){
|
||||
get_tickets()
|
||||
}
|
||||
|
||||
|
||||
function filter_year_ticket_change(nv, ov){
|
||||
var fm = $$('filter_month_ticket')
|
||||
filters = {'opt': 'yearmonth', 'year': nv, 'month': fm.getValue()}
|
||||
get_tickets(filters)
|
||||
}
|
||||
|
||||
|
||||
function filter_month_ticket_change(nv, ov){
|
||||
var fy = $$('filter_year_ticket')
|
||||
filters = {'opt': 'yearmonth', 'year': fy.getValue(), 'month': nv}
|
||||
get_tickets(filters)
|
||||
}
|
||||
|
||||
|
||||
function filter_dates_ticket_change(range){
|
||||
if(range.start != null && range.end != null){
|
||||
filters = {'opt': 'dates', 'range': range}
|
||||
get_tickets(filters)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function configuracion_inicial_ticket(){
|
||||
current_dates_tickets()
|
||||
get_tickets()
|
||||
|
||||
webix.ajax().sync().get('/values/configticket', function(text, data){
|
||||
var values = data.json()
|
||||
//~ showvar(values)
|
||||
cfg_ticket['open_pdf'] = values.open_pdf
|
||||
cfg_ticket['direct_print'] = values.direct_print
|
||||
cfg_ticket['edit_cant'] = values.edit_cant
|
||||
cfg_ticket['total_up'] = values.total_up
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_active_tickets(grid){
|
||||
filters = {'opt': 'active'}
|
||||
grid.showProgress({type: 'icon'})
|
||||
|
||||
webix.ajax().get('/tickets', filters, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
grid.clearAll();
|
||||
if (values.ok){
|
||||
grid.parse(values.rows, 'json')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function configuracion_inicial_ticket_to_invoice(){
|
||||
var grid = $$('grid_tickets_active')
|
||||
var gridt = $$('grid_tickets_invoice')
|
||||
var form = $$('form_ticket_invoice')
|
||||
var chk = $$('chk_is_invoice_day')
|
||||
|
||||
chk.setValue(false)
|
||||
get_active_tickets(grid)
|
||||
form.setValues({id_partner: 0, lbl_tclient: 'Ninguno'})
|
||||
gridt.attachEvent('onAfterAdd', function(id, index){
|
||||
gridt.adjustColumn('index')
|
||||
gridt.adjustColumn('folio', 'all')
|
||||
gridt.adjustColumn('fecha', 'all')
|
||||
});
|
||||
gridt.clearAll()
|
||||
}
|
||||
|
||||
|
||||
function configuracion_inicial_nuevo_ticket(){
|
||||
var grid = $$('grid_tdetails')
|
||||
|
||||
webix.ajax().sync().get('/values/taxes', function(text, data){
|
||||
var values = data.json()
|
||||
table_taxes.clear()
|
||||
table_taxes.insert(values)
|
||||
})
|
||||
get_forma_pago('lst_ticket_forma_pago')
|
||||
grid.clearAll()
|
||||
table_pt.clear()
|
||||
table_totals.clear()
|
||||
show('grid_ticket_total_up', cfg_ticket['total_up'])
|
||||
$$('form_new_ticket').setValues({notas: '', forma_pago: last_forma_pago})
|
||||
}
|
||||
|
||||
|
||||
function cmd_nuevo_ticket_click(){
|
||||
configuracion_inicial_nuevo_ticket()
|
||||
$$('multi_tickets').setValue('tickets_new')
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_from_ticket_click(){
|
||||
var grid = $$('grid_tickets')
|
||||
|
||||
if(grid.count() == 0){
|
||||
return
|
||||
}
|
||||
|
||||
var row = grid.getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un ticket')
|
||||
return
|
||||
}
|
||||
|
||||
configuracion_inicial_nuevo_ticket()
|
||||
$$('multi_tickets').setValue('tickets_new')
|
||||
$$('grid_tdetails').load('ticketsdetails?opt=by_ticket_id&id=' + row.id)
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_to_invoice_click(){
|
||||
configuracion_inicial_ticket_to_invoice()
|
||||
$$('multi_tickets').setValue('tickets_invoice')
|
||||
}
|
||||
|
||||
|
||||
function validar_ticket(){
|
||||
var grid = $$('grid_tdetails')
|
||||
|
||||
if(!grid.count()){
|
||||
webix.UIManager.setFocus('tsearch_product_key')
|
||||
msg = 'Agrega al menos un producto'
|
||||
msg_error(msg)
|
||||
return false
|
||||
}
|
||||
|
||||
var values = $$('form_new_ticket').getValues()
|
||||
if(!values.forma_pago){
|
||||
msg = 'La forma de pago es requerida'
|
||||
msg_error(msg)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
function get_ticket_pdf(id){
|
||||
window.open('/doc/tpdf/' + id, '_blank')
|
||||
}
|
||||
|
||||
|
||||
function guardar_ticket(values){
|
||||
var gd = $$('grid_tdetails')
|
||||
var grid = $$('grid_tickets')
|
||||
|
||||
var rows = gd.data.getRange()
|
||||
for (i = 0; i < rows.length; i++) {
|
||||
delete rows[i]['id']
|
||||
delete rows[i]['delete']
|
||||
delete rows[i]['clave']
|
||||
delete rows[i]['clave_sat']
|
||||
delete rows[i]['unidad']
|
||||
delete rows[i]['importe']
|
||||
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
|
||||
rows[i]['descuento'] = parseFloat(rows[i]['descuento'])
|
||||
}
|
||||
|
||||
last_forma_pago = values.forma_pago
|
||||
var data = new Object()
|
||||
data['opt'] = 'add'
|
||||
data['productos'] = rows
|
||||
data['forma_pago'] = values.forma_pago
|
||||
data['notas'] = values.notas
|
||||
|
||||
webix.ajax().sync().post('tickets', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
msg_ok('Ticket generado correctamente')
|
||||
$$('form_new_ticket').setValues({})
|
||||
gd.clearAll()
|
||||
grid.add(values.row)
|
||||
$$('multi_tickets').setValue('tickets_home')
|
||||
if(cfg_ticket.open_pdf){
|
||||
get_ticket_pdf(values.row.id)
|
||||
}
|
||||
if(cfg_ticket.direct_print){
|
||||
print_ticket(values.row.id)
|
||||
}
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function cmd_generar_ticket_click(){
|
||||
var form = $$('form_new_ticket')
|
||||
|
||||
if(!form.validate()) {
|
||||
msg_error('Valores inválidos')
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues()
|
||||
if(!validar_ticket()){
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Todos los datos son correctos?<BR><BR>'
|
||||
msg += '¿Estás seguro de generar este Ticket?'
|
||||
|
||||
webix.confirm({
|
||||
title: 'Generar Ticket',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
guardar_ticket(values)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_cerrar_ticket_click(){
|
||||
$$('multi_tickets').setValue('tickets_home')
|
||||
}
|
||||
|
||||
|
||||
function calcular_precio_con_impuestos(precio, taxes){
|
||||
var precio_final = precio
|
||||
|
||||
for(var tax of taxes){
|
||||
impuesto = table_taxes.findOne({'id': tax.tax})
|
||||
if(impuesto.tipo == 'E'){
|
||||
continue
|
||||
}
|
||||
var base = precio
|
||||
if(impuesto.tipo == 'R'){
|
||||
base = (precio * -1).round(DECIMALES)
|
||||
}
|
||||
precio_final += (impuesto.tasa * base).round(DECIMALES)
|
||||
}
|
||||
|
||||
return precio_final
|
||||
}
|
||||
|
||||
|
||||
function edit_cant(id){
|
||||
if(!cfg_ticket['edit_cant']){
|
||||
return
|
||||
}
|
||||
$$('grid_tdetails').edit({row: id, column: 'cantidad'})
|
||||
}
|
||||
|
||||
|
||||
function agregar_producto(values){
|
||||
var taxes = values.taxes
|
||||
var producto = values.row
|
||||
var form = $$('form_new_ticket')
|
||||
var grid = $$('grid_tdetails')
|
||||
var row = grid.getItem(producto.id)
|
||||
var precio_final = 0.0
|
||||
|
||||
if(row == undefined){
|
||||
producto['cantidad'] = 1
|
||||
producto['valor_unitario'] = calcular_precio_con_impuestos(
|
||||
parseFloat(producto['valor_unitario']), taxes)
|
||||
producto['importe'] = producto['valor_unitario']
|
||||
//~ var id = grid.add(producto, 0)
|
||||
//~ edit_cant(id)
|
||||
}else{
|
||||
producto['cantidad'] = parseFloat(row.cantidad) + 1
|
||||
producto['descuento'] = parseFloat(row.descuento)
|
||||
producto['valor_unitario'] = parseFloat(row.valor_unitario)
|
||||
precio_final = producto['valor_unitario'] - producto['descuento']
|
||||
producto['importe'] = (precio_final * producto['cantidad']).round(DECIMALES)
|
||||
//~ grid.updateItem(row.id, producto)
|
||||
}
|
||||
form.setValues({tsearch_product_key: '', tsearch_product_name: ''}, true)
|
||||
|
||||
//~ Validate stock
|
||||
if(producto.inventario){
|
||||
if(producto.cantidad > producto.existencia){
|
||||
msg_error('No hay suficiente existencia de este producto')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if(row == undefined){
|
||||
var id = grid.add(producto, 0)
|
||||
edit_cant(id)
|
||||
}else{
|
||||
grid.updateItem(row.id, producto)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function buscar_producto_key(key){
|
||||
|
||||
var filters = {
|
||||
opt: 'by_key',
|
||||
key: key,
|
||||
}
|
||||
|
||||
webix.ajax().get('/products', filters, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
if (values.ok){
|
||||
agregar_producto(values)
|
||||
} else {
|
||||
msg = 'No se encontró la clave<BR><BR>' + key
|
||||
msg_error(msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
//~ webix.ajax().get('/values/productokey', {'key': key}, {
|
||||
//~ error: function(text, data, xhr) {
|
||||
//~ msg_error('Error al consultar')
|
||||
//~ },
|
||||
//~ success: function(text, data, xhr){
|
||||
//~ var values = data.json()
|
||||
//~ if (values.ok){
|
||||
//~ agregar_producto(values)
|
||||
//~ } else {
|
||||
//~ msg = 'No se encontró la clave<BR><BR>' + key
|
||||
//~ msg_error(msg)
|
||||
//~ }
|
||||
//~ }
|
||||
//~ })
|
||||
|
||||
}
|
||||
|
||||
|
||||
function tsearch_product_key_press(code, e){
|
||||
var value = this.getValue()
|
||||
if(code == 13 && value.trim().length > 0){
|
||||
buscar_producto_key(value.trim())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function grid_ticket_details_click(id, e, node){
|
||||
if(id.column != 'delete'){
|
||||
return
|
||||
}
|
||||
var grid = $$('grid_tdetails')
|
||||
grid.remove(id.row)
|
||||
}
|
||||
|
||||
|
||||
function grid_tickets_details_before_edit_stop(state, editor){
|
||||
var grid = $$('grid_tdetails')
|
||||
pause(500)
|
||||
var row = grid.getItem(editor.row)
|
||||
|
||||
if(editor.column == 'cantidad'){
|
||||
var cantidad = parseFloat(state.value)
|
||||
if(isNaN(cantidad)){
|
||||
msg = 'La cantidad debe ser un número'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}else if(cantidad <= 0){
|
||||
msg = 'La cantidad no puede cero o menor'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}
|
||||
|
||||
//~ Validate stock
|
||||
if(row['inventario']){
|
||||
if(cantidad > row['existencia']){
|
||||
msg = 'No hay suficiente existencia de este producto'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var valor_unitario = parseFloat(row['valor_unitario'])
|
||||
var descuento = parseFloat(row['descuento'])
|
||||
}
|
||||
|
||||
if(editor.column == 'valor_unitario'){
|
||||
var valor_unitario = parseFloat(state.value)
|
||||
if(isNaN(valor_unitario)){
|
||||
msg = 'El valor unitario debe ser un número'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}else if(valor_unitario <= 0){
|
||||
msg = 'El valor unitario no puede cero o menor'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}
|
||||
var cantidad = parseFloat(row['cantidad'])
|
||||
var descuento = parseFloat(row['descuento'])
|
||||
}
|
||||
|
||||
if(editor.column == 'descuento'){
|
||||
var descuento = parseFloat(state.value)
|
||||
if(isNaN(descuento)){
|
||||
msg = 'El descuento debe ser un número'
|
||||
msg_error(msg)
|
||||
grid.blockEvent()
|
||||
state.value = state.old
|
||||
grid.editCancel()
|
||||
grid.unblockEvent()
|
||||
return true
|
||||
}
|
||||
var cantidad = parseFloat(row['cantidad'])
|
||||
var valor_unitario = parseFloat(row['valor_unitario'])
|
||||
}
|
||||
|
||||
var precio_final = valor_unitario - descuento
|
||||
row['importe'] = (cantidad * precio_final).round(DECIMALES)
|
||||
|
||||
grid.refresh()
|
||||
if(cfg_ticket['edit_cant']){
|
||||
focus('tsearch_product_name')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function gt_productos_found_click(obj){
|
||||
buscar_producto_key(obj.clave)
|
||||
}
|
||||
|
||||
|
||||
function cancel_ticket(id){
|
||||
var grid = $$('grid_tickets')
|
||||
var data = new Object()
|
||||
data['opt'] = 'cancel'
|
||||
data['id'] = id
|
||||
|
||||
webix.ajax().sync().post('tickets', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
grid.updateItem(id, values.row)
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_cancelar_ticket_click(){
|
||||
var grid = $$('grid_tickets')
|
||||
|
||||
if(grid.count() == 0){
|
||||
return
|
||||
}
|
||||
|
||||
var row = grid.getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona un ticket')
|
||||
return
|
||||
}
|
||||
|
||||
if(row['estatus']=='Cancelado'){
|
||||
msg_error('El ticket ya esta cancelado')
|
||||
return
|
||||
}
|
||||
|
||||
if(row['estatus']=='Facturado'){
|
||||
msg_error('El ticket esta facturado')
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de cancelar el siguiente Ticket?<BR><BR>'
|
||||
msg += 'Folio: ' + row['folio']
|
||||
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER'
|
||||
webix.confirm({
|
||||
title:'Cancelar Ticket',
|
||||
ok:'Si',
|
||||
cancel:'No',
|
||||
type:'confirm-error',
|
||||
text:msg,
|
||||
callback:function(result){
|
||||
if (result){
|
||||
cancel_ticket(row['id'])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function chk_is_invoice_day_change(new_value, old_value){
|
||||
var value = Boolean(new_value)
|
||||
|
||||
show('fs_ticket_search_client', !value)
|
||||
enable('lst_global_periodicidad_2', value)
|
||||
enable('lst_global_months_2', value)
|
||||
|
||||
var current_date = new Date()
|
||||
var current_month = (current_date.getMonth() + 1).toString().padStart(2, '0')
|
||||
$$('lst_global_months_2').setValue(current_month)
|
||||
}
|
||||
|
||||
|
||||
function send_timbrar_invoice(id){
|
||||
webix.ajax().post('invoices', {opt: 'timbrar', id: id, update: false}, function(text, data){
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
webix.alert({
|
||||
title: 'Error al Timbrar',
|
||||
text: values.msg,
|
||||
type: 'alert-error'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function save_ticket_to_invoice(data){
|
||||
webix.ajax().sync().post('tickets', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
msg_ok(values.msg)
|
||||
send_timbrar_invoice(values.id)
|
||||
$$('chk_is_invoice_day').setValue(false)
|
||||
$$('multi_tickets').setValue('tickets_home')
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_new_invoice_from_ticket_click(){
|
||||
var form = this.getFormView();
|
||||
var chk = $$('chk_is_invoice_day')
|
||||
var grid = $$('grid_tickets_invoice')
|
||||
var values = form.getValues()
|
||||
var tickets = []
|
||||
|
||||
if(!chk.getValue()){
|
||||
if(values.id_partner == 0){
|
||||
webix.UIManager.setFocus('tsearch_client_name')
|
||||
msg = 'Selecciona un cliente'
|
||||
msg_error(msg)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if(!grid.count()){
|
||||
msg = 'Agrega al menos un ticket a facturar'
|
||||
msg_error(msg)
|
||||
return false
|
||||
}
|
||||
|
||||
grid.eachRow(function(row){
|
||||
tickets.push(row)
|
||||
})
|
||||
|
||||
var data = new Object()
|
||||
data['opt'] = 'invoice'
|
||||
|
||||
data['client'] = values.id_partner
|
||||
data['tickets'] = tickets
|
||||
data['is_invoice_day'] = chk.getValue()
|
||||
|
||||
var periodicidad = ''
|
||||
if(data['is_invoice_day']){
|
||||
periodicidad = $$('lst_global_periodicidad_2').getValue() + '|'
|
||||
periodicidad += $$('lst_global_months_2').getValue() + '|'
|
||||
periodicidad += new Date().getFullYear()
|
||||
}
|
||||
data['periodicidad'] = periodicidad
|
||||
|
||||
msg = 'Todos los datos son correctos.<BR><BR>'
|
||||
if(data['is_invoice_day']){
|
||||
msg += 'Es Factura Global.<BR><BR>'
|
||||
}
|
||||
msg += '¿Estás seguro de generar esta factura?'
|
||||
|
||||
webix.confirm({
|
||||
title: 'Generar Factura',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
save_ticket_to_invoice(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function grid_tickets_active_double_click(id, e, node){
|
||||
this.move(id.row, -1, $$('grid_tickets_invoice'))
|
||||
}
|
||||
|
||||
|
||||
function grid_tickets_invoice_double_click(id, e, node){
|
||||
this.move(id.row, -1, $$('grid_tickets_active'))
|
||||
}
|
||||
|
||||
|
||||
function cmd_move_tickets_right_click(){
|
||||
var source = $$('grid_tickets_active')
|
||||
var target = $$('grid_tickets_invoice')
|
||||
_move_tickets(source, target)
|
||||
}
|
||||
|
||||
|
||||
function cmd_move_tickets_left_click(){
|
||||
var target = $$('grid_tickets_active')
|
||||
var source = $$('grid_tickets_invoice')
|
||||
_move_tickets(source, target)
|
||||
}
|
||||
|
||||
|
||||
function _move_tickets(source, target){
|
||||
var rows = source.getSelectedItem()
|
||||
|
||||
if(rows == undefined){
|
||||
source.eachRow(
|
||||
function(row){
|
||||
this.copy(row, -1, target)
|
||||
}
|
||||
)
|
||||
source.clearAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ticket_set_client(row){
|
||||
var form = $$('form_ticket_invoice')
|
||||
var html = '<span class="webix_icon fa-user"></span><span class="lbl_partner">'
|
||||
form.setValues({
|
||||
id_partner: row.id,
|
||||
tsearch_client_key: '',
|
||||
tsearch_client_name: ''}, true)
|
||||
html += row.nombre + ' (' + row.rfc + ')</span>'
|
||||
$$('lbl_tclient').setValue(html)
|
||||
}
|
||||
|
||||
|
||||
function ticket_search_client_by_id(id){
|
||||
webix.ajax().get('/values/client', {'id': id}, {
|
||||
error: function(text, data, xhr) {
|
||||
msg_error('Error al consultar')
|
||||
},
|
||||
success: function(text, data, xhr){
|
||||
var values = data.json()
|
||||
if (values.ok){
|
||||
ticket_set_client(values.row)
|
||||
}else{
|
||||
msg = 'No se encontró un cliente con la clave: ' + id
|
||||
msg_error(msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function tsearch_client_key_press(code, e){
|
||||
var value = this.getValue()
|
||||
if(code == 13 && value.length > 0){
|
||||
var id = parseInt(value, 10)
|
||||
if (isNaN(id)){
|
||||
msg_error('Captura una clave válida')
|
||||
}else{
|
||||
ticket_search_client_by_id(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function grid_ticket_clients_found_click(obj){
|
||||
ticket_set_client(obj)
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_notes_click(){
|
||||
win_ticket_notes.init()
|
||||
var values = $$('form_new_ticket').getValues()
|
||||
$$('ticket_notes').setValue(values.notas)
|
||||
$$('win_ticket_notes').show()
|
||||
to_end('ticket_notes')
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_save_note_click(){
|
||||
var value = $$('ticket_notes').getValue()
|
||||
$$('form_new_ticket').setValues({notas: value}, true)
|
||||
$$('win_ticket_notes').close()
|
||||
|
||||
}
|
||||
|
||||
|
||||
function print_ticket(id){
|
||||
var data = new Object()
|
||||
data['opt'] = 'print'
|
||||
data['id'] = id
|
||||
|
||||
webix.ajax().post('tickets', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
msg_ok(values.msg)
|
||||
}else{
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function grid_tickets_click(id, e, node){
|
||||
if(id.column == 'pdf'){
|
||||
//~ window.open('/doc/tpdf/' + id, '_blank')
|
||||
get_ticket_pdf(id.row)
|
||||
return
|
||||
}
|
||||
|
||||
if(id.column == 'print'){
|
||||
print_ticket(id.row)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_report_pdf_click(){
|
||||
webix.toPDF($$('grid_tickets'), {
|
||||
ignore: {'pdf': true, 'print': true},
|
||||
filename: 'Reporte_Tickets',
|
||||
width: 612,
|
||||
height: 792,
|
||||
columns:{
|
||||
index: true,
|
||||
serie: {width: 50},
|
||||
folio: {width: 50},
|
||||
fecha: {width: 125},
|
||||
estatus: true,
|
||||
total: {css: 'right'},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_ticket_report_xls_click(){
|
||||
webix.toExcel($$('grid_tickets'), {
|
||||
filename: 'Reporte_Tickets',
|
||||
name: 'Tickets',
|
||||
ignore: {'pdf': true, 'print': true},
|
||||
rawValues: true,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function grid_tdetails_render(data){
|
||||
var total = 0.0
|
||||
this.eachRow(function(id){
|
||||
var item = this.getItem(id)
|
||||
total += item.importe
|
||||
})
|
||||
var id = $$('grid_ticket_total_up').getFirstId()
|
||||
$$('grid_ticket_total_up').updateItem(id, {total: total})
|
||||
}
|
|
@ -1,9 +1,30 @@
|
|||
var PUBLICO = "Público en general";
|
||||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 of the License, or
|
||||
//~ (at your option) any later version.
|
||||
//~
|
||||
//~ This program is distributed in the hope that it will be useful,
|
||||
//~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//~ GNU General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var PUBLICO = "PUBLICO EN GENERAL";
|
||||
var RFC_PUBLICO = "XAXX010101000";
|
||||
var RFC_EXTRANJERO = "XEXX010101000";
|
||||
var PAIS = "México";
|
||||
var DECIMALES = 2;
|
||||
//~ var DECIMALES_PU = 4;
|
||||
var DECIMALES_TAX = 4;
|
||||
var CLAVE_ANTICIPOS = '84111506';
|
||||
var CURRENCY_MN = 'MXN';
|
||||
var KEY_SAT_01 = '01010101';
|
||||
|
||||
|
||||
var db = new loki('data.db');
|
||||
|
@ -14,7 +35,9 @@ var table_totals = db.addCollection('totals', {unique: ['tax']})
|
|||
var table_series = db.addCollection('series')
|
||||
var table_usocfdi = db.addCollection('usocfdi')
|
||||
var table_relaciones = db.addCollection('relaciones')
|
||||
var table_waypayment = db.addCollection('waypayment')
|
||||
|
||||
var msg = ''
|
||||
|
||||
var months = [
|
||||
{id: -1, value: 'Todos'},
|
||||
|
@ -32,17 +55,89 @@ var months = [
|
|||
{id: 12, value: 'Diciembre'},
|
||||
]
|
||||
|
||||
var days = [
|
||||
{id: -1, value: '00'},
|
||||
{id: 1, value: '01'},
|
||||
{id: 2, value: '02'},
|
||||
{id: 3, value: '03'},
|
||||
{id: 4, value: '04'},
|
||||
{id: 5, value: '05'},
|
||||
{id: 6, value: '06'},
|
||||
{id: 7, value: '07'},
|
||||
{id: 8, value: '08'},
|
||||
{id: 9, value: '09'},
|
||||
{id: 10, value: '10'},
|
||||
{id: 11, value: '11'},
|
||||
{id: 12, value: '12'},
|
||||
{id: 13, value: '13'},
|
||||
{id: 14, value: '14'},
|
||||
{id: 15, value: '15'},
|
||||
{id: 16, value: '16'},
|
||||
{id: 17, value: '17'},
|
||||
{id: 18, value: '18'},
|
||||
{id: 19, value: '19'},
|
||||
{id: 20, value: '20'},
|
||||
{id: 21, value: '21'},
|
||||
{id: 22, value: '22'},
|
||||
{id: 23, value: '23'},
|
||||
{id: 24, value: '24'},
|
||||
{id: 25, value: '25'},
|
||||
{id: 26, value: '26'},
|
||||
{id: 27, value: '27'},
|
||||
{id: 28, value: '28'},
|
||||
{id: 29, value: '29'},
|
||||
{id: 30, value: '30'},
|
||||
{id: 31, value: '31'},
|
||||
]
|
||||
|
||||
|
||||
|
||||
function get_icon(tipo){
|
||||
icons = {
|
||||
xml: 'fa-file-code-o',
|
||||
pdf: 'fa-file-pdf-o',
|
||||
html: 'fa-html5',
|
||||
zip: 'fa-file-zip-o',
|
||||
email: 'fa-envelope-o',
|
||||
print: 'fa-print',
|
||||
table: 'fa-table',
|
||||
}
|
||||
return "<span class='webix_icon " + icons[tipo] + "'></span>"
|
||||
}
|
||||
|
||||
|
||||
function focus(name){
|
||||
webix.UIManager.setFocus(name)
|
||||
}
|
||||
|
||||
|
||||
function select_all(name){
|
||||
focus(name)
|
||||
$$(name).getInputNode().select()
|
||||
}
|
||||
|
||||
|
||||
function to_end(name){
|
||||
focus(name)
|
||||
var txt = $$(name)
|
||||
var pos = txt.getValue().length
|
||||
var height = txt.getInputNode().scrollHeight
|
||||
|
||||
webix.html.setSelectionRange(txt.getInputNode(), pos)
|
||||
txt.getInputNode().scrollTop = height
|
||||
}
|
||||
|
||||
|
||||
function showvar(values){
|
||||
webix.message(JSON.stringify(values, null, 2))
|
||||
}
|
||||
|
||||
|
||||
function showtype(values){
|
||||
webix.message(typeof(values))
|
||||
}
|
||||
|
||||
|
||||
function show(nombre, value){
|
||||
if(value == '0'){
|
||||
value = false
|
||||
|
@ -55,6 +150,23 @@ function show(nombre, value){
|
|||
}
|
||||
|
||||
|
||||
function show_column(table, column){
|
||||
$$(table).showColumn(column)
|
||||
}
|
||||
|
||||
|
||||
function enable(nombre, value){
|
||||
if(value == '0'){
|
||||
value = false
|
||||
}
|
||||
if(value){
|
||||
$$(nombre).enable()
|
||||
}else{
|
||||
$$(nombre).disable()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function msg_error(msg){
|
||||
if(!msg){
|
||||
msg = 'Error al consultar'
|
||||
|
@ -76,15 +188,65 @@ Number.prototype.round = function(decimals){
|
|||
String.prototype.is_number = function(){
|
||||
return /^\d+$/.test(this)
|
||||
}
|
||||
|
||||
|
||||
String.prototype.to_float = function(){
|
||||
return get_float(this)
|
||||
}
|
||||
String.prototype.to_float4 = function(){
|
||||
return get_float4(this)
|
||||
}
|
||||
|
||||
|
||||
function get_float(value){
|
||||
return parseFloat(value.replace('$', '').replace(',', '').trim()).round(2)
|
||||
var f = parseFloat(value.replace('$', '').replace(/,/g, '').trim()).round(DECIMALES)
|
||||
if(!f){
|
||||
f = 0.00
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
||||
function get_float4(value){
|
||||
var f = parseFloat(value.replace('$', '').replace(/,/g, '').trim()).round(DECIMALES_TAX)
|
||||
if(!f){
|
||||
f = 0.00
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
||||
var format_decimal_2 = webix.Number.numToStr({
|
||||
groupSize: 3,
|
||||
decimalSize: 2,
|
||||
groupDelimiter: ",",
|
||||
decimalDelimiter: "."
|
||||
})
|
||||
|
||||
var format_decimal_4 = webix.Number.numToStr({
|
||||
groupSize: 3,
|
||||
decimalSize: 4,
|
||||
groupDelimiter: ",",
|
||||
decimalDelimiter: "."
|
||||
})
|
||||
|
||||
|
||||
function format_currency(value){
|
||||
var fv = ''
|
||||
if(get_config('decimales_precios') == 4){
|
||||
fv = '$ ' + format_decimal_4(value)
|
||||
}else{
|
||||
fv = '$ ' + format_decimal_2(value)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
|
||||
function format_currency2(value){
|
||||
return '$ ' + format_decimal_2(value)
|
||||
}
|
||||
|
||||
|
||||
function format_currency4(value){
|
||||
return '$ ' + format_decimal_4(value)
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,6 +256,7 @@ webix.protoUI({
|
|||
$init:function(){
|
||||
this.attachEvent("onItemClick", function(){
|
||||
this.$setValue(this.config.raw, true)
|
||||
this.getInputNode().select()
|
||||
})
|
||||
this.attachEvent("onBlur", function(){
|
||||
this.$setValue(this.config.value)
|
||||
|
@ -105,18 +268,132 @@ webix.protoUI({
|
|||
$setValue:function(value, raw){
|
||||
this.config.raw = value
|
||||
if(!raw){
|
||||
value = webix.i18n.priceFormat(value)
|
||||
value = format_currency(value)
|
||||
}
|
||||
this.getInputNode().value = value
|
||||
}
|
||||
}, webix.ui.text)
|
||||
|
||||
|
||||
webix.ui.datafilter.rowCount = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = master.count();
|
||||
webix.protoUI({
|
||||
$cssName: "text",
|
||||
name: "currency4",
|
||||
$init:function(){
|
||||
this.attachEvent("onItemClick", function(){
|
||||
this.$setValue(this.config.raw, true)
|
||||
this.getInputNode().select()
|
||||
})
|
||||
this.attachEvent("onBlur", function(){
|
||||
this.$setValue(this.config.value)
|
||||
})
|
||||
},
|
||||
$render:function(){
|
||||
this.$setValue(this.config.value)
|
||||
},
|
||||
$setValue:function(value, raw){
|
||||
this.config.raw = value
|
||||
if(!raw){
|
||||
value = format_currency4(value)
|
||||
}
|
||||
this.getInputNode().value = value
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn)
|
||||
}, webix.ui.text)
|
||||
|
||||
|
||||
webix.protoUI({
|
||||
$cssName: "text",
|
||||
name: "currency2",
|
||||
$init:function(){
|
||||
this.attachEvent("onItemClick", function(){
|
||||
this.$setValue(this.config.raw, true)
|
||||
this.getInputNode().select()
|
||||
})
|
||||
this.attachEvent("onBlur", function(){
|
||||
this.$setValue(this.config.value)
|
||||
})
|
||||
},
|
||||
$render:function(){
|
||||
this.$setValue(this.config.value)
|
||||
},
|
||||
$setValue:function(value, raw){
|
||||
this.config.raw = value
|
||||
if(!raw){
|
||||
value = format_currency2(value)
|
||||
}
|
||||
this.getInputNode().value = value
|
||||
}
|
||||
}, webix.ui.text)
|
||||
|
||||
|
||||
webix.ui.datafilter.countRows = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = master.count();
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn);
|
||||
|
||||
|
||||
webix.ui.datafilter.summActive = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = this.summGenerate(master);
|
||||
},
|
||||
summGenerate:function(master){
|
||||
var sum = 0
|
||||
master.eachRow(function(id){
|
||||
var row = master.getItem(id)
|
||||
if(row.estatus == 'Generado'){
|
||||
var importe = row.total
|
||||
if(typeof importe === 'string'){
|
||||
importe = row.total.to_float()
|
||||
}
|
||||
sum += importe
|
||||
}
|
||||
})
|
||||
return webix.i18n.priceFormat(sum)
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn);
|
||||
|
||||
|
||||
webix.ui.datafilter.summTimbrada = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = this.summGenerate(master);
|
||||
},
|
||||
summGenerate:function(master){
|
||||
var sum = 0
|
||||
master.eachRow(function(id){
|
||||
var row = master.getItem(id)
|
||||
if(row.estatus == 'Timbrada'){
|
||||
var importe = row.total_mn
|
||||
if(typeof importe === 'string'){
|
||||
importe = row.total_mn.to_float()
|
||||
}
|
||||
sum += importe
|
||||
}
|
||||
})
|
||||
return webix.i18n.priceFormat(sum)
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn);
|
||||
|
||||
|
||||
webix.ui.datafilter.summTimbradaN = webix.extend({
|
||||
refresh:function(master, node, value){
|
||||
node.firstChild.innerHTML = this.summGenerate(master);
|
||||
},
|
||||
summGenerate:function(master){
|
||||
var sum = 0
|
||||
master.eachRow(function(id){
|
||||
var row = master.getItem(id)
|
||||
if(row.estatus == 'Timbrado'){
|
||||
var importe = row.total
|
||||
if(typeof importe === 'string'){
|
||||
importe = row.total.to_float()
|
||||
}
|
||||
sum += importe
|
||||
}
|
||||
})
|
||||
return webix.i18n.priceFormat(sum)
|
||||
}
|
||||
}, webix.ui.datafilter.summColumn);
|
||||
|
||||
|
||||
|
||||
function validate_rfc(value){
|
||||
|
@ -176,6 +453,58 @@ function validate_rfc(value){
|
|||
}
|
||||
|
||||
|
||||
function validar_rfc(value){
|
||||
rfc = value.trim().toUpperCase();
|
||||
if (rfc == ""){
|
||||
msg_error('El RFC no puede estar vacío')
|
||||
return false
|
||||
}
|
||||
|
||||
if (rfc.length < 12 || rfc.length > 13){
|
||||
msg_error('Longitud incorrecta del RFC')
|
||||
return false
|
||||
}
|
||||
|
||||
var length = rfc.length
|
||||
var start = 4
|
||||
if(length==12){
|
||||
start = 2
|
||||
}
|
||||
|
||||
var part = rfc.slice(0, start);
|
||||
var re = new RegExp('[a-z&Ñ]{' + start + '}', 'i');
|
||||
if (!part.match(re)){
|
||||
msg_error('El RFC tiene caractéres inválidos al inicio')
|
||||
return false
|
||||
}
|
||||
part = rfc.slice(-3);
|
||||
re = new RegExp('[a-z0-9]{3}', 'i');
|
||||
if (!part.match(re)){
|
||||
msg_error('El RFC tiene caractéres inválidos al final')
|
||||
return false
|
||||
}
|
||||
|
||||
part = rfc.slice(-9, -3);
|
||||
re = new RegExp('[0-9]{6}', 'i');
|
||||
if (!part.match(re)){
|
||||
msg_error('Fecha inválida')
|
||||
return false
|
||||
}
|
||||
var month = parseInt(part.slice(-4, -2))
|
||||
if (month == 0 || month > 12 ){
|
||||
msg_error('Fecha inválida')
|
||||
return false
|
||||
}
|
||||
var day = parseInt(part.slice(-2))
|
||||
if (day == 0 || day > 31 ){
|
||||
msg_error('Fecha inválida')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
function validate_email(email){
|
||||
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return re.test(email)
|
||||
|
@ -227,3 +556,141 @@ webix.DataDriver.plainjs = webix.extend({
|
|||
return this.hash2tree(hash, 0);
|
||||
}
|
||||
}, webix.DataDriver.json)
|
||||
|
||||
|
||||
function get_forma_pago(control){
|
||||
webix.ajax().get('/values/formapago', {key: true}, function(text, data){
|
||||
var values = data.json()
|
||||
$$(control).getList().parse(values)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function get_way_payment(){
|
||||
webix.ajax().get('/satformapago', {opt: 'active_by_id'}, function(text, data){
|
||||
var values = data.json()
|
||||
table_waypayment.clear()
|
||||
table_waypayment.insert(values)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function set_way_payment(control, filter99=false, current_way_payment=''){
|
||||
if(filter99){
|
||||
var values = table_waypayment.chain().find({'value': { '$ne' : 'Por definir' }}).data()
|
||||
}else{
|
||||
var values = table_waypayment.chain().data()
|
||||
}
|
||||
$$(control).getList().parse(values)
|
||||
if(current_way_payment){
|
||||
$$(control).setValue(current_way_payment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function validate_regexp(value, pattern){
|
||||
re = new RegExp(pattern, 'i');
|
||||
if(value.match(re)){
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function validate_pedimento(value){
|
||||
var pattern = '[0-9]{2} [0-9]{2} [0-9]{4} [0-9]{7}'
|
||||
return validate_regexp(value, pattern)
|
||||
}
|
||||
|
||||
|
||||
function validate_curp(value){
|
||||
var pattern = '[A-Z][A,E,I,O,U,X][A-Z]{2}[0-9]{2}[0-1][0-9][0-3][0-9][M,H][A-Z]{2}[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]'
|
||||
return validate_regexp(value, pattern)
|
||||
}
|
||||
|
||||
|
||||
//config may as well include only text, color and date hash
|
||||
webix.editors.$popup = {
|
||||
text:{
|
||||
view: 'popup', width:500, height:200,
|
||||
body: {view: 'textarea'}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
function pause(milliseconds) {
|
||||
var dt = new Date();
|
||||
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
|
||||
}
|
||||
|
||||
|
||||
|
||||
//~ Revisado
|
||||
|
||||
function lst_clear(lst){
|
||||
lst.setValue('')
|
||||
lst.define('options', [])
|
||||
lst.refresh()
|
||||
}
|
||||
|
||||
|
||||
function lst_parse(lst, values){
|
||||
lst.getList().parse(values)
|
||||
}
|
||||
|
||||
|
||||
function lst_parse2(lst_name, values){
|
||||
obj = $$(lst_name)
|
||||
obj.getList().parse(values)
|
||||
}
|
||||
|
||||
|
||||
function set_value(control, value){
|
||||
obj = $$(control)
|
||||
obj.blockEvent()
|
||||
obj.setValue(value)
|
||||
obj.unblockEvent()
|
||||
}
|
||||
|
||||
|
||||
function grid_parse(grid_name, values){
|
||||
obj = $$(grid_name)
|
||||
obj.clearAll()
|
||||
obj.parse(values)
|
||||
}
|
||||
|
||||
|
||||
function activate_tab(parent, name){
|
||||
$$(parent).getTabbar().setValue(name)
|
||||
}
|
||||
|
||||
|
||||
var opt_global_periodicidad = [
|
||||
{id: '01', value: '[01] Diario'},
|
||||
{id: '02', value: '[02] Semanal'},
|
||||
{id: '03', value: '[03] Quincenal'},
|
||||
{id: '04', value: '[04] Mensual'},
|
||||
{id: '05', value: '[05] Bimestral'},
|
||||
]
|
||||
|
||||
var opt_global_months = [
|
||||
{id: '01', value: '[01] Enero'},
|
||||
{id: '02', value: '[02] Febrero'},
|
||||
{id: '03', value: '[03] Marzo'},
|
||||
{id: '04', value: '[04] Abril'},
|
||||
{id: '05', value: '[05] Mayo'},
|
||||
{id: '06', value: '[06] Junio'},
|
||||
{id: '07', value: '[07] Julio'},
|
||||
{id: '08', value: '[08] Agosto'},
|
||||
{id: '09', value: '[09] Septiembre'},
|
||||
{id: '10', value: '[10] Octubre'},
|
||||
{id: '11', value: '[11] Noviembre'},
|
||||
{id: '12', value: '[12] Diciembre'},
|
||||
{id: '13', value: '[13] Enero-Febrero'},
|
||||
{id: '14', value: '[14] Marzo-Abril'},
|
||||
{id: '15', value: '[15] Mayo-Junio'},
|
||||
{id: '16', value: '[16] Julio-Agosto'},
|
||||
{id: '17', value: '[17] Septiembre-Octubre'},
|
||||
{id: '18', value: '[18] Noviembre-Diciembre'},
|
||||
]
|
||||
|
|
|
@ -29,10 +29,6 @@ webix.i18n.locales["es-ES"] = {
|
|||
today: "Hoy"
|
||||
},
|
||||
|
||||
controls:{
|
||||
select:"Seleccione",
|
||||
invalidMessage: "Valor de entrada no válido"
|
||||
},
|
||||
dataExport:{
|
||||
page:"Página",
|
||||
of:"de"
|
||||
|
@ -81,7 +77,12 @@ webix.i18n.locales["es-ES"] = {
|
|||
italic: "Itálico"
|
||||
},
|
||||
combo:{
|
||||
select:"Seleccionar",
|
||||
selectAll:"Seleccionar todo",
|
||||
unselectAll:"Deselecciona todo"
|
||||
},
|
||||
message:{
|
||||
ok:"OK",
|
||||
cancel:"Cancelar"
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,275 +0,0 @@
|
|||
webix.protoUI({
|
||||
name: "sidebar",
|
||||
defaults:{
|
||||
titleHeight: 40,
|
||||
type: "sideBar",
|
||||
activeTitle: true,
|
||||
select: true,
|
||||
scroll: false,
|
||||
collapsed: false,
|
||||
collapsedWidth: 41,
|
||||
position: "left",
|
||||
width: 250,
|
||||
mouseEventDelay: 10
|
||||
},
|
||||
$init: function(config){
|
||||
this.$ready.push(this._initSidebar);
|
||||
this.$ready.push(this._initContextMenu);
|
||||
},
|
||||
|
||||
on_context:{},
|
||||
on_mouse_move:{},
|
||||
_initSidebar: function(){
|
||||
this._fullWidth = this.config.width;
|
||||
this.attachEvent("onBeforeOpen", function(id){
|
||||
if(!this.config.multipleOpen)
|
||||
this.closeAll();
|
||||
return !this.config.collapsed;
|
||||
});
|
||||
this.attachEvent("onItemClick", function(id, ev, node){
|
||||
if(this.getPopup() && !this.getPopup().config.hidden)
|
||||
ev.showpopup = true;
|
||||
if(webix.env.touch)
|
||||
this._showPopup(id, node);
|
||||
});
|
||||
this.attachEvent("onBeforeSelect", function(id){
|
||||
if(!this.getItem(id).$count){
|
||||
var selected = this.getSelectedId();
|
||||
if(selected && id!= selected){
|
||||
var parentId = this.getParentId(selected);
|
||||
|
||||
this.removeCss(parentId, "webix_sidebar_selected");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.attachEvent("onAfterSelect", function(id){
|
||||
var parentId = this.getParentId(id);
|
||||
this.addCss(parentId, "webix_sidebar_selected");
|
||||
var title = this.getPopupTitle();
|
||||
|
||||
title.callEvent("onMasterSelect",[id]);
|
||||
});
|
||||
this.attachEvent("onMouseMove", function(id, ev, node){
|
||||
this._showPopup(id, node);
|
||||
});
|
||||
|
||||
if(this.config.collapsed)
|
||||
this.collapse();
|
||||
},
|
||||
_showPopup: function(id, node){
|
||||
if(this.config.collapsed){
|
||||
var popup = this.getPopup();
|
||||
|
||||
if(popup){
|
||||
var title = this.getPopupTitle();
|
||||
if(title){
|
||||
this._updateTitle(id);
|
||||
}
|
||||
var list = this.getPopupList();
|
||||
if(list){
|
||||
this._updateList(id);
|
||||
}
|
||||
var x = (this.config.position == "left"?this.config.collapsedWidth:-popup.config.width);
|
||||
popup.show(node, {x: x , y:-1});
|
||||
}
|
||||
}
|
||||
},
|
||||
_updateTitle: function(id){
|
||||
var title = this.getPopupTitle();
|
||||
title.masterId = id;
|
||||
title.parse(this.getItem(id));
|
||||
var selectedId = this.getSelectedId();
|
||||
if(selectedId && this.getParentId(selectedId) == id){
|
||||
webix.html.addCss(title.$view, "webix_sidebar_selected", true);
|
||||
}
|
||||
else{
|
||||
webix.html.removeCss(title.$view, "webix_sidebar_selected");
|
||||
}
|
||||
|
||||
if(selectedId == id){
|
||||
webix.html.addCss(title.$view, "webix_selected", true);
|
||||
}
|
||||
else{
|
||||
webix.html.removeCss(title.$view, "webix_selected");
|
||||
}
|
||||
},
|
||||
_updateList: function(id){
|
||||
var list = this.getPopupList();
|
||||
list.masterId = id;
|
||||
var selectedId = this.getSelectedId();
|
||||
var data = [].concat(webix.copy(this.data.getBranch(id)));
|
||||
list.unselect();
|
||||
if(data.length){
|
||||
list.show();
|
||||
list.data.importData(data);
|
||||
if(list.exists(selectedId))
|
||||
list.select(selectedId);
|
||||
}
|
||||
else
|
||||
list.hide();
|
||||
|
||||
},
|
||||
_initContextMenu: function(){
|
||||
var config = this.config,
|
||||
popup;
|
||||
|
||||
if(config.popup){
|
||||
popup = webix.$$(config.popup);
|
||||
}
|
||||
if(!popup){
|
||||
var dirClassName = (config.position=="left"?"webix_sidebar_popup_left":"webix_sidebar_popup_right");
|
||||
var popupConfig = {
|
||||
view:"popup",
|
||||
css: "webix_sidebar_popup "+dirClassName,
|
||||
autofit: false,
|
||||
width: this._fullWidth - this.config.collapsedWidth,
|
||||
borderless: true,
|
||||
padding:0,
|
||||
body:{
|
||||
rows:[
|
||||
{
|
||||
view: "template", borderless: true, css: "webix_sidebar_popup_title",
|
||||
template: "#value#", height: this.config.titleHeight+2,
|
||||
on:{
|
||||
onMasterSelect: function(id){
|
||||
var master = this.getTopParentView().master;
|
||||
if( master && master.getParentId(id) == this.masterId){
|
||||
webix.html.addCss(this.$view, "webix_sidebar_selected", true);
|
||||
}
|
||||
if(master.config.collapsed && master.getItem(id).$level ==1){
|
||||
webix.html.addCss(this.$view, "webix_selected", true);
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick:{
|
||||
webix_template: function(){
|
||||
var id = this.masterId;
|
||||
var master = this.getTopParentView().master;
|
||||
if(!master.getItem(id).$count)
|
||||
master.select(id);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ view: "list", select: true, borderless: true, css: "webix_sidebar_popup_list", autoheight: true,
|
||||
on:{
|
||||
onAfterSelect: function(id){
|
||||
this.getTopParentView().master.select(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
webix.extend(popupConfig, config.popup||{}, true);
|
||||
popup = webix.ui(popupConfig);
|
||||
popup.master = this;
|
||||
}
|
||||
popup.attachEvent("onBeforeShow",function(){
|
||||
return config.collapsed;
|
||||
});
|
||||
var master = this;
|
||||
var h = webix.event(document.body,"mousemove", function(e){
|
||||
var trg = e.target || e.srcElement;
|
||||
if(!popup.config.hidden && !popup.$view.contains(trg) && !master.$view.firstChild.contains(trg)){
|
||||
popup.hide();
|
||||
}
|
||||
});
|
||||
this.attachEvent("onDestruct", function(){
|
||||
if(webix.removeEvent)
|
||||
webix.removeEvent(h);
|
||||
if(popup)
|
||||
popup.destructor();
|
||||
});
|
||||
config.popupId = popup.config.id;
|
||||
},
|
||||
getPopup: function(){
|
||||
return webix.$$(this.config.popupId);
|
||||
},
|
||||
getPopupTitle: function(){
|
||||
var popup = this.getPopup();
|
||||
return popup.getBody().getChildViews()[0];
|
||||
},
|
||||
getPopupList: function(){
|
||||
var popup = this.getPopup();
|
||||
return popup.getBody().getChildViews()[1];
|
||||
},
|
||||
position_setter:function(value){
|
||||
var newPos = value;
|
||||
var oldPos = value=="left"?"right":"left";
|
||||
|
||||
webix.html.removeCss(this.$view, "webix_sidebar_"+oldPos);
|
||||
webix.html.addCss(this.$view, "webix_sidebar_"+newPos, true);
|
||||
|
||||
var popup = this.getPopup();
|
||||
if(popup){
|
||||
var popupEl = popup.$view;
|
||||
webix.html.removeCss(popupEl, "webix_sidebar_popup_"+oldPos);
|
||||
webix.html.addCss(popupEl, "webix_sidebar_popup_"+newPos, true);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
collapse: function(){
|
||||
this.define("collapsed", true);
|
||||
},
|
||||
expand: function(){
|
||||
this.define("collapsed", false);
|
||||
},
|
||||
toggle: function(){
|
||||
var collapsed = !this.config.collapsed;
|
||||
this.define("collapsed", collapsed);
|
||||
},
|
||||
collapsed_setter: function(value){
|
||||
var width;
|
||||
|
||||
if(!value){
|
||||
width = this._fullWidth;
|
||||
}
|
||||
else{
|
||||
width = this.config.collapsedWidth;
|
||||
this.closeAll();
|
||||
}
|
||||
|
||||
if(!value){
|
||||
this.type.collapsed = false;
|
||||
webix.html.addCss(this.$view, "webix_sidebar_expanded", true);
|
||||
}
|
||||
else{
|
||||
this.type.collapsed = true;
|
||||
webix.html.removeCss(this.$view, "webix_sidebar_expanded");
|
||||
}
|
||||
|
||||
this.define("width",width);
|
||||
this.resize();
|
||||
|
||||
return value;
|
||||
}
|
||||
}, webix.ui.tree);
|
||||
|
||||
webix.type(webix.ui.tree, {
|
||||
name:"sideBar",
|
||||
height: "auto",
|
||||
css: "webix_sidebar",
|
||||
template: function(obj, common){
|
||||
if(common.collapsed)
|
||||
return common.icon(obj, common);
|
||||
return common.arrow(obj, common)+common.icon(obj, common) +"<span>"+obj.value+"</span>";
|
||||
},
|
||||
arrow: function(obj, common){
|
||||
var html = "";
|
||||
var open = "";
|
||||
for (var i=1; i<=obj.$level; i++){
|
||||
if (i==obj.$level && obj.$count){
|
||||
var className = "webix_sidebar_dir_icon webix_icon fa-angle-"+(obj.open?"down":"left");
|
||||
html+="<span class='"+className+"'></span>";
|
||||
}
|
||||
}
|
||||
return html;
|
||||
},
|
||||
icon:function(obj, common){
|
||||
if(obj.icon)
|
||||
return "<span class='webix_icon webix_sidebar_icon fa-"+obj.icon+"'></span>";
|
||||
return "";
|
||||
}
|
||||
});
|
|
@ -1,20 +1,35 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 of the License, or
|
||||
//~ (at your option) any later version.
|
||||
//~
|
||||
//~ This program is distributed in the hope that it will be useful,
|
||||
//~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//~ GNU General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var toolbar_banco = [
|
||||
{view: 'richselect', id: 'lst_cuentas_banco', label: 'Cuenta',
|
||||
labelWidth: 100, options: []},
|
||||
{view: 'text', id: 'txt_cuenta_moneda', label: 'Moneda', readonly: true},
|
||||
{view: 'currency', id: 'txt_cuenta_saldo', label: 'Saldo', readonly: true,
|
||||
{view: 'currency2', id: 'txt_cuenta_saldo', label: 'Saldo', readonly: true,
|
||||
inputAlign: 'right', value: 0}
|
||||
]
|
||||
|
||||
|
||||
var toolbar_filtro_cuenta = [
|
||||
{view: 'richselect', id: 'filtro_cuenta_year', label: 'Año',
|
||||
{view: 'richselect', id: 'filter_cuenta_year', label: 'Año',
|
||||
labelAlign: 'right', labelWidth: 50, width: 150, options: []},
|
||||
{view: 'richselect', id: 'filtro_cuenta_mes', label: 'Mes',
|
||||
{view: 'richselect', id: 'filter_cuenta_month', label: 'Mes',
|
||||
labelAlign: 'right', labelWidth: 50, width: 200, options: months},
|
||||
{view: 'daterangepicker', id: 'filtro_cuenta_fechas', label: 'Fechas',
|
||||
{view: 'daterangepicker', id: 'filter_cuenta_dates', label: 'Fechas',
|
||||
labelAlign: 'right', width: 300},
|
||||
{},
|
||||
]
|
||||
|
@ -26,6 +41,11 @@ var toolbar_movimientos_banco = [
|
|||
{view: 'button', id: 'cmd_agregar_deposito', label: 'Depósito',
|
||||
type: 'iconButton', autowidth: true, icon: 'plus'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_complemento_pago', label: 'Generar Factura de Pago',
|
||||
type: 'iconButton', autowidth: true, icon: 'file-code-o'},
|
||||
{view: 'button', id: 'cmd_show_invoice_pay', label: 'Ver Facturas de Pago',
|
||||
type: 'iconButton', autowidth: true, icon: 'table'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_cancelar_movimiento', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
]
|
||||
|
@ -35,6 +55,7 @@ var grid_cuentabanco_cols = [
|
|||
{id: 'id', header:'ID', hidden: true},
|
||||
{id: 'fecha', header: 'Fecha', width: 150},
|
||||
{id: 'numero_operacion', header: 'Referencia'},
|
||||
{id: 'way_payment', header: 'Forma de Pago', hidden: true},
|
||||
{id: 'descripcion', header: ['Descripción', {content: 'textFilter'}],
|
||||
fillspace:true},
|
||||
{id: 'retiro', header: ['Retiro', {content: 'numberFilter'}],
|
||||
|
@ -43,6 +64,7 @@ var grid_cuentabanco_cols = [
|
|||
width: 125, format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'saldo', header: ['Saldo'],
|
||||
width: 125, format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'invoice', header: ['FP'], width: 40, css: 'center', hidden: true},
|
||||
]
|
||||
|
||||
|
||||
|
@ -62,7 +84,7 @@ var grid_cfdi_por_pagar_cols = [
|
|||
{id: 'index', header: '#', adjust: 'data', css: 'right'},
|
||||
{id: 'id', header: 'ID', hidden: true},
|
||||
{id: 'serie', header: 'Serie', adjust: 'data'},
|
||||
{id: 'folio', header: 'Folio', adjust: 'data', css: 'right'},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'data', css: 'right'},
|
||||
{id: 'uuid', header: 'UUID', width: 250, hidden: true},
|
||||
{id: 'fecha', header: 'Fecha y Hora', width: 150, sort: 'date'},
|
||||
{id: 'tipo_comprobante', header: 'Tipo', adjust: 'data'},
|
||||
|
@ -70,6 +92,10 @@ var grid_cfdi_por_pagar_cols = [
|
|||
{id: 'cliente', header: ['Razón Social', {content: 'selectFilter'}],
|
||||
fillspace:true, sort: 'string'},
|
||||
{id: 'total', header: ['Total'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right', hidden: true},
|
||||
{id: 'currency', header: ['Moneda', {content: 'selectFilter'}],
|
||||
adjust: 'data', sort: 'string', hidden: true},
|
||||
{id: 'total_mn', header: ['Total M.N'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'saldo', header: ['Saldo'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
|
@ -87,11 +113,62 @@ var grid_cfdi_este_deposito_cols = [
|
|||
{id: 'estatus', header: 'Estatus', adjust: 'header'},
|
||||
{id: 'cliente', header: ['Razón Social'], fillspace: true},
|
||||
{id: 'total', header: ['Total'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right', hidden: true},
|
||||
{id: 'currency', header: ['Moneda', {content: 'selectFilter'}],
|
||||
adjust: 'data', sort: 'string', hidden: true},
|
||||
{id: 'total_mn', header: ['Total M.N'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'saldo', header: ['Saldo'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'this_pay', header: ['Este pago'], width: 125, sort: 'int', hidden: true,
|
||||
format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
||||
{id: 'importe', header: ['Este pago'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
||||
{id: 'type_change', header: ['T.C.'], width: 75, hidden: true,
|
||||
format: format_currency4, css: 'right'},
|
||||
]
|
||||
|
||||
|
||||
var grid_cfdi_pay_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: 'serie', header: ["Serie"], adjust: "data", sort: 'string'},
|
||||
{id: 'folio', header: ['Folio'], adjust: 'data',
|
||||
sort: 'int', css: 'right', footer: {text: 'Facturas', colspan: 3}},
|
||||
{id: "uuid", header: ["UUID"], adjust: "data",
|
||||
sort:"string", hidden:true},
|
||||
{id: "fecha", header: ["Fecha y Hora"],
|
||||
adjust: "data", sort: "string"},
|
||||
{id: "tipo_comprobante", header: ["Tipo"],
|
||||
adjust: 'header', sort: 'string'},
|
||||
{id: "estatus", header: ["Estatus"],
|
||||
adjust: "data", sort:"string"},
|
||||
{id: 'cliente', header: ['Razón Social'], fillspace: true},
|
||||
{id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
{id: 'email', header: '@', adjust: 'data', template: get_icon('email')}
|
||||
]
|
||||
|
||||
|
||||
var grid_pay_related_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right'},
|
||||
{id: 'id', header: 'ID', hidden: true},
|
||||
{id: 'serie', header: 'Serie', adjust: 'data'},
|
||||
{id: 'folio', header: 'Folio', adjust: 'data', css: 'right'},
|
||||
{id: 'uuid', header: 'UUID', width: 250, hidden: true},
|
||||
{id: 'fecha', header: 'Fecha y Hora', width: 150, sort: 'date'},
|
||||
{id: 'tipo_comprobante', header: 'Tipo', adjust: 'data'},
|
||||
{id: 'estatus', header: 'Estatus', adjust: 'header'},
|
||||
{id: 'cliente', header: ['Razón Social'], fillspace: true},
|
||||
{id: 'total', header: ['Total'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'saldo', header: ['Saldo'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right', css: 'right',
|
||||
footer: 'Importe Depósito'},
|
||||
{id: 'importe', header: ['Este pago'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summColumn', css: 'right'}},
|
||||
]
|
||||
|
||||
|
||||
|
@ -99,6 +176,7 @@ var grid_cfdi_por_pagar = {
|
|||
view: 'datatable',
|
||||
id: 'grid_cfdi_por_pagar',
|
||||
select: 'row',
|
||||
multiselect: true,
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
height: 250,
|
||||
|
@ -120,6 +198,7 @@ var grid_cfdi_este_deposito = {
|
|||
view: 'datatable',
|
||||
id: 'grid_cfdi_este_deposito',
|
||||
select: 'row',
|
||||
multiselect: true,
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
height: 200,
|
||||
|
@ -138,9 +217,111 @@ var grid_cfdi_este_deposito = {
|
|||
}
|
||||
|
||||
|
||||
var grid_cfdi_pay = {
|
||||
view: 'datatable',
|
||||
id: 'grid_cfdi_pay',
|
||||
select: 'row',
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_cfdi_pay_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var grid_pay_related = {
|
||||
view: 'datatable',
|
||||
id: 'grid_pay_related',
|
||||
select: 'row',
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
footer: true,
|
||||
columns: grid_pay_related_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var grid_bank_invoice_pay_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: 'serie', header: ["Serie"], adjust: "data", sort: 'string',
|
||||
template: '{common.subrow()} #serie#'},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
|
||||
sort: 'int', css: 'right', footer: {text: 'Facturas', colspan: 3}},
|
||||
{id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data",
|
||||
sort:"string", hidden:true},
|
||||
{id: "fecha", header: ["Fecha y Hora"], width: 135,
|
||||
sort: "string"},
|
||||
{id: "tipo_comprobante", header: ["Tipo"], adjust: 'data',
|
||||
sort: 'string'},
|
||||
{id: "estatus", header: ["Estatus", {content: "selectFilter"}],
|
||||
adjust: "header", sort:"string"},
|
||||
{id: 'movimiento', header: ['Movimiento', {content: "selectFilter"}],
|
||||
adjust: 'data', sort: 'string'},
|
||||
{id: 'total', header: ['Total', {content: 'numberFilter'}],
|
||||
width: 125, sort: 'int', format: webix.i18n.priceFormat, css: 'right',
|
||||
hidden: true},
|
||||
{id: 'currency', header: ['Moneda', {content: 'selectFilter'}],
|
||||
adjust: 'data', sort: 'string', hidden: true},
|
||||
{id: 'total_mn', header: ['Total M.N.', {content: 'numberFilter'}],
|
||||
width: 150, sort: 'int', format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summTimbrada', css: 'right'}},
|
||||
{id: 'cliente', header: ['Razón Social', {content: 'selectFilter'}],
|
||||
fillspace: true, sort: 'string'},
|
||||
{id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
//~ {id: 'ods', header: 'ODS', adjust: 'data', template: get_icon('table')},
|
||||
//~ {id: 'zip', header: 'ZIP', adjust: 'data', template: get_icon('zip')},
|
||||
{id: 'email', header: '@', adjust: 'data', template: get_icon('email')}
|
||||
]
|
||||
|
||||
|
||||
var grid_bank_invoice_pay = {
|
||||
view: 'datatable',
|
||||
id: 'grid_bank_invoice_pay',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_bank_invoice_pay_cols,
|
||||
scheme:{
|
||||
$change:function(item){
|
||||
if (item.estatus == 'Cancelada'){
|
||||
item.$css = 'cancel'
|
||||
}
|
||||
}
|
||||
},
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var toolbar_banco_retiro = [
|
||||
{view: 'label', label: 'Agregar retiro de banco'},
|
||||
{},
|
||||
{view: 'label', label: 'Agregar retiro de banco', id: 'title_bank_retiro'},
|
||||
{view: 'button', id: 'cmd_guardar_retiro', label: 'Guardar Retiro',
|
||||
type: 'iconButton', autowidth: true, icon: 'minus'},
|
||||
{view: 'icon', click: '$$("multi_bancos").setValue("banco_home")',
|
||||
|
@ -149,8 +330,7 @@ var toolbar_banco_retiro = [
|
|||
|
||||
|
||||
var toolbar_banco_deposito = [
|
||||
{view: 'label', label: 'Agregar depósito de banco'},
|
||||
{},
|
||||
{view: 'label', label: 'Agregar depósito de banco', id: 'title_bank_deposit'},
|
||||
{view: 'button', id: 'cmd_guardar_deposito', label: 'Guardar Depósito',
|
||||
type: 'iconButton', autowidth: true, icon: 'plus'},
|
||||
{view: 'icon', click: '$$("multi_bancos").setValue("banco_home")',
|
||||
|
@ -158,6 +338,46 @@ var toolbar_banco_deposito = [
|
|||
]
|
||||
|
||||
|
||||
var toolbar_bank_pay = [
|
||||
{view: 'label', label: 'Factura de pago'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_pay_stamp', label: 'Timbrar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ticket'},
|
||||
{view: 'button', id: 'cmd_pay_cancel', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'minus'},
|
||||
{view: 'button', id: 'cmd_pay_delete', label: 'Eliminar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
{view: 'checkbox', id: 'chk_pay_close_when_stamp',
|
||||
label: 'Cerrar al timbrar', tooltip: 'Cerrar al timbrar'},
|
||||
{},
|
||||
{view: 'icon', click: '$$("multi_bancos").setValue("banco_home")',
|
||||
icon: 'times-circle'}
|
||||
]
|
||||
|
||||
|
||||
var toolbar_bank_invoice_pay = [
|
||||
{view: 'label', label: 'Administración de Facturas de Pago'},
|
||||
{},
|
||||
{view: 'icon', click: '$$("multi_bancos").setValue("banco_home")',
|
||||
icon: 'times-circle'}
|
||||
]
|
||||
|
||||
|
||||
var toolbar_bank_invoice_pay_filter = [
|
||||
{view: 'richselect', id: 'filter_invoice_pay_year', label: 'Año',
|
||||
labelAlign: 'right', labelWidth: 50, width: 150, options: []},
|
||||
{view: 'richselect', id: 'filter_invoice_pay_month', label: 'Mes',
|
||||
labelAlign: 'right', labelWidth: 50, width: 175, options: months},
|
||||
{view: 'daterangepicker', id: 'filter_invoice_pay_dates', label: 'Fechas',
|
||||
labelAlign: 'right', width: 275},
|
||||
{view: 'button', id: 'cmd_invoice_pay_sat', label: 'SAT',
|
||||
type: 'iconButton', autowidth: true, icon: 'check-circle'},
|
||||
{view: 'button', id: 'cmd_invoice_pay_cancel', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
{},
|
||||
]
|
||||
|
||||
|
||||
var controls_banco_retiro = [
|
||||
{view: 'toolbar', elements: toolbar_banco_retiro},
|
||||
{cols: [
|
||||
|
@ -176,7 +396,7 @@ var controls_banco_retiro = [
|
|||
{view: 'richselect', id: 'lst_retiro_forma_pago',
|
||||
name: 'retiro_forma_pago', label: 'Forma de Pago', required: true,
|
||||
options: [], labelWidth: 125, labelAlign: 'right'},
|
||||
{view: 'currency', type: 'text', id: 'txt_retiro_importe',
|
||||
{view: 'currency2', type: 'text', id: 'txt_retiro_importe',
|
||||
name: 'retiro_importe', label: 'Importe', labelAlign: 'right',
|
||||
required: true, invalidMessage: 'Captura un valor númerico',
|
||||
inputAlign: 'right', value: ''}
|
||||
|
@ -207,23 +427,78 @@ var controls_banco_deposito = [
|
|||
{view: 'richselect', id: 'lst_deposito_forma_pago',
|
||||
name: 'deposito_forma_pago', label: 'Forma de Pago', required: true,
|
||||
options: [], labelWidth: 125, labelAlign: 'right'},
|
||||
{view: 'currency', type: 'text', id: 'txt_deposito_importe',
|
||||
{view: 'currency2', type: 'text', id: 'txt_deposito_importe',
|
||||
name: 'deposito_importe', label: 'Importe', labelAlign: 'right',
|
||||
required: true, invalidMessage: 'Captura un valor númerico',
|
||||
inputAlign: 'right', value: ''}
|
||||
inputAlign: 'right', value: ''},
|
||||
{view: 'currency4', type: 'text', id: 'deposit_type_change',
|
||||
name: 'deposit_type_change', label: 'T.C.', labelAlign: 'right',
|
||||
required: false, invalidMessage: 'Captura un valor númerico',
|
||||
inputAlign: 'right', value: '1.0000', width: 175, hidden: true}
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'textarea', id: 'deposito_descripcion', label: 'Descripción',
|
||||
name: 'deposito_descripcion', labelAlign: 'right', required: true,
|
||||
labelWidth: 125, height: 70},
|
||||
]},
|
||||
{view: 'label', label: '<b>Facturas por pagar: </b>'},
|
||||
{cols: [
|
||||
{view: 'label', label: '<b>Facturas por pagar: </b>'},
|
||||
{view: 'richselect', id: 'lst_partner_account_bank', hidden: true,
|
||||
name: 'partner_account_bank', label: 'Cuenta Origen', required: false,
|
||||
options: [], labelWidth: 125, labelAlign: 'right'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_invoice_payed', label: 'Solo marcar pagada',
|
||||
type: 'iconButton', autowidth: true, icon: 'check-circle',
|
||||
tooltip: 'No afecta a saldos'},
|
||||
]},
|
||||
grid_cfdi_por_pagar,
|
||||
{view: 'label', label: '<b>Facturas a pagar en este depósito: </b>'},
|
||||
grid_cfdi_este_deposito,
|
||||
]
|
||||
|
||||
|
||||
var controls_bank_pay = [
|
||||
{view: 'toolbar', elements: toolbar_bank_pay},
|
||||
{view: 'label', label: '<b>Este depósito: </b>'},
|
||||
{cols: [
|
||||
{view: 'datepicker', id: 'pay_date', name: 'pay_date',
|
||||
label: 'Fecha', format: '%d-%M-%Y', labelAlign: 'right',
|
||||
required: true, invalidMessage: 'Selecciona una fecha',
|
||||
labelWidth: 125, readonly: true},
|
||||
{view: 'search', id: 'pay_time', name: 'pay_time', label: 'Hora',
|
||||
icon: 'clock-o', labelAlign: 'right', required: true,
|
||||
readonly: true,
|
||||
invalidMessage: 'Captura una hora'},
|
||||
{view: 'text', id: 'pay_reference', name: 'pay_reference',
|
||||
label: 'Referencia', labelAlign: 'right', readonly: true},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'richselect', id: 'pay_way_payment', readonly: true,
|
||||
name: 'pay_way_payment', label: 'Forma de Pago', required: true,
|
||||
options: [], labelWidth: 125, labelAlign: 'right'},
|
||||
{view: 'currency', type: 'text', id: 'pay_import', name: 'pay_import',
|
||||
label: 'Importe', labelAlign: 'right', required: true, readonly: true,
|
||||
invalidMessage: 'Captura un valor númerico', inputAlign: 'right'}
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'textarea', id: 'pay_description', label: 'Descripción',
|
||||
name: 'pay_description', labelAlign: 'right', required: true,
|
||||
labelWidth: 125, height: 70, readonly: true},
|
||||
]},
|
||||
{view: 'label', label: '<b>Facturas de pago de este depósito: </b>'},
|
||||
grid_cfdi_pay,
|
||||
{view: 'label', label: '<b>Facturas relacionadas en este pago: </b>'},
|
||||
grid_pay_related
|
||||
]
|
||||
|
||||
|
||||
var controls_bank_invoice_pay = [
|
||||
{view: 'toolbar', elements: toolbar_bank_invoice_pay},
|
||||
{view: 'toolbar', elements: toolbar_bank_invoice_pay_filter},
|
||||
grid_bank_invoice_pay
|
||||
]
|
||||
|
||||
|
||||
var form_banco_retiro = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
|
@ -250,6 +525,32 @@ var form_banco_deposito = {
|
|||
}
|
||||
|
||||
|
||||
var form_bank_pay = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_bank_pay',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_bank_pay,
|
||||
}],
|
||||
}
|
||||
|
||||
|
||||
var form_bank_invoice_pay = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_bank_invoice_pay',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_bank_invoice_pay,
|
||||
}],
|
||||
}
|
||||
|
||||
|
||||
var multi_bancos = {
|
||||
id: 'multi_bancos',
|
||||
animate: true,
|
||||
|
@ -261,7 +562,9 @@ var multi_bancos = {
|
|||
grid_cuentabanco,
|
||||
]},
|
||||
{id: 'banco_retiro', rows: [form_banco_retiro]},
|
||||
{id: 'banco_deposito', rows: [form_banco_deposito]}
|
||||
{id: 'banco_deposito', rows: [form_banco_deposito]},
|
||||
{id: 'bank_pay', rows: [form_bank_pay]},
|
||||
{id: 'bank_invoice_pay', rows: [form_bank_invoice_pay]}
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -277,3 +580,109 @@ var app_bancos = {
|
|||
}
|
||||
|
||||
|
||||
var win_body_mov_description = {rows: [
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
{view: 'textarea', id: 'mov_description', name: 'mov_description',
|
||||
height: 300},
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_save_mov_description', autowidth: true,
|
||||
label: 'Guardar', type: 'iconButton', icon: 'save', hotkey: 'Ctrl+enter'},
|
||||
{maxWidth: 50},
|
||||
{view: 'button', id: 'cmd_close_mov_description', autowidth: true,
|
||||
label: 'Cerrar', type: 'iconButton', icon: 'times-circle', hotkey: 'esc'},
|
||||
{}]},
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
],}
|
||||
|
||||
|
||||
var win_mov_description = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_mov_description',
|
||||
height: 400,
|
||||
width: 600,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Descripción del movimiento',
|
||||
body: win_body_mov_description,
|
||||
})
|
||||
$$('cmd_save_mov_description').attachEvent('onItemClick', cmd_save_mov_description_click)
|
||||
$$('cmd_close_mov_description').attachEvent('onItemClick', cmd_close_mov_description_click)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var opt_reasons_cancel_pay = [
|
||||
{id: '', value: ''},
|
||||
{id: '01', value: '[01] Comprobante emitido con errores con relación'},
|
||||
{id: '02', value: '[02] Comprobante emitido con errores sin relación'},
|
||||
{id: '03', value: '[03] No se llevó acabo la operación'},
|
||||
{id: '04', value: '[04] Operación nominativa relacionada en una factura global'},
|
||||
]
|
||||
|
||||
|
||||
var body_invoice_cancel_pay = {rows: [{minHeight: 15},
|
||||
{view: 'richselect', id: 'lst_reasons_cancel', labelPosition: 'top', label: 'Razón de cancelación', options: opt_reasons_cancel_pay, value: '', width: 400},
|
||||
{view: 'text', id: 'txt_cancel_uuid', labelPosition: 'top', label: 'UUID que sustituye', width: 400},
|
||||
{view: 'label', label: 'Esta acción no se puede deshacer', autowidth: true, align: 'center'},
|
||||
{view: 'label', label: '¿Estás seguro de continuar?', autowidth: true, align: 'center'},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_invoice_cancel_pay', width: 100, label: 'Cancelar', type: 'danger', icon: 'ban'},
|
||||
{maxWidth: 25},
|
||||
{view: 'button', id: 'cmd_win_cancel_pay_close', width: 100, label: 'Cerrar'},
|
||||
{}
|
||||
]},
|
||||
{minHeight: 20},
|
||||
]}
|
||||
|
||||
|
||||
var win_invoice_cancel_pay = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_invoice_cancel_pay',
|
||||
modal: true,
|
||||
width: 400,
|
||||
position: 'center',
|
||||
head: 'Cancelar CFDI',
|
||||
body: body_invoice_cancel_pay,
|
||||
})
|
||||
$$('cmd_invoice_cancel_pay').attachEvent('onItemClick', cmd_invoice_cancel_pay_click)
|
||||
$$('cmd_win_cancel_pay_close').attachEvent('onItemClick', cmd_win_cancel_pay_close_click)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var body_invoice_cancel_pay2 = {rows: [{minHeight: 15},
|
||||
{view: 'richselect', id: 'lst_reasons_cancel2', labelPosition: 'top', label: 'Razón de cancelación', options: opt_reasons_cancel_pay, value: '', width: 400},
|
||||
{view: 'text', id: 'txt_cancel_uuid2', labelPosition: 'top', label: 'UUID que sustituye', width: 400},
|
||||
{view: 'label', label: 'Esta acción no se puede deshacer', autowidth: true, align: 'center'},
|
||||
{view: 'label', label: '¿Estás seguro de continuar?', autowidth: true, align: 'center'},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_invoice_cancel_pay2', width: 100, label: 'Cancelar', type: 'danger', icon: 'ban'},
|
||||
{maxWidth: 25},
|
||||
{view: 'button', id: 'cmd_win_cancel_pay_close2', width: 100, label: 'Cerrar'},
|
||||
{}
|
||||
]},
|
||||
{minHeight: 20},
|
||||
]}
|
||||
|
||||
|
||||
var win_invoice_cancel_pay2 = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_invoice_cancel_pay2',
|
||||
modal: true,
|
||||
width: 400,
|
||||
position: 'center',
|
||||
head: 'Cancelar CFDI de Pago',
|
||||
body: body_invoice_cancel_pay2,
|
||||
})
|
||||
$$('cmd_invoice_cancel_pay2').attachEvent('onItemClick', cmd_invoice_cancel_pay2_click)
|
||||
$$('cmd_win_cancel_pay_close2').attachEvent('onItemClick', cmd_win_cancel_pay_close2_click)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,39 @@ var form_controls_empresa = [
|
|||
]
|
||||
|
||||
|
||||
var msg_header = 'Bienvenido a Empresa Libre'
|
||||
var msg_header = '<font color="#610B0B">Bienvenido a Empresa Libre</font>'
|
||||
var header = [
|
||||
{view: 'label', label: '<b><font color="#610B0B">Alta de Emisor</font></b>'},
|
||||
{},
|
||||
{view: 'button', type: 'icon', width: 40, css: 'app_button',
|
||||
icon: 'home', click: 'window.location = "/"'},
|
||||
]
|
||||
var footer = [
|
||||
{},
|
||||
{view: 'button', value: 'Respaldar BD', click: 'cmd_respaldar_bd'},
|
||||
{},
|
||||
]
|
||||
|
||||
|
||||
var grid_empresas_cols = [
|
||||
{id: 'delete', header: '', width: 30, css: 'delete'},
|
||||
{id: 'rfc', header: 'RFC Emisor', fillspace: true,
|
||||
footer: {content: 'countRows', css: 'right'}},
|
||||
]
|
||||
|
||||
|
||||
var grid_empresas = {
|
||||
view: 'datatable',
|
||||
id: 'grid_empresas',
|
||||
select: 'row',
|
||||
url: '/values/empresas',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
headermenu: true,
|
||||
footer: true,
|
||||
columns: grid_empresas_cols,
|
||||
}
|
||||
|
||||
|
||||
var ui_empresas = {
|
||||
rows: [
|
||||
|
@ -18,7 +50,7 @@ var ui_empresas = {
|
|||
{maxHeight: 50},
|
||||
{cols: [{}, {type: 'space', padding: 5,
|
||||
rows: [
|
||||
{view: 'template', template: 'Alta de nuevo emisor', type: 'header'},
|
||||
{view: 'toolbar', elements: header},
|
||||
{
|
||||
container: 'form_empresas',
|
||||
view: 'form',
|
||||
|
@ -29,6 +61,8 @@ var ui_empresas = {
|
|||
alta_rfc:function(value){ return value.trim() != '';},
|
||||
}
|
||||
},
|
||||
grid_empresas,
|
||||
{view: 'toolbar', elements: footer},
|
||||
]}, {}, ]
|
||||
},
|
||||
]
|
||||
|
|
|
@ -16,16 +16,16 @@ var form_controls = [
|
|||
]
|
||||
|
||||
|
||||
var msg_header = 'Bienvenido a Empresa Libre'
|
||||
|
||||
var ui_login = {
|
||||
rows: [
|
||||
{maxHeight: 50},
|
||||
{view: 'template', template: msg_header, maxHeight: 50, css: 'login_header'},
|
||||
{view: 'template', id: 'title_login', template: '', maxHeight: 50,
|
||||
css: 'login_header'},
|
||||
{maxHeight: 50},
|
||||
{cols: [{}, {type: 'space', padding: 5,
|
||||
rows: [
|
||||
{view: 'template', template: 'Acceso al sistema', type: 'header'},
|
||||
{view: 'template', type: 'header',
|
||||
template: '<font color="#610B0B">Acceso al sistema</font>'},
|
||||
{
|
||||
container: 'form_login',
|
||||
view: 'form',
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
var menu_data = [
|
||||
{id: 'app_home', icon: 'dashboard', value: 'Inicio'},
|
||||
{id: 'app_partners', icon: 'users', value: 'Clientes y Proveedores'},
|
||||
{id: 'app_partners', icon: 'address-book-o', value: 'Clientes y Proveedores'},
|
||||
{id: 'app_products', icon: 'server', value: 'Productos y Servicios'},
|
||||
{id: 'app_bancos', icon: 'university', value: 'Bancos'},
|
||||
{id: 'app_invoices', icon: 'cart-plus', value: 'Facturas'},
|
||||
{id: 'app_invoices', icon: 'file-code-o', value: 'Facturas'},
|
||||
]
|
||||
|
||||
|
||||
var sidebar = {
|
||||
view: 'sidebar',
|
||||
id: 'main_sidebar',
|
||||
data: menu_data,
|
||||
ready: function(){
|
||||
this.select('app_home');
|
||||
|
@ -36,6 +37,9 @@ var multi_main = {
|
|||
app_partners,
|
||||
app_products,
|
||||
app_bancos,
|
||||
app_school,
|
||||
app_nomina,
|
||||
app_tickets,
|
||||
app_invoices,
|
||||
],
|
||||
}
|
||||
|
@ -55,20 +59,28 @@ var menu_user = {
|
|||
}
|
||||
|
||||
|
||||
var link_blog = "<a class='link_default' target='_blank' href='https://empresalibre.net/blog'>Blog</a>";
|
||||
var link_forum = "<a class='link_default' target='_blank' href='https://git.cuates.net/elmau/empresa-libre/issues'>Foro</a>";
|
||||
var link_doc = "<a class='link_default' target='_blank' href='https://empresalibre.net/docs'>Doc</a>";
|
||||
|
||||
|
||||
var ui_main = {
|
||||
rows: [
|
||||
{view: 'toolbar', padding: 3, elements: [
|
||||
{view: 'button', type: 'icon', icon: 'bars',
|
||||
width: 37, align: 'left', css: 'app_button', click: function(){
|
||||
$$('$sidebar1').toggle()
|
||||
$$('main_sidebar').toggle()
|
||||
}
|
||||
},
|
||||
{view: 'label', id: 'lbl_title_main', label: '<b>Empresa Libre</b>'},
|
||||
{},
|
||||
{view: 'label', id: 'lbl_blog', label: link_blog, align: 'right', width: 30},
|
||||
{view: 'label', id: 'lbl_forum', label: link_forum, align: 'right', width: 30},
|
||||
{view: 'label', id: 'lbl_doc', label: link_doc, align: 'right', width: 25},
|
||||
menu_user,
|
||||
{view: 'button', type: 'icon', width: 45, css: 'app_button',
|
||||
icon: 'bell-o', badge: 0},
|
||||
{view: 'button', type: 'icon', width: 45, css: 'app_button',
|
||||
{view: 'button', id: 'cmd_update_timbres', type: 'icon', width: 45,
|
||||
css: 'app_button', icon: 'bell-o', badge: 0},
|
||||
{view: 'button', type: 'icon', width: 30, css: 'app_button',
|
||||
icon: 'cogs', id: 'cmd_ir_al_admin', hidden: true,
|
||||
click: 'cmd_ir_al_admin_click'}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
|
||||
var toolbar_nomina = [
|
||||
{view: 'button', id: 'cmd_empleados', label: 'Empleados', type: 'iconButton',
|
||||
autowidth: true, icon: 'users'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_nomina_report', label: 'Reporte', type: 'iconButton',
|
||||
autowidth: true, icon: 'table'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_nomina_delete', label: 'Eliminar',
|
||||
type: 'iconButton', autowidth: true, icon: 'minus'},
|
||||
]
|
||||
|
||||
|
||||
var toolbar_nomina_util = [
|
||||
{view: 'button', id: 'cmd_nomina_import', label: 'Importar',
|
||||
type: 'iconButton', autowidth: true, icon: 'upload'},
|
||||
{view: 'button', id: 'cmd_nomina_timbrar', label: 'Timbrar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ticket'},
|
||||
{view: 'button', id: 'cmd_nomina_sat', label: 'SAT',
|
||||
type: 'iconButton', autowidth: true, icon: 'check-circle'},
|
||||
{view: 'button', id: 'cmd_nomina_log', label: 'Log',
|
||||
type: 'iconButton', autowidth: true, icon: 'download'},
|
||||
{view: 'button', id: 'cmd_nomina_download', label: 'Descargar',
|
||||
type: 'iconButton', autowidth: true, icon: 'download'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_nomina_cancel', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
]
|
||||
|
||||
|
||||
var toolbar_nomina_filter = [
|
||||
{view: 'richselect', id: 'filter_year_nomina', label: 'Año',
|
||||
labelAlign: 'right', labelWidth: 50, width: 150, options: []},
|
||||
{view: 'richselect', id: 'filter_month_nomina', label: 'Mes',
|
||||
labelAlign: 'right', labelWidth: 50, width: 200, options: months},
|
||||
{view: 'daterangepicker', id: 'filter_dates_nomina', label: 'Fechas',
|
||||
labelAlign: 'right', width: 300},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_nomina_without_stamp', label: 'Sin Timbrar',
|
||||
type: 'iconButton', autowidth: true, icon: 'filter'},
|
||||
]
|
||||
|
||||
|
||||
var grid_cols_nomina = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie"], adjust: "header"},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
|
||||
sort: 'int', css: 'right', footer: {text: 'Recibos', colspan: 3}},
|
||||
{id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data",
|
||||
sort:"string", hidden:true},
|
||||
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort: "string"},
|
||||
{id: "estatus", header: ["Estatus", {content: "selectFilter"}],
|
||||
adjust: "data", sort:"string"},
|
||||
{id: 'fecha_pago', header: ['Fecha de Pago', {content: 'selectFilter'}],
|
||||
adjust: 'data', sort: 'string'},
|
||||
{id: 'total', header: ['Total', {content: 'numberFilter'}], width: 150,
|
||||
sort: 'int', format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summTimbradaN', css: 'right'}},
|
||||
{id: "empleado", header: ["Empleado", {content: "selectFilter"}],
|
||||
fillspace:true, sort:"string", footer: {text: '$ 0.00'}},
|
||||
{id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
{id: 'email', header: '@', adjust: 'data', template: get_icon('email')}
|
||||
]
|
||||
|
||||
|
||||
var grid_nomina = {
|
||||
view: 'datatable',
|
||||
id: 'grid_nomina',
|
||||
select: 'row',
|
||||
multiselect: true,
|
||||
scrollY: true,
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_cols_nomina,
|
||||
scheme:{
|
||||
$change:function(item){
|
||||
if (item.estatus == 'Cancelado'){
|
||||
item.$css = 'cancel'
|
||||
}
|
||||
}
|
||||
},
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var rows_nomina_home = [
|
||||
{view: 'toolbar', elements: toolbar_nomina},
|
||||
{view: 'toolbar', elements: toolbar_nomina_util},
|
||||
{view: 'toolbar', elements: toolbar_nomina_filter},
|
||||
grid_nomina,
|
||||
]
|
||||
|
||||
|
||||
var toolbar_nomina_empleados = [
|
||||
{view: 'button', id: 'cmd_new_empleado', label: 'Nuevo', type: 'iconButton',
|
||||
autowidth: true, icon: 'user-plus'},
|
||||
{view: 'button', id: 'cmd_edit_empleado', label: 'Editar', type: 'iconButton',
|
||||
autowidth: true, icon: 'user'},
|
||||
{view: 'button', id: 'cmd_delete_empleado', label: 'Eliminar', type: 'iconButton',
|
||||
autowidth: true, icon: 'user-times'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_import_empleados', label: 'Importar',
|
||||
type: 'iconButton', autowidth: true, icon: 'upload'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_close_empleados', label: 'Cerrar', type: 'iconButton',
|
||||
autowidth: true, icon: 'times-circle-o'},
|
||||
]
|
||||
|
||||
|
||||
var grid_cols_empleados = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "num_empleado", header: ["No Empleado"], adjust: "data"},
|
||||
{id: "rfc", header: ["RFC", {content: 'textFilter'}], adjust: "data", sort: "string"},
|
||||
{id: "curp", header: ["CURP"], adjust: "data", hidden:true, sort: "string"},
|
||||
{id: "nombre_completo", header: ["Empleado", {content: 'textFilter'}],
|
||||
adjust: "data", fillspace: true, sort: "string"},
|
||||
{id: 'imss', header: ['IMSS'], adjust: 'data'},
|
||||
{id: 'salario_base', header: ['Salario Base'], adjust: 'header',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'salario_diario', header: ['Salario Diario'], adjust: 'header',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: "fecha_ingreso", header: ["Fecha de Ingreso"], adjust: "header",
|
||||
sort: "string"},
|
||||
]
|
||||
|
||||
|
||||
var grid_empleados = {
|
||||
view: 'datatable',
|
||||
id: 'grid_employees',
|
||||
select: 'row',
|
||||
scrollY: true,
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_cols_empleados,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var rows_nomina_empleados = [
|
||||
{view: 'toolbar', elements: toolbar_nomina_empleados},
|
||||
grid_empleados,
|
||||
]
|
||||
|
||||
|
||||
var multi_nomina = {
|
||||
id: 'multi_nomina',
|
||||
view: 'multiview',
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: 'nomina_home', rows: rows_nomina_home},
|
||||
{id: 'nomina_empleados', rows: rows_nomina_empleados},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var app_nomina = {
|
||||
id: 'app_nomina',
|
||||
rows:[
|
||||
{view: 'template', type: 'header', template: 'Timbrado de Nómina'},
|
||||
multi_nomina
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var body_import_employees = {rows: [
|
||||
{view: 'form', id: 'form_upload_employees', rows: [
|
||||
{cols: [{},
|
||||
{view: 'uploader', id: 'up_employees', autosend: false,
|
||||
link: 'lst_upload_employees', value: 'Seleccionar Plantilla',
|
||||
upload: '/files/employees'}, {}]},
|
||||
{cols: [
|
||||
{view: 'list', id: 'lst_upload_employees', name: 'lst_employees',
|
||||
type: 'uploader', autoheight: true, borderless: true}]},
|
||||
{cols: [{}, {view: 'button', id: 'cmd_import_employees',
|
||||
label: 'Importar Empleados'}, {}]},
|
||||
]},
|
||||
],}
|
||||
|
||||
|
||||
var win_import_employees = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_import_employees',
|
||||
width: 400,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Importar Empleados',
|
||||
body: body_import_employees,
|
||||
})
|
||||
$$('cmd_import_employees').attachEvent('onItemClick', cmd_import_employees_click)
|
||||
$$('up_employees').attachEvent('onUploadComplete', up_employees_upload_complete)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var body_import_nomina = {rows: [
|
||||
{view: 'form', id: 'form_upload_nomina', rows: [
|
||||
{cols: [{},
|
||||
{view: 'uploader', id: 'up_nomina', autosend: false,
|
||||
link: 'lst_upload_nomina', value: 'Seleccionar Plantilla',
|
||||
upload: '/files/nomina'}, {}]},
|
||||
{cols: [
|
||||
{view: 'list', id: 'lst_upload_nomina', name: 'lst_nomina',
|
||||
type: 'uploader', autoheight: true, borderless: true}]},
|
||||
{cols: [{}, {view: 'button', id: 'cmd_import_template_nomina',
|
||||
label: 'Importar Nómina'}, {}]},
|
||||
]},
|
||||
],}
|
||||
|
||||
|
||||
var win_import_nomina = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_import_nomina',
|
||||
width: 400,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Importar Nómina',
|
||||
body: body_import_nomina,
|
||||
})
|
||||
$$('cmd_import_template_nomina').attachEvent('onItemClick', cmd_import_template_nomina_click)
|
||||
$$('up_nomina').attachEvent('onUploadComplete', up_nomina_upload_complete)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var opt_reasons_cancel_nomina = [
|
||||
{id: '', value: ''},
|
||||
{id: '01', value: '[01] Comprobante emitido con errores con relación'},
|
||||
{id: '02', value: '[02] Comprobante emitido con errores sin relación'},
|
||||
{id: '03', value: '[03] No se llevó acabo la operación'},
|
||||
{id: '04', value: '[04] Operación nominativa relacionada en una factura global'},
|
||||
]
|
||||
|
||||
|
||||
var body_invoice_cancel_nomina = {rows: [{minHeight: 15},
|
||||
{view: 'richselect', id: 'lst_reasons_cancel', labelPosition: 'top', label: 'Razón de cancelación', options: opt_reasons_cancel_pay, value: '', width: 400},
|
||||
{view: 'text', id: 'txt_cancel_uuid', labelPosition: 'top', label: 'UUID que sustituye', width: 400},
|
||||
{view: 'label', label: 'Esta acción no se puede deshacer', autowidth: true, align: 'center'},
|
||||
{view: 'label', label: '¿Estás segura de continuar?', autowidth: true, align: 'center'},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_invoice_cancel_nomina', width: 100, label: 'Cancelar', type: 'danger', icon: 'ban'},
|
||||
{maxWidth: 25},
|
||||
{view: 'button', id: 'cmd_win_cancel_nomina_close', width: 100, label: 'Cerrar'},
|
||||
{}
|
||||
]},
|
||||
{minHeight: 20},
|
||||
]}
|
||||
|
||||
|
||||
var win_invoice_cancel_nomina = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_invoice_cancel_nomina',
|
||||
modal: true,
|
||||
width: 400,
|
||||
position: 'center',
|
||||
head: 'Cancelar CFDI',
|
||||
body: body_invoice_cancel_nomina,
|
||||
})
|
||||
$$('cmd_invoice_cancel_nomina').attachEvent('onItemClick', cmd_invoice_cancel_nomina_click)
|
||||
$$('cmd_win_cancel_nomina_close').attachEvent('onItemClick', cmd_win_cancel_nomina_close_click)
|
||||
}
|
||||
}
|
|
@ -1,3 +1,18 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 of the License, or
|
||||
//~ (at your option) any later version.
|
||||
//~
|
||||
//~ This program is distributed in the hope that it will be useful,
|
||||
//~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//~ GNU General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var toolbar_partners = [
|
||||
|
@ -7,12 +22,15 @@ var toolbar_partners = [
|
|||
autowidth: true, icon: 'user'},
|
||||
{view: 'button', id: 'cmd_delete_partner', label: 'Eliminar', type: 'iconButton',
|
||||
autowidth: true, icon: 'user-times'},
|
||||
{},
|
||||
//~ {view: 'button', id: 'cmd_partner_zero', label: 'Saldo 0', type: 'iconButton',
|
||||
//~ autowidth: true, icon: 'power-off', disabled: true},
|
||||
]
|
||||
|
||||
|
||||
var grid_partners_cols = [
|
||||
{id: 'index', header:'#', css: 'right',
|
||||
footer: {content: 'rowCount', colspan: 2, css: 'right'}},
|
||||
footer: {content: 'countRows', colspan: 2, css: 'right'}},
|
||||
{id: 'id', header: 'Clave', sort: 'int', css: 'right'},
|
||||
{id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust: 'data',
|
||||
sort: 'string', footer: {text: 'Clientes y Proveedores', colspan: 2}},
|
||||
|
@ -66,7 +84,10 @@ var controls_fiscales = [
|
|||
invalidMessage: 'El Tipo de Persona es requerido'},
|
||||
{template: 'Dirección Fiscal', type: 'section'},
|
||||
{cols: [{view: 'text', id: 'rfc', name: 'rfc', label: 'RFC: ', width: 300,
|
||||
required: true, invalidMessage: 'RFC inválido', attributes: {maxlength: 13}},{}]},
|
||||
required: true, invalidMessage: 'RFC inválido', attributes: {maxlength: 13}},
|
||||
{view: 'text', id: 'id_fiscal', name: 'id_fiscal', label: 'ID Fiscal: ',
|
||||
width: 400, required: false, attributes: {maxlength: 40}, hidden: true},
|
||||
{}]},
|
||||
{view: 'text', id: 'nombre', name: 'nombre', label: 'Razón Social: ', required: true,
|
||||
invalidMessage: 'La Razón Social es requerida'},
|
||||
{view: 'text', id: 'calle', name: 'calle', label: 'Calle: '},
|
||||
|
@ -75,12 +96,12 @@ var controls_fiscales = [
|
|||
{cols: [{view: 'text', id: 'no_interior', name: 'no_interior', width: 300,
|
||||
label: 'No Interior: '},{}]},
|
||||
{cols: [{view: 'search', id: 'codigo_postal', name: 'codigo_postal',
|
||||
width: 300, label: 'C.P.: ', attributes: {maxlength: 5}},{}]},
|
||||
width: 300, label: 'C.P.: ', attributes: {maxlength: 5}, required: true},{}]},
|
||||
{view: 'text', id: 'colonia', name: 'colonia', label: 'Colonia: '},
|
||||
{view: 'text', id: 'municipio', name: 'municipio', label: 'Municipio: '},
|
||||
{view: 'text', id: 'estado', name: 'estado', label: 'Estado: '},
|
||||
{view: 'text', id: 'pais', name: 'pais', label: 'País: ',
|
||||
value: 'México', readonly: true},
|
||||
{view: 'text', id: 'pais', name: 'pais', label: 'País: ', value: 'México',
|
||||
readonly: true, placeholder: 'Usa solo tres letras de acuerdo al catalogo del SAT'},
|
||||
{template: 'Condiciones Comerciales', type: 'section'},
|
||||
{cols: [
|
||||
{view: 'richselect', id: 'forma_pago', name: 'forma_pago',
|
||||
|
@ -101,25 +122,41 @@ var controls_fiscales = [
|
|||
{view: 'richselect', id: 'lst_uso_cfdi_socio', name: 'uso_cfdi_socio',
|
||||
label: 'Uso del CFDI', options: []},
|
||||
{},
|
||||
]},
|
||||
{template: 'Regimenes Fiscales', type: 'section'},
|
||||
{cols: [
|
||||
{view: 'list', id: 'lst_receptor_regimenes_fiscales', data: [],
|
||||
select: 'multiselect', width: 600, height: 125, required: true},
|
||||
{},
|
||||
]}
|
||||
]
|
||||
|
||||
|
||||
var controls_others = [
|
||||
{view: 'checkbox', id: 'es_activo', name: 'es_activo', label: 'Activo: ',
|
||||
value: true, bottomLabel: ' Se recomienda solo desactivar y no eliminar'},
|
||||
value: true, bottomLabel: ' Se recomienda solo desactivar y no eliminar'},
|
||||
{view: 'text', id: 'commercial_name', name: 'nombre_comercial',
|
||||
label: 'Nombre Comercial: '},
|
||||
{view: 'text', id: 'telefonos', name: 'telefonos', label: 'Teléfonos: '},
|
||||
{view: 'text', id: 'web', name: 'web', label: 'Página Web: '},
|
||||
{cols: [
|
||||
{view: 'text', id: 'correo_facturas', name: 'correo_facturas',
|
||||
label: 'Correos para Facturas: ', tooltip: 'Separados por comas',
|
||||
bottomLabel: 'Uno o más correos electrónicos separados por comas'},
|
||||
{view: 'text', id: 'partner_email_fp', name: 'partner_email_fp',
|
||||
label: 'Para Facturas de pago: ', tooltip: 'Separados por comas',
|
||||
bottomLabel: 'Uno o más correos electrónicos separados por comas'},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'checkbox', id: 'es_cliente', name: 'es_cliente',
|
||||
label: 'Es Cliente: ', value: true, width: 180},
|
||||
{view: 'text', id: 'cuenta_cliente', name: 'cuenta_cliente',
|
||||
label: 'Cuenta Cliente: ', disabled: true}, {}]
|
||||
label: 'Cuenta Cliente: ', disabled: true},
|
||||
{view: "currency", type: "text", id: 'partner_balance', width: 300,
|
||||
name: 'partner_balance', label: 'Saldo', labelWidth: 100,
|
||||
labelAlign: "right", required: true, inputAlign: "right",
|
||||
invalidMessage: "Captura un valor númerico", readonly: true},
|
||||
]
|
||||
},
|
||||
{cols: [
|
||||
{view: 'checkbox', id: 'es_proveedor', name: 'es_proveedor',
|
||||
|
@ -128,12 +165,56 @@ var controls_others = [
|
|||
label: 'Cuenta Proveedor: ', disabled: true}, {}]
|
||||
},
|
||||
{view: 'checkbox', name: 'es_ong', label: 'Es ONG: ', value: false},
|
||||
{view: 'text', name: 'tags', label: 'Etiquetas',
|
||||
{view: 'text', name: 'tags', label: 'Etiquetas', disabled: true,
|
||||
tooltip: 'Utiles para filtrados rápidos. Separa por comas.'},
|
||||
{view: 'textarea' , height: 200, name: 'notas', label: 'Notas'},
|
||||
]
|
||||
|
||||
|
||||
var grid_partner_account_bank_cols = [
|
||||
{id: 'id', header: 'ID', hidden: true},
|
||||
{id: 'delete', header: '', width: 30, css: 'delete'},
|
||||
{id: 'banco', header: 'Banco', fillspace: 1},
|
||||
{id: 'cuenta', header: 'Cuenta', fillspace: 1},
|
||||
{id: 'clabe', header: 'CLABE', fillspace: 1},
|
||||
//~ {id: 'moneda', header: 'Moneda', fillspace: 1},
|
||||
]
|
||||
|
||||
|
||||
var grid_partner_account_bank = {
|
||||
view: 'datatable',
|
||||
id: 'grid_partner_account_bank',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
columns: grid_partner_account_bank_cols,
|
||||
}
|
||||
|
||||
|
||||
var controls_partner_bank = [
|
||||
{template: 'Agregar cuenta de banco', type: 'section'},
|
||||
{view: 'form', id: 'form_partner_account_bank', rows: [
|
||||
{cols: [
|
||||
{view: 'richselect', id: 'lst_partner_bank', name: 'partner_bank',
|
||||
label: 'Banco: ', required: true, options: []},
|
||||
{view: 'text', id: 'partner_account', name: 'partner_account',
|
||||
label: 'Cuenta: ', required: true},
|
||||
{view: 'text', id: 'partner_clabe', name: 'partner_clabe',
|
||||
label: 'CLABE: ', required: true},
|
||||
]},
|
||||
{minHeight: 10},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_partner_add_account_bank', maxWidth: 200,
|
||||
label: 'Agregar cuenta'},
|
||||
{}]},
|
||||
],
|
||||
},
|
||||
{minHeight: 20, maxHeight: 20},
|
||||
{template: 'Cuentas de banco existentes', type: 'section'},
|
||||
grid_partner_account_bank,
|
||||
{minHeight: 50},
|
||||
]
|
||||
|
||||
|
||||
var toolbar_contacts = [
|
||||
{view: 'button', id: 'cmd_new_contact', label: 'Nuevo', type: 'iconButton',
|
||||
|
@ -143,7 +224,7 @@ var toolbar_contacts = [
|
|||
|
||||
var grid_contacts_cols = [
|
||||
{id: 'index', header: '#', adjust:'data', css:'right',
|
||||
footer: {content: 'rowCount'}},
|
||||
footer: {content: 'countRows'}},
|
||||
{id: 'id', header: '', hidden: true},
|
||||
{id: 'title', header: 'Título', adjust:'data', sort: 'string',
|
||||
footer: 'Contactos'},
|
||||
|
@ -271,11 +352,12 @@ var controls_partner = [
|
|||
{
|
||||
view: 'tabview',
|
||||
id: 'tab_partner',
|
||||
tabbar: {options: ['Datos Fiscales', 'Otros Datos', 'Contactos']}, animate: true,
|
||||
tabbar: {ptions: ['Datos Fiscales', 'Otros Datos', 'Cuentas de Banco']},
|
||||
animate: true,
|
||||
cells: [
|
||||
{id: 'Datos Fiscales', rows: controls_fiscales},
|
||||
{id: 'Otros Datos', rows: controls_others},
|
||||
{id: 'Contactos', rows: [multi_contacts]},
|
||||
{id: 'Cuentas de Banco', rows: controls_partner_bank}
|
||||
]
|
||||
},
|
||||
{rows: [
|
||||
|
|
|
@ -7,31 +7,52 @@ var toolbar_products = [
|
|||
autowidth: true, icon: "pencil"},
|
||||
{view: "button", id: "cmd_delete_product", label: "Eliminar",
|
||||
type: "iconButton", autowidth: true, icon: "minus"},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_import_products', label: 'Importar',
|
||||
type: 'iconButton', autowidth: true, icon: 'upload'},
|
||||
{view: "button", id: "cmd_add_inventory", label: "Altas", hidden: true,
|
||||
type: "iconButton", autowidth: true, icon: "plus"},
|
||||
{view: "button", id: "cmd_products_add", label: "Altas CFDI", hidden: true,
|
||||
type: "iconButton", autowidth: true, icon: "plus"},
|
||||
{view: 'button', id: 'cmd_show_exists', label: 'Existencias', hidden: true,
|
||||
type: 'iconButton', autowidth: true, icon: 'table'},
|
||||
]
|
||||
|
||||
|
||||
var grid_products_cols = [
|
||||
{ id: "id", header: "ID", width: 75},
|
||||
{ id: "id", header: "ID", width: 75, hidden: true},
|
||||
{ id: 'es_activo', header: 'Activo', hidden: true},
|
||||
{ id: "clave_sat", header: ["Clave SAT"], width: 100,},
|
||||
{ id: "clave", header: ["Clave", {content: "textFilter"}], width: 100,
|
||||
sort: 'string', footer: {content: 'rowCount', css: 'right'}},
|
||||
sort: 'string', footer: {content: 'countRows', css: 'right'}},
|
||||
{ id: "descripcion", header: ["Descripción", {content: "textFilter"}],
|
||||
fillspace:true, sort: 'string', footer: 'Productos y Servicios'},
|
||||
{ id: "unidad", header: ["Unidad", {content: "selectFilter"}], width: 150,
|
||||
sort:"string" },
|
||||
{ id: "valor_unitario", header: ["Precio", {content: "numberFilter"}], width: 150,
|
||||
sort:"int", format: webix.i18n.priceFormat, css: "right" },
|
||||
{ id: "valor_unitario", header: ["Precio", {content: "numberFilter"}],
|
||||
width: 150, sort: 'int', format: format_currency, css: "right" },
|
||||
{ id: 'existencia', header: ['Existencia', {content: 'numberFilter'}],
|
||||
width: 100, sort: 'int', format: webix.i18n.numberFormat,
|
||||
hidden: true, css: 'right' },
|
||||
]
|
||||
|
||||
|
||||
var grid_products = {
|
||||
view: "datatable",
|
||||
id: "grid_products",
|
||||
select: "row",
|
||||
view: 'datatable',
|
||||
id: 'grid_products',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_products_cols,
|
||||
scheme:{
|
||||
$change:function(item){
|
||||
if(!item.es_activo){
|
||||
item.$css = 'cancel'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,6 +111,15 @@ var suggest_sat_producto = {
|
|||
}
|
||||
|
||||
|
||||
var opt_tax_object = [
|
||||
{id: '01', value: '[01] No objeto de impuesto.'},
|
||||
{id: '02', value: '[02] Sí objeto de impuesto.'},
|
||||
{id: '03', value: '[03] Sí objeto del impuesto y no obligado al desglose.'},
|
||||
{id: '04', value: '[04] Sí objeto del impuesto y no causa impuesto.'},
|
||||
{id: '05', value: '[05] Sí objeto del impuesto, IVA crédito PODEBI.'},
|
||||
]
|
||||
|
||||
|
||||
var controls_generals = [
|
||||
{view: 'checkbox', id: 'es_activo_producto', name: 'es_activo_producto',
|
||||
label: 'Activo: ', value: true,
|
||||
|
@ -113,28 +143,37 @@ var controls_generals = [
|
|||
{id: 'txt_col1'}]},
|
||||
{view: "textarea", id: "descripcion", name: "descripcion", height: 200,
|
||||
label: "Descripción", required: true, labelPosition: "top",
|
||||
invalidMessage: "La Descripción es requerida" },
|
||||
invalidMessage: "La Descripción es requerida",
|
||||
placeholder: 'El SAT solo permite 1000 caracteres en este campo'},
|
||||
{minHeight: 5},
|
||||
{cols: [
|
||||
{view: "richselect", id: "unidad", name: "unidad", label: "Unidad",
|
||||
width: 300, labelWidth: 130, labelAlign: "right", required: true,
|
||||
invalidMessage: "La Unidad es requerida", options: []},
|
||||
{view: 'text', id: 'tags_producto', name: 'tags_producto',
|
||||
labelAlign: 'right', label: 'Etiquetas',
|
||||
placeholder: 'Separadas por comas'}
|
||||
{view: 'richselect', id: 'objeto_impuesto', name: 'objeto_impuesto', label: 'Objeto de Impuestos',
|
||||
width: 500, labelWidth: 150, labelAlign: "right", required: true,
|
||||
invalidMessage: 'Este campo es requerido', options: opt_tax_object},
|
||||
{},
|
||||
]},
|
||||
{cols: [{view: "currency", type: "text", id: "valor_unitario",
|
||||
name: "valor_unitario", label: "Valor Unitario", width: 300,
|
||||
labelWidth: 130, labelAlign: "right", required: true,
|
||||
invalidMessage: "Captura un valor númerico", inputAlign: "right" },{}]},
|
||||
{cols: [
|
||||
{view: 'checkbox', id: 'inventario', name: 'inventario', hidden: true,
|
||||
{view: "currency", type: "text", id: "valor_unitario",
|
||||
name: "valor_unitario", label: "Valor Unitario", width: 300,
|
||||
labelWidth: 130, labelAlign: "right", required: true,
|
||||
invalidMessage: "Captura un valor númerico", inputAlign: "right"},
|
||||
{view: 'currency', type: 'text', id: 'precio_con_impuestos',
|
||||
name: 'precio_con_impuestos', label: 'Con Impuestos', width: 300,
|
||||
labelWidth: 115, labelAlign: 'right', required: false,
|
||||
invalidMessage: 'Captura un valor númerico', inputAlign: 'right'},
|
||||
{},]},
|
||||
{cols: [
|
||||
{view: 'checkbox', id: 'chk_inventario', name: 'inventario', hidden: true,
|
||||
label: 'Inventario', labelAlign: 'right', labelWidth: 130},
|
||||
{view: 'counter', id: 'existencia', name: 'existencia', hidden: true,
|
||||
label: 'Existencia', step: 5, value: 0, min: 0, disabled: true},
|
||||
{view: 'counter', id: 'minimo', name: 'minimo', hidden: true,
|
||||
{view: 'counter', id: 'txt_existencia', name: 'existencia',
|
||||
hidden: true, label: 'Existencia', step: 5, value: 0, min: 0,
|
||||
disabled: true, readonly: true},
|
||||
{view: 'counter', id: 'txt_minimo', name: 'minimo', hidden: true,
|
||||
label: 'Mínimo', step: 5, value: 0, min: 0, disabled: true},
|
||||
{id: 'txt_col2'}]},
|
||||
{},]},
|
||||
{cols:[{view:'label', label:'Impuestos', width: 300, align:'center'}, {}]},
|
||||
{cols:[grid_product_taxes, {}]}
|
||||
]
|
||||
|
@ -149,8 +188,8 @@ var controls_products = [
|
|||
],
|
||||
},
|
||||
{rows: [
|
||||
{ template:"", type: "section" },
|
||||
{ margin: 10, cols: [{},
|
||||
{template: "", type: "section"},
|
||||
{margin: 10, cols: [{},
|
||||
{view: "button", id: "cmd_save_product", label: "Guardar" , type: "form", autowidth: true, align:"center"},
|
||||
{view: "button", id: "cmd_cancel_product", label: "Cancelar" , type: "danger", autowidth: true, align:"center"},
|
||||
{}]
|
||||
|
@ -175,6 +214,129 @@ var form_product = {
|
|||
}
|
||||
|
||||
|
||||
var toolbar_products_add = {view: 'toolbar', elements: [{},
|
||||
{view: 'button', id: 'cmd_add_products_from_xml', label: 'Desde XML',
|
||||
type: 'iconButton', autowidth: true, icon: 'upload'},
|
||||
{}]}
|
||||
|
||||
|
||||
var rows_pro_add_partner = [
|
||||
{view: 'fieldset', label: 'Buscar Proveedor', body: {rows: [
|
||||
{cols: [
|
||||
{view: 'search', id: 'search_partner_id', label: 'por Clave',
|
||||
labelPosition: 'top', maxWidth: 200, placeholder: 'Captura la clave'},
|
||||
{view: 'search', id: 'search_partner_name', label: 'por Nombre o RFC',
|
||||
labelPosition: 'top', placeholder: 'Captura al menos tres letras'},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'label', id: 'lbl_partner_title', label: 'Seleccionado: ', autowidth: true},
|
||||
{view: 'label', id: 'lbl_partner', label: 'Ninguno'},
|
||||
]}
|
||||
]}},
|
||||
]
|
||||
|
||||
|
||||
var grid_partner_products_cols = [
|
||||
{id: 'select', header: '', template:'{common.checkbox()}', width:35},
|
||||
{id: 'key', header: {text: 'Clave', css: 'center'}, width: 100,
|
||||
adjust: 'data'},
|
||||
{id: 'key_sat', header:{text: 'Clave SAT', css: 'center'}, width: 100,
|
||||
adjust: 'data'},
|
||||
{id: 'description', header:{text: 'Descripción', css: 'center'},
|
||||
fillspace: true},
|
||||
{id: "pedimento", header: 'Pedimento', editor: 'text', hidden: true},
|
||||
{id: 'unit', header:{text: 'Unidad', css: 'center'}, width: 100,
|
||||
adjust: 'data'},
|
||||
{id: 'unit_value', header:{text: 'Valor Unitario', css: 'center'},
|
||||
width: 100, format: format_currency, css: 'right'},
|
||||
{id: 'cant', header: {text: 'Cantidad', css: 'center'}, width: 50,
|
||||
format: webix.i18n.numberFormat, css: 'right'},
|
||||
{id: 'separate', header: '', width: 25},
|
||||
{id: 'id_product', header: '', hidden: true},
|
||||
{id: 'key1', header:{text: 'Clave', css: 'center'}, width: 100,
|
||||
adjust: true, editor: 'text', hidden: true},
|
||||
{id: 'key_sat1', header:{text: 'Clave SAT', css: 'center'}, width: 100,
|
||||
adjust: true, editor: 'text'},
|
||||
{id: 'description1', header:{text: 'Descripción', css: 'center'},
|
||||
fillspace: true, editor: 'popup'},
|
||||
{id: 'unit_value1', header:{text: 'Valor Unitario', css: 'center'},
|
||||
width: 100, format: format_currency, css: 'right', editor: 'text'},
|
||||
{id: 'cant1', header: {text: 'Cantidad', css: 'center'}, width: 50,
|
||||
format: webix.i18n.numberFormat, css: 'right', editor: 'text'},
|
||||
]
|
||||
|
||||
|
||||
var grid_partner_products = {
|
||||
view: 'datatable',
|
||||
id: 'grid_partner_products',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
editable: true,
|
||||
columns: grid_partner_products_cols,
|
||||
data: [],
|
||||
fixedRowHeight: false,
|
||||
on:{
|
||||
onCheck:function(rowId, colId, state){
|
||||
grid_partner_products_select(rowId, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var controls_products_add = [
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
toolbar_products_add,
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
{cols: [
|
||||
{rows: rows_pro_add_partner},
|
||||
{maxWidth: 10},
|
||||
{},
|
||||
]},
|
||||
{view: 'label', label: 'Detalle', height: 30, align: 'left'},
|
||||
{cols: [
|
||||
grid_partner_products,
|
||||
//~ grid_products_add,
|
||||
]},
|
||||
{rows: [
|
||||
{template:"", type: "section" },
|
||||
{margin: 10, cols: [{},
|
||||
{view: 'button', id: 'cmd_save_products_add', label: 'Guardar',
|
||||
autowidth: true, align: 'center'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_close_products_add', label: 'Cancelar',
|
||||
type: 'danger', autowidth: true, align: 'center'}
|
||||
]
|
||||
},
|
||||
]}
|
||||
]
|
||||
|
||||
|
||||
var controls_form_products_add = [
|
||||
{
|
||||
view: 'tabview',
|
||||
id: 'tv_invoice',
|
||||
animate: true,
|
||||
cells: [
|
||||
{id: 'Altas a inventario', rows: controls_products_add},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
var form_products_add = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_products_add',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_form_products_add,
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
var multi_products = {
|
||||
id: "multi_products",
|
||||
animate: true,
|
||||
|
@ -183,17 +345,197 @@ var multi_products = {
|
|||
{view:"toolbar", elements: toolbar_products},
|
||||
grid_products,
|
||||
]},
|
||||
{id: "product_new", rows:[form_product]}
|
||||
{id: "product_new", rows:[form_product]},
|
||||
{id: "product_add", rows:[form_products_add]}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var app_products = {
|
||||
id: "app_products",
|
||||
id: 'app_products',
|
||||
rows:[
|
||||
{view: "template", id: "th_products", type: "header", template:"Administración de Productos" },
|
||||
{view: 'template', id: 'th_products', type: 'header',
|
||||
template: 'Administración de Productos y Servicios'},
|
||||
multi_products
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var body_import_products = {rows: [
|
||||
{view: 'form', id: 'form_upload_products', rows: [
|
||||
{cols: [{},
|
||||
{view: 'uploader', id: 'up_products', autosend: false,
|
||||
link: 'lst_upload_products', value: 'Seleccionar Archivo',
|
||||
upload: '/files/products'}, {}]},
|
||||
{cols: [
|
||||
{view: 'list', id: 'lst_upload_products', name: 'lst_upload_products',
|
||||
type: 'uploader', autoheight: true, borderless: true}]},
|
||||
{cols: [{}, {view: 'button', id: 'cmd_upload_products',
|
||||
label: 'Importar Productos'}, {}]},
|
||||
]},
|
||||
]}
|
||||
|
||||
|
||||
var win_import_products = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_import_products',
|
||||
width: 400,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Importar Productos',
|
||||
body: body_import_products,
|
||||
})
|
||||
$$('cmd_upload_products').attachEvent('onItemClick', cmd_upload_products_click)
|
||||
$$('up_products').attachEvent('onUploadComplete', up_products_upload_complete)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var body_add_products_from_xml = {rows: [
|
||||
{view: 'form', id: 'form_upload_products_from_xml', rows: [
|
||||
{cols: [{},
|
||||
{view: 'uploader', id: 'up_products_from_xml', autosend: false,
|
||||
link: 'lst_up_products_from_xml', value: 'Seleccionar Archivo',
|
||||
upload: '/files/productsadd'}, {}]},
|
||||
{cols: [
|
||||
{view: 'list', id: 'lst_up_products_from_xml', type: 'uploader',
|
||||
autoheight: true, borderless: true}]},
|
||||
{cols: [{}, {view: 'button', id: 'cmd_upload_products_from_xml',
|
||||
label: 'Cargar Productos'}, {}]},
|
||||
]},
|
||||
]}
|
||||
|
||||
|
||||
var win_add_products_from_xml = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_add_products_from_xml',
|
||||
width: 400,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Agregar Productos desde XML',
|
||||
body: body_add_products_from_xml,
|
||||
})
|
||||
$$('cmd_upload_products_from_xml').attachEvent('onItemClick', cmd_upload_products_from_xml_click)
|
||||
$$('up_products_from_xml').attachEvent('onUploadComplete', up_products_from_xml_upload_complete)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var body_add_inventory = {rows: [{minHeight: 10},
|
||||
{view: 'text', id: 'txt_add_id', readonly: true, hidden: true},
|
||||
{cols: [
|
||||
{view: 'text', id: 'txt_add_key', label: 'Clave',
|
||||
labelPosition: 'top', readonly: true},
|
||||
{view: 'text', id: 'txt_add_unit', label: 'Unidad',
|
||||
labelPosition: 'top', readonly: true},
|
||||
]},
|
||||
{view: 'textarea', id: 'txt_add_description', height: 100,
|
||||
label: 'Descripción', readonly: true, labelPosition: 'top'},
|
||||
{minHeight: 10},
|
||||
{cols: [
|
||||
{view: 'counter', id: 'txt_new_cant', label: 'Cantidad a agregar',
|
||||
labelWidth: 'auto', step: 1, value: 0, min: 0.01},
|
||||
{view: 'richselect', id: 'lst_warehouses', label: 'Almacen: ',
|
||||
labelPosition: 'left', required: false, options: [], hidden: false},
|
||||
]},
|
||||
{minHeight: 20},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_add_inventory_save', label: 'Guardar'}, {},
|
||||
{view: 'button', id: 'cmd_add_inventory_cancel', label: 'Cancelar', type: 'danger'}, {}
|
||||
]},
|
||||
{minHeight: 20},
|
||||
]}
|
||||
|
||||
|
||||
var win_add_inventory = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_add_inventory',
|
||||
width: 600,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Agregar entrada manualmente',
|
||||
body: body_add_inventory,
|
||||
})
|
||||
$$('cmd_add_inventory_save').attachEvent('onItemClick', cmd_add_inventory_save_click)
|
||||
$$('cmd_add_inventory_cancel').attachEvent('onItemClick', cmd_add_inventory_cancel_click)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var grid_warehouse_exists_cols = [
|
||||
{ id: 'id', header: 'ID', width: 75, hidden: true},
|
||||
{ id: 'warehouse', header: ['Almacen'], fillspace:true,
|
||||
footer: {text: 'Total', css: 'right'}},
|
||||
{ id: 'exists', header: ['Existencia'], width: 100, sort: 'int',
|
||||
format: webix.i18n.numberFormat, css: 'right',
|
||||
footer: {content: 'summColumn', css: 'right'} },
|
||||
]
|
||||
|
||||
|
||||
var grid_warehouse_exists = {
|
||||
view: 'datatable',
|
||||
id: 'grid_warehouse_exists',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
select: 'row',
|
||||
footer: true,
|
||||
columns: grid_warehouse_exists_cols,
|
||||
}
|
||||
|
||||
|
||||
var body_win_show_exists = {rows: [{maxHeight: 10, minHeight: 10},
|
||||
{minWidth: 500},
|
||||
{cols: [
|
||||
{maxWidth: 10},
|
||||
{view: 'text', id: 'txt_id_product', readonly: true, hidden: true},
|
||||
grid_warehouse_exists,
|
||||
{maxWidth: 10}
|
||||
]},
|
||||
{maxHeight: 10},
|
||||
{cols: [{maxWidth: 10},
|
||||
{view: 'label', id: 'lbl_title_move', label: 'Primero, selecciona el almacen origen en la tabla superior.'},
|
||||
]},
|
||||
{cols: [{maxWidth: 10},
|
||||
{view: 'counter', id: 'txt_cant_to_move', label: 'Cantidad a mover:',
|
||||
labelPosition: 'top', step: 1, value: 0, min: 0.01},
|
||||
{view: 'richselect', id: 'lst_warehouse_target', label: 'Almacen destino: ',
|
||||
labelPosition: 'top', required: false, options: []}, {maxWidth: 10},
|
||||
{view: 'button', id: 'cmd_warehouse_move', label: 'Mover', maxWidth: 100},
|
||||
{maxWidth: 10}]},
|
||||
{minHeight: 25, maxHeight: 25},
|
||||
{template: 'Ajuste de almacen', type: 'section'},
|
||||
{cols: [{maxWidth: 10},
|
||||
{view: 'counter', id: 'txt_cant_to_adjust', label: 'Cantidad a ajustar:',
|
||||
labelPosition: 'top', step: 1, value: 0, min: -1000000},
|
||||
{view: 'button', id: 'cmd_adjust_stock', label: 'Ajustar', maxWidth: 100},
|
||||
{maxWidth: 10}]},
|
||||
{maxHeight: 20, minHeight: 20},
|
||||
{cols: [{},
|
||||
{view: 'button', id: 'cmd_win_show_exists_close', label: 'Cerrar', type: 'danger'},
|
||||
{}]},
|
||||
{maxHeight: 20, minHeight: 20},
|
||||
]}
|
||||
|
||||
|
||||
var win_show_exists = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_show_exists',
|
||||
width: 500,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Existencia por Almacen',
|
||||
body: body_win_show_exists,
|
||||
})
|
||||
$$('cmd_win_show_exists_close').attachEvent('onItemClick', cmd_win_show_exists_close_click)
|
||||
$$('cmd_warehouse_move').attachEvent('onItemClick', cmd_warehouse_move_click)
|
||||
$$('cmd_adjust_stock').attachEvent('onItemClick', cmd_adjust_stock_click)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
|
||||
|
||||
var toolbar_students = [
|
||||
{view: 'button', id: 'cmd_new_student', label: 'Nuevo', type: 'iconButton',
|
||||
autowidth: true, icon: 'user-plus'},
|
||||
{view: 'button', id: 'cmd_edit_student', label: 'Editar', type: 'iconButton',
|
||||
autowidth: true, icon: 'user'},
|
||||
{view: 'button', id: 'cmd_delete_student', label: 'Eliminar', type: 'iconButton',
|
||||
autowidth: true, icon: 'user-times'},
|
||||
]
|
||||
|
||||
|
||||
var grid_cols_students = [
|
||||
{id: 'index', header:'#', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 2, css: 'right'}},
|
||||
{id: 'id', header: 'Clave', sort: 'int', css: 'right'},
|
||||
{id: 'nombre', header: ['Nombre', {content: 'textFilter'}],
|
||||
sort: 'string'},
|
||||
{id: 'paterno', header: ['A. Paterno', {content: 'textFilter'}],
|
||||
sort: 'string'},
|
||||
{id: 'materno', header: ['A. Materno', {content: 'textFilter'}],
|
||||
sort: 'string'},
|
||||
{id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust: 'data',
|
||||
sort: 'string'},
|
||||
{id: 'curp', header: ['CURP'], sort: 'string', adjust: 'data'},
|
||||
]
|
||||
|
||||
|
||||
var grid_students = {
|
||||
view: 'datatable',
|
||||
id: 'grid_students',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_cols_students,
|
||||
ready:function(){
|
||||
this.adjustColumn('index');
|
||||
this.adjustColumn('id');
|
||||
this.adjustColumn('nombre');
|
||||
this.adjustColumn('rfc');
|
||||
this.adjustColumn('curp');
|
||||
},
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i+1;
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var rows_school_home = [
|
||||
{view: 'toolbar', elements: toolbar_students},
|
||||
grid_students,
|
||||
]
|
||||
|
||||
|
||||
var student_controls_generales = [
|
||||
{view: 'text', id: 'student_name', name: 'nombre', label: 'Nombre: ',
|
||||
required: true, invalidMessage: 'El nombre es requerido'},
|
||||
{view: 'text', id: 'student_paterno', name: 'paterno', label: 'Apellido Paterno: ',
|
||||
required: true, invalidMessage: 'El apellido paterno es requerido'},
|
||||
{view: 'text', id: 'student_materno', name: 'materno',
|
||||
label: 'Apellido Materno: '},
|
||||
{cols: [
|
||||
{view: 'text', id: 'student_rfc', name: 'rfc', label: 'RFC: ',
|
||||
invalidMessage: 'RFC inválido', adjust: 'data',
|
||||
attributes: {maxlength: 13}},
|
||||
{view: 'text', id: 'student_curp', name: 'curp', label: 'CURP: ',
|
||||
required: true, invalidMessage: 'CURP inválido', adjust: 'data',
|
||||
attributes: {maxlength: 20}},
|
||||
{}]},
|
||||
{cols: [
|
||||
{view: 'richselect', id: 'student_grupo', name: 'grupo',
|
||||
label: 'Nivel Educativo: ', required: true, options: [],
|
||||
invalidMessage: 'El Nivel Educativo es requerido'},
|
||||
{},
|
||||
]},
|
||||
]
|
||||
|
||||
|
||||
var form_controls_student = [
|
||||
{
|
||||
view: 'tabview',
|
||||
id: 'tab_student',
|
||||
tabbar: {options: ['Datos Generales']}, animate: true,
|
||||
cells: [
|
||||
{id: 'Datos Generales', rows: student_controls_generales},
|
||||
]
|
||||
},
|
||||
{rows: [
|
||||
{ template:"", type: "section" },
|
||||
{ margin: 10, cols: [{},
|
||||
{view: "button", id: "cmd_save_student", label: "Guardar" ,
|
||||
type: "form", autowidth: true, align: "center"},
|
||||
{view: "button", id: "cmd_cancel_student", label: "Cancelar" ,
|
||||
type: "danger", autowidth: true, align: "center"},
|
||||
{}]
|
||||
},
|
||||
]}
|
||||
]
|
||||
|
||||
|
||||
var form_student = {
|
||||
type: 'space',
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_student',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: form_controls_student,
|
||||
elementsConfig: {
|
||||
labelWidth: 150,
|
||||
labelAlign: 'right'
|
||||
},
|
||||
rules: {
|
||||
nombre: function(value){ return value.trim() != '';},
|
||||
curp: validate_curp,
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
var multi_school = {
|
||||
id: 'multi_school',
|
||||
view: 'multiview',
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: 'school_home', rows: rows_school_home},
|
||||
{id: 'school_groups', rows: []},
|
||||
{id: 'new_student', rows: [form_student]},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var app_school = {
|
||||
id: 'app_school',
|
||||
rows:[
|
||||
{view: 'template', id: 'th_school', type: 'header',
|
||||
template: 'Administración de Escuela'},
|
||||
multi_school
|
||||
],
|
||||
}
|
|
@ -0,0 +1,492 @@
|
|||
|
||||
|
||||
var toolbar_tickets = [
|
||||
{view: 'button', id: 'cmd_nuevo_ticket', label: 'Nuevo', type: 'iconButton',
|
||||
autowidth: true, icon: 'plus'},
|
||||
{view: 'button', id: 'cmd_ticket_from_ticket', label: 'Regenerar',
|
||||
type: 'iconButton', autowidth: true, icon: 'pencil'},
|
||||
{view: 'button', id: 'cmd_ticket_to_invoice', label: 'Facturar',
|
||||
type: 'iconButton', autowidth: true, icon: 'file-code-o'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_ticket_report_pdf', label: 'Reporte',
|
||||
type: 'iconButton', autowidth: true, icon: 'file-pdf-o'},
|
||||
{view: 'button', id: 'cmd_ticket_report_xls', label: 'Reporte',
|
||||
type: 'iconButton', autowidth: true, icon: 'table'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_cancelar_ticket', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
]
|
||||
|
||||
|
||||
var toolbar_tickets_filter = [
|
||||
{view: 'button', id: 'cmd_ticket_filter_today', label: 'Hoy', type: 'iconButton',
|
||||
autowidth: true, icon: 'filter'},
|
||||
{view: 'richselect', id: 'filter_year_ticket', label: 'Año',
|
||||
labelAlign: 'right', labelWidth: 50, width: 150, options: []},
|
||||
{view: 'richselect', id: 'filter_month_ticket', label: 'Mes',
|
||||
labelAlign: 'right', labelWidth: 50, width: 200, options: months},
|
||||
{view: 'daterangepicker', id: 'filter_dates_ticket', label: 'Fechas',
|
||||
labelAlign: 'right', width: 300},
|
||||
]
|
||||
|
||||
|
||||
var grid_tickets_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "header",
|
||||
sort: "string"},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
|
||||
sort: 'int', css: 'right', footer: {text: 'Tickets', colspan: 3}},
|
||||
{id: "fecha", header: ["Fecha y Hora"],
|
||||
adjust: "data", sort: "date"},
|
||||
{id: "estatus", header: ["Estatus", {content: "selectFilter"}],
|
||||
adjust: "data", sort:"string"},
|
||||
{id: 'total', header: ['Total', {content: 'numberFilter'}], width: 150,
|
||||
sort: 'int', format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summActive', css: 'right'}},
|
||||
{id: "cliente", header: ["Razón Social", {content: "selectFilter"}],
|
||||
fillspace:true, sort:"string", hidden: true},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
{id: 'print', header: '', adjust: 'data', template: get_icon('print')},
|
||||
]
|
||||
|
||||
|
||||
var grid_tickets = {
|
||||
view: 'datatable',
|
||||
id: 'grid_tickets',
|
||||
select: 'row',
|
||||
scrollY: true,
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_tickets_cols,
|
||||
scheme:{
|
||||
$change:function(item){
|
||||
if (item.estatus == 'Cancelado'){
|
||||
item.$css = 'cancel'
|
||||
}
|
||||
}
|
||||
},
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var rows_tickets_home = [
|
||||
{view: 'toolbar', elements: toolbar_tickets},
|
||||
{view: 'toolbar', elements: toolbar_tickets_filter},
|
||||
grid_tickets,
|
||||
]
|
||||
|
||||
|
||||
var ticket_suggest_products = {
|
||||
view: 'gridsuggest',
|
||||
id: 'gt_productos_found',
|
||||
name: 'gt_productos_found',
|
||||
body: {
|
||||
autoConfig: false,
|
||||
header: true,
|
||||
columns: [
|
||||
{id: 'id', hidden: true},
|
||||
{id: 'clave', header: 'Clave', adjust: 'data'},
|
||||
{id: 'descripcion', header: 'Descripción', width: 500},
|
||||
{id: 'unidad', header: 'Unidad', adjust: 'data'},
|
||||
{id: 'valor_unitario', header: 'Valor Unitario', adjust: 'data',
|
||||
format: webix.i18n.priceFormat}
|
||||
],
|
||||
dataFeed:function(text){
|
||||
if (text.length > 2){
|
||||
this.load('/values/product?name=' + text)
|
||||
}else{
|
||||
this.hide()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var tbody_buscar_producto = {rows: [
|
||||
{cols: [
|
||||
{view: 'search', id: 'tsearch_product_key', name: 'tsearch_product_key',
|
||||
label: 'por Clave', labelPosition:'top', maxWidth: 250,
|
||||
placeholder: 'Presiona ENTER para buscar'},
|
||||
{view: 'search', id: 'tsearch_product_name', name: 'tsearch_product_name',
|
||||
label: 'por Descripción', labelPosition:'top',
|
||||
suggest: ticket_suggest_products, placeholder: 'Captura al menos tres letras'},
|
||||
]},
|
||||
]}
|
||||
|
||||
|
||||
var grid_tdetails_cols = [
|
||||
{id: "id_product", header:"ID", hidden: true},
|
||||
{id: 'delete', header: '', width: 30, css: 'delete'},
|
||||
{id: "clave", header:{text: 'Clave', css: 'center'}, width: 100,
|
||||
footer: {text: 'Artículos', css: 'right_footer3'}},
|
||||
{id: "clave_sat", hidden: true},
|
||||
{id: "descripcion", header:{text: 'Descripción', css: 'center'},
|
||||
fillspace: true, footer: {content: 'countRows', css: 'footer3'}},
|
||||
{id: "unidad", header:{text: 'Unidad', css: 'center'}, width: 100,
|
||||
editor: 'select', options: 'values/unidades'},
|
||||
{id: 'cantidad', header: {text: 'Cantidad', css: 'center'}, width: 100,
|
||||
format: webix.i18n.numberFormat, css: 'right', editor: 'text',
|
||||
footer: {content: 'summColumn', css: 'right_footer3'}},
|
||||
{id: "valor_unitario", header:{text: 'Valor Unitario', css: 'center'},
|
||||
width: 100, format: webix.i18n.priceFormat, css: 'right', editor: 'text',
|
||||
footer: {text: 'Total ', css: 'right_footer2'}},
|
||||
{id: 'descuento', header: {text: 'Descuento', css: 'center'}, hidden: true,
|
||||
width: 80, format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
||||
{id: 'precio_final', hidden: true, header: 'precio_final', width: 80,
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: "importe", header:{text: 'Importe', css: 'center'}, width: 150,
|
||||
format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summColumn', css: 'right_footer2'}},
|
||||
{id: "inventario", hidden: true},
|
||||
{id: "existencia", hidden: true},
|
||||
]
|
||||
|
||||
|
||||
var grid_tdetails = {
|
||||
view: 'datatable',
|
||||
id: 'grid_tdetails',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
editable: true,
|
||||
footer: true,
|
||||
columns: grid_tdetails_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.delete = '-'
|
||||
})
|
||||
}
|
||||
},
|
||||
data: [],
|
||||
}
|
||||
|
||||
|
||||
var body_ticket_informacion = {rows: [
|
||||
{view: 'richselect', id: 'lst_ticket_forma_pago', name: 'forma_pago',
|
||||
label: 'Forma de Pago', labelPosition: 'top', required: true,
|
||||
options: []},
|
||||
],}
|
||||
|
||||
|
||||
var toolbar_new_ticket = {
|
||||
view: 'toolbar', elements: [
|
||||
{view: 'button', id: 'cmd_generar_ticket', label: 'Generar',
|
||||
icon: 'ticket', type: 'iconButton', autowidth: true,
|
||||
align: 'center', hotkey: 'Ctrl+g'}, {},
|
||||
{view: 'button', id: 'cmd_ticket_notes', label: 'Notas',
|
||||
autowidth: true, type: 'iconButton', icon: 'commenting-o'}, {},
|
||||
{view: 'button', id: 'cmd_cerrar_ticket', label: 'Cerrar',
|
||||
type: 'danger', autowidth: true, align: 'center'}
|
||||
]}
|
||||
|
||||
|
||||
var grid_ticket_total_up = {
|
||||
view: 'datatable',
|
||||
id: 'grid_ticket_total_up',
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
width: 250,
|
||||
header: false,
|
||||
footer: true,
|
||||
hidden: true,
|
||||
rowHeight: 0,
|
||||
columns: [
|
||||
{id: 'id', hidden: true},
|
||||
{id: 'title', width: 100,
|
||||
footer: {text: 'Total ', css: 'right_footer2'}},
|
||||
{id: 'total', fillspace: true, format: webix.i18n.priceFormat,
|
||||
footer: {content: 'summColumn', css: 'right_footer2'}},
|
||||
],
|
||||
data: [{id:0, title: '', total: 0.00}]
|
||||
}
|
||||
|
||||
|
||||
var cells_new_ticket = [
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
toolbar_new_ticket,
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
{cols: [{rows: [
|
||||
{view: 'fieldset', label: 'Buscar Producto', body: tbody_buscar_producto},
|
||||
]},
|
||||
{maxWidth: 10},
|
||||
{maxWidth: 300, rows: [
|
||||
{view: 'fieldset', label: 'Información', body: body_ticket_informacion},
|
||||
]},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'label', label: 'Detalle', height: 30, align: 'left'},
|
||||
{},
|
||||
grid_ticket_total_up,
|
||||
]},
|
||||
grid_tdetails,
|
||||
]
|
||||
|
||||
|
||||
var toolbar_ticket_invoice = {view: 'toolbar', elements: [{},
|
||||
{view: 'checkbox', id: 'chk_is_invoice_day', labelWidth: 0, width: 150,
|
||||
labelRight: 'Es Factura Global'},
|
||||
{view: 'richselect', id: 'lst_global_periodicidad_2', labelWidth: 90, width: 225,
|
||||
label: 'Periodicidad:', options: opt_global_periodicidad, value: '01', disabled: true},
|
||||
{view: 'richselect', id: 'lst_global_months_2', labelWidth: 50, width: 250,
|
||||
label: 'Mes:', options: opt_global_months, value: '01', disabled: true},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_close_ticket_invoice', label: 'Cerrar',
|
||||
type: 'danger', autowidth: true, align: 'center'}
|
||||
]}
|
||||
|
||||
|
||||
var ticket_suggest_partners = {
|
||||
view: 'gridsuggest',
|
||||
id: 'grid_ticket_clients_found',
|
||||
name: 'grid_ticket_clients_found',
|
||||
body: {
|
||||
autoConfig: false,
|
||||
header: false,
|
||||
columns: [
|
||||
{id: 'id', hidden: true},
|
||||
{id: 'nombre', adjust: 'data'},
|
||||
{id: 'rfc', adjust: 'data'},
|
||||
{id: 'forma_pago', hidden: true},
|
||||
{id: 'uso_cfdi', hidden: true},
|
||||
],
|
||||
dataFeed:function(text){
|
||||
if (text.length > 2){
|
||||
this.load('/values/client?name=' + text)
|
||||
}else{
|
||||
this.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var ticket_search_client = {cols: [{rows: [
|
||||
{view: 'fieldset', id: 'fs_ticket_search_client', label: 'Buscar Cliente', body: {rows: [
|
||||
{cols: [
|
||||
{view: 'search', id: 'tsearch_client_key', name: 'tsearch_client_key',
|
||||
label: 'por Clave', labelPosition: 'top', maxWidth: 250,
|
||||
placeholder:'Presiona ENTER para buscar'},
|
||||
{view: 'search', id: 'tsearch_client_name',
|
||||
name: 'tsearch_client_name', label: 'por Nombre o RFC',
|
||||
labelPosition: 'top', suggest: ticket_suggest_partners,
|
||||
placeholder: 'Captura al menos tres letras'},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'label', id: 'lbl_tclient_title', autowidth:true,
|
||||
name: "lbl_tclient_title", label: 'Seleccionado: ' },
|
||||
{view: 'label', id: 'lbl_tclient', name: 'lbl_tclient',
|
||||
label: 'Ninguno'},
|
||||
]}
|
||||
]}},
|
||||
]},]}
|
||||
|
||||
|
||||
var grid_tickets_active_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right'},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
||||
sort: "string"},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
|
||||
sort: 'int', css: 'right', footer: {content: 'countRows', css: 'right'}},
|
||||
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort: "string",
|
||||
footer: 'Tickets'},
|
||||
{id: 'total', header: 'Total', width: 150,sort: 'int', css: 'right',
|
||||
format: webix.i18n.priceFormat, footer: {content: 'summColumn',
|
||||
css: 'right'}},
|
||||
]
|
||||
|
||||
|
||||
var grid_tickets_active = {
|
||||
view: 'datatable',
|
||||
id: 'grid_tickets_active',
|
||||
select: 'row',
|
||||
multiselect: true,
|
||||
adjust: true,
|
||||
footer: true,
|
||||
drag: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_tickets_active_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var grid_tickets_invoice_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right'},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
||||
sort: "string"},
|
||||
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
|
||||
sort: 'int', css: 'right', footer: {content: 'countRows', css: 'right'}},
|
||||
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort: "string",
|
||||
footer: 'Tickets'},
|
||||
{id: 'total', header: 'Total', width: 150,sort: 'int', css: 'right',
|
||||
format: webix.i18n.priceFormat, footer: {content: 'summColumn',
|
||||
css: 'right'}},
|
||||
]
|
||||
|
||||
|
||||
var grid_tickets_invoice = {
|
||||
view: 'datatable',
|
||||
id: 'grid_tickets_invoice',
|
||||
select: 'row',
|
||||
multiselect: true,
|
||||
adjust: true,
|
||||
footer: true,
|
||||
drag: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_tickets_invoice_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var controls_ticket_to_invoice = [
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
toolbar_ticket_invoice,
|
||||
{minHeight: 10, maxHeight: 10},
|
||||
ticket_search_client,
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
{cols:[
|
||||
{rows: [{view: 'label', label: 'Tickets sin facturar', height: 30,
|
||||
align: 'left'},
|
||||
grid_tickets_active]},
|
||||
{rows:[{},
|
||||
{view: 'button', id: 'cmd_move_tickets_right', label: '->', autowidth: true},
|
||||
{view: 'button', id: 'cmd_move_tickets_left', label: '<-', autowidth: true},
|
||||
{}]},
|
||||
{rows: [{view: 'label', label: 'Tickets a facturar', height: 30,
|
||||
align: 'left'},
|
||||
grid_tickets_invoice]},
|
||||
]},
|
||||
{minHeight: 20, maxHeight: 20},
|
||||
{margin: 20, cols: [{},
|
||||
{view: 'button', id: 'cmd_new_invoice_from_ticket', label: 'Facturar',
|
||||
icon: 'ticket', type: 'iconButton', autowidth: true, align: 'center'},
|
||||
{}]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
var controls_new_ticket = [
|
||||
{
|
||||
view: 'tabview',
|
||||
id: 'tv_new_ticket',
|
||||
animate: true,
|
||||
cells: [
|
||||
{id: 'Generar', rows: cells_new_ticket},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
var controls_ticket_invoice = [
|
||||
{
|
||||
view: 'tabview',
|
||||
id: 'tv_ticket_invoice',
|
||||
animate: true,
|
||||
cells: [
|
||||
{id: 'Facturar Tickets', rows: controls_ticket_to_invoice},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
var form_new_ticket = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_new_ticket',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_new_ticket,
|
||||
}],
|
||||
}
|
||||
|
||||
|
||||
var form_ticket_invoice = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_ticket_invoice',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_ticket_invoice,
|
||||
}],
|
||||
}
|
||||
|
||||
|
||||
var multi_tickets = {
|
||||
id: 'multi_tickets',
|
||||
view: 'multiview',
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: 'tickets_home', rows: rows_tickets_home},
|
||||
{id: 'tickets_new', rows:[form_new_ticket]},
|
||||
{id: 'tickets_invoice', rows:[form_ticket_invoice]}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var app_tickets = {
|
||||
id: 'app_tickets',
|
||||
rows:[
|
||||
{view: 'template', id: 'th_ticckets', type: 'header',
|
||||
template: 'Punto de venta - Tickets'},
|
||||
multi_tickets
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
var body_ticket_notes = {rows: [
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
{view: 'textarea', id: 'ticket_notes', name: 'ticket_notes', height: 300,
|
||||
placeholder: 'Captura las notas'},
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
{cols: [{}, {view: 'button', id: 'cmd_ticket_save_note', autowidth: true,
|
||||
label: 'Guardar y Cerrar', type: 'iconButton', hotkey: 'Ctrl+enter'},
|
||||
{}]},
|
||||
{minHeight: 5, maxHeight: 5},
|
||||
]}
|
||||
|
||||
|
||||
var win_ticket_notes = {
|
||||
init: function(){
|
||||
webix.ui({
|
||||
view: 'window',
|
||||
id: 'win_ticket_notes',
|
||||
height: 400,
|
||||
width: 500,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
head: 'Notas',
|
||||
body: body_ticket_notes,
|
||||
})
|
||||
$$('cmd_ticket_save_note').attachEvent('onItemClick', cmd_ticket_save_note_click)
|
||||
}
|
||||
}
|
|
@ -1,14 +1,8 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
<link rel="stylesheet" href="/static/css/sidebar_air.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/app.css" type="text/css">
|
||||
<script src="/static/js/sidebar.js" type="text/javascript" ></script>
|
||||
|
||||
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/admin.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/admin.js" type="text/javascript" ></script>
|
||||
|
||||
</%block>
|
||||
|
||||
<%block name="content">
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="/static/img/favicon.png">
|
||||
<link rel="stylesheet" href="/static/css/air.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/sidebar_air.css" type="text/css">
|
||||
<link rel="stylesheet" href="/static/css/app.css" type="text/css">
|
||||
<script src="/static/js/webix.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/es-MX.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/lokijs.min.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
|
||||
|
||||
<%block name="media"/>
|
||||
|
||||
</head>
|
||||
|
@ -17,7 +20,7 @@
|
|||
<body>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
webix.debug = true;
|
||||
webix.debug = false;
|
||||
webix.i18n.setLocale("es-MX");
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/empresas.js" type="text/javascript" ></script>
|
||||
</%block>
|
||||
|
||||
|
@ -10,29 +11,131 @@
|
|||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
function agregar_empresa(values){
|
||||
webix.ajax().post("/empresas", values, function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
$$('form_empresas').clear()
|
||||
$$('grid_empresas').add(values.row)
|
||||
$$('grid_empresas').refresh()
|
||||
msg_ok(values.msg)
|
||||
} else {
|
||||
msg_error(values.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function validate_nuevo_rfc(){
|
||||
var msg = ''
|
||||
var form = this.getFormView();
|
||||
|
||||
if (!form.validate()) {
|
||||
webix.message({ type:"error", text:"Valores inválidos" });
|
||||
msg = 'Valores inválidos'
|
||||
msg_error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var values = form.getValues()
|
||||
|
||||
webix.ajax().post("/empresas", values, function(text, data, xhr) {
|
||||
if(!validar_rfc(values['alta_rfc'])){
|
||||
return
|
||||
}
|
||||
|
||||
values['opt'] = 1
|
||||
|
||||
msg = '¿Estás seguro de agregar este nuevo emisor?'
|
||||
webix.confirm({
|
||||
title: 'Agregar Emisor',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
msg = 'Agregando empresa, espera la confirmación...'
|
||||
msg_ok(msg)
|
||||
agregar_empresa(values)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function borrar_empresa(id){
|
||||
var row = $$('grid_empresas').getItem(id)
|
||||
webix.ajax().del('/empresas', {rfc: row.rfc}, function(text, xml, xhr){
|
||||
msg = 'Emisor eliminado correctamente'
|
||||
if(xhr.status == 200){
|
||||
$$('grid_empresas').remove(id)
|
||||
msg_ok(msg)
|
||||
}else{
|
||||
msg = 'No se pudo eliminar'
|
||||
msg_error(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function grid_empresas_click(id, e, node){
|
||||
if(id.column != 'delete'){
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de borrar el RFC seleccionado?<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER'
|
||||
webix.confirm({
|
||||
title: 'Borrar Emisor',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
borrar_empresa(id.row)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function respaldar_bd(){
|
||||
webix.ajax().post("/empresas", {'opt': 2}, function(text, data, xhr) {
|
||||
var values = data.json();
|
||||
if (values.ok) {
|
||||
|
||||
msg_ok(values.msg)
|
||||
} else {
|
||||
webix.message({ type:"error", text: values.msg })
|
||||
msg_error(values.msg)
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_respaldar_bd(){
|
||||
msg = '¿Estás seguro de respaldar las Bases de Datos?'
|
||||
webix.confirm({
|
||||
title: 'Respaldar BD',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
msg = 'Respaldando Bases de datos...'
|
||||
msg_ok(msg)
|
||||
respaldar_bd()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
webix.ready(function(){
|
||||
webix.ui(ui_empresas);
|
||||
});
|
||||
webix.ui(ui_empresas)
|
||||
$$('grid_empresas').attachEvent('onItemClick', grid_empresas_click)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ function validate_login(){
|
|||
|
||||
webix.ready(function(){
|
||||
webix.ui(ui_login);
|
||||
webix.ajax().get("/values/titlelogin", function(text, data, xhr){
|
||||
var value = data.json();
|
||||
$$("title_login").setHTML(value);
|
||||
})
|
||||
$$("txt_rfc").focus();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%block name="media">
|
||||
<link rel="stylesheet" href="/static/css/sidebar_air.css" type="text/css">
|
||||
<script src="/static/js/sidebar.js" type="text/javascript" ></script>
|
||||
|
||||
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/partners.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/products.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/bancos.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/school.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/nomina.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/tickets.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/invoices.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/ui/main.js" type="text/javascript" ></script>
|
||||
|
||||
<script src="/static/js/controller/partners.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/products.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/bancos.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/school.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/nomina.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/tickets.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/invoices.js" type="text/javascript" ></script>
|
||||
<script src="/static/js/controller/main.js" type="text/javascript" ></script>
|
||||
|
||||
|
|