forked from nathalie/pedi2
Compare commits
834 commits
selecciona
...
master
Author | SHA1 | Date | |
---|---|---|---|
0f8e58841e | |||
63ce45f903 | |||
965a9c7cfc | |||
d343be346e | |||
c1bff4e8a9 | |||
6258853ec4 | |||
595c0893c5 | |||
7ade1b18f1 | |||
5aadfe6753 | |||
5711c28f56 | |||
786ab8cb98 | |||
6c49a4dca0 | |||
9cc82a9171 | |||
![]() |
e61c3f6d4b | ||
bb07289bcc | |||
e0f55661a4 | |||
76239ee7dd | |||
53e75ae357 | |||
bcc4f4a28a | |||
66298228e3 | |||
9ee6de7877 | |||
8362cacc84 | |||
e029c42c0a | |||
596ac50e60 | |||
f6de37a1eb | |||
9d98a5cd5b | |||
4062f4b786 | |||
bd92c26b0a | |||
6ea534932f | |||
96516a5083 | |||
9c07a91914 | |||
d5e70dc291 | |||
45a7688fbd | |||
4d05edd9c3 | |||
cc6fe6878a | |||
7f59b9a2ff | |||
148e54356c | |||
87c3bb207f | |||
d7c3ed857c | |||
b0ac8f538c | |||
7a7cd678ad | |||
e9a6def7c1 | |||
53dc4d735e | |||
a74f89f684 | |||
dd463a6a79 | |||
35e1d6455e | |||
572a8cf3be | |||
b976826bf5 | |||
da4fd472ae | |||
89f886e32c | |||
92d6bc2035 | |||
fee23f389c | |||
7619196179 | |||
537bfd52ff | |||
3a313d033d | |||
cee049c545 | |||
0207fca0cc | |||
ed89065faf | |||
502aefd7a8 | |||
44f0d8c66b | |||
03475daa99 | |||
aa75e3de79 | |||
21b16e0243 | |||
e0d17e052b | |||
e3b17eea4a | |||
5e54d2afea | |||
9a57a826dc | |||
a1aa381052 | |||
ea9a9e2195 | |||
251dbd1120 | |||
98120f1ce9 | |||
71c4b166be | |||
c35eb49001 | |||
0cdb491246 | |||
01cf18b540 | |||
8dba92e8c1 | |||
c602742e33 | |||
a4951bfdfd | |||
88c82d9439 | |||
929191f173 | |||
08bdbe0ee1 | |||
9f4afd1bac | |||
c7834fa9d2 | |||
21d28c6a5b | |||
546eceaefd | |||
bc70e28127 | |||
f6f565b6bd | |||
eaae5d02ea | |||
f961601184 | |||
e521b4521f | |||
11d8bd1920 | |||
3a6face6ba | |||
20c7d33ace | |||
9c234107e8 | |||
6d55b77a95 | |||
e7a8d89a29 | |||
b1fb744684 | |||
c84ab5f475 | |||
86bf66ebcd | |||
7c2f592072 | |||
7c8c5ad60d | |||
e49c043231 | |||
a0ee4131c8 | |||
5a1d95c636 | |||
d261506775 | |||
e58e19bfe1 | |||
d86d52a478 | |||
0e42cf2c14 | |||
200c38cb29 | |||
60c327f74b | |||
309ce637c8 | |||
5c059057b9 | |||
8fa3f78280 | |||
b6cd844ffd | |||
3c14055006 | |||
e37aa25b3d | |||
d87091846d | |||
f520578525 | |||
aaeee70c9e | |||
05dc58710d | |||
5020d406bf | |||
6d6d8d4387 | |||
![]() |
116875b769 | ||
ee96d89e55 | |||
5d7d533083 | |||
b1b764fd7c | |||
cc6b0f5a6e | |||
db87c38e3b | |||
8fb810c73f | |||
208cb31b53 | |||
db056e7d34 | |||
8649ff5bbd | |||
09fce4e96a | |||
0ce7b00e90 | |||
0009d4b123 | |||
9062faf24e | |||
54d1e6ab36 | |||
5e69a04d35 | |||
b61fdb1fff | |||
8b86cddb33 | |||
4bbab3a8f9 | |||
2356fe597a | |||
bb27698e80 | |||
5a9d7cb54b | |||
cdbe38e41b | |||
0397810260 | |||
53414643a6 | |||
639f6cff77 | |||
6627118dce | |||
d890d405bd | |||
db714a209c | |||
eddf2776d0 | |||
07a71098f4 | |||
6501e76507 | |||
06d80eed5a | |||
b68d22380e | |||
c56f67ca85 | |||
7526ab300c | |||
bcadd1f1ae | |||
2a2ea06875 | |||
441007e66b | |||
78b9d682cc | |||
1115764d81 | |||
5be87b5c26 | |||
670bb39e75 | |||
1498b67200 | |||
a7096e7dc0 | |||
422be13c51 | |||
0e63e795e4 | |||
37cdbe5480 | |||
de635d1a82 | |||
9f0319fe48 | |||
8928fb2842 | |||
c514569acd | |||
0fc370e9d1 | |||
9332aa33c1 | |||
c11331695a | |||
688abf406d | |||
ceaddcabc3 | |||
f9a0ee5146 | |||
e879daa73e | |||
91225d7796 | |||
a3b6d686d3 | |||
612abc4378 | |||
ac559770c0 | |||
5c3d68a4e9 | |||
a497ae134e | |||
f16b18c8b1 | |||
![]() |
665ab517fb | ||
![]() |
eee23082db | ||
![]() |
eb1b5bbc2e | ||
![]() |
46675f9acf | ||
c58824ff52 | |||
fcb2d2c5bc | |||
686fcf3bd5 | |||
c064e80116 | |||
f26234c3bf | |||
0173d7bd36 | |||
a16487cc3f | |||
![]() |
d9747c9280 | ||
dbaff75734 | |||
a96adedb82 | |||
![]() |
8d50a29355 | ||
5b8f9cb694 | |||
214292bc8f | |||
![]() |
b752f9e8c5 | ||
![]() |
6787dde711 | ||
![]() |
02aba80fc9 | ||
![]() |
afddeadeac | ||
17148d73f8 | |||
a38bceab82 | |||
ff96c104a2 | |||
854278bc99 | |||
197b087097 | |||
5c51653037 | |||
a5be67df2e | |||
d8c8865d13 | |||
9a310484d6 | |||
80b5dc60ac | |||
517e5203c9 | |||
dbdb97a78e | |||
79bdb04ce2 | |||
3503be8e56 | |||
faa947e6a7 | |||
fdd3232345 | |||
b72fc57b8d | |||
3cb27c5c30 | |||
b4458862f4 | |||
7a4aa6d7a0 | |||
0637b7a208 | |||
af8879eadd | |||
9e93b914ac | |||
![]() |
687768d860 | ||
1b920093c4 | |||
210c91f3a8 | |||
2ee7fca584 | |||
258bccf59b | |||
ca42526a62 | |||
f484bfff79 | |||
9384d09ff6 | |||
f460cdd6ce | |||
4b4a284914 | |||
a641247748 | |||
82a518fa1d | |||
deaa65d857 | |||
4af9e53a50 | |||
8d64d85b8b | |||
2c720faca7 | |||
85fa9f1e9b | |||
c8d1969352 | |||
1eb77be1d0 | |||
3949cf3400 | |||
973d099bf1 | |||
802d4d0c0b | |||
134ed0cd22 | |||
2bfcf59f3e | |||
4e197204a9 | |||
2075bcab0f | |||
c0d8392f6e | |||
ef9a296f5c | |||
bc55b4c34f | |||
e779111856 | |||
d6990f8c88 | |||
8eb385c67e | |||
2970982c77 | |||
9e63c83126 | |||
439f69a30c | |||
d0ce8e8e23 | |||
3b858f5b2b | |||
0512ea9ab2 | |||
8488d9d6c5 | |||
354045c5df | |||
ae1f8673e7 | |||
4f74bf38f9 | |||
8a2539f207 | |||
04673b1754 | |||
88af33d998 | |||
23af6ccd61 | |||
777f442118 | |||
7cae00e613 | |||
5a61ca46c5 | |||
e379825fd9 | |||
6b2da42160 | |||
48cf57a6d8 | |||
aa545ff82a | |||
b29d63ed4d | |||
1e91f443a7 | |||
6782b7f675 | |||
85b3f1dd0f | |||
a006fc15fa | |||
37fd0fb4d3 | |||
d794dbd2b0 | |||
7140796ccd | |||
5b9908e0b5 | |||
f837b7f066 | |||
0dba210a6a | |||
571b02382e | |||
2f071e631d | |||
1e830e3cfd | |||
0381bb0567 | |||
adabd09ea7 | |||
a9ca04811e | |||
5458fae6d9 | |||
5023032ac2 | |||
fb0e13089f | |||
21aa36e3d1 | |||
f81141d18b | |||
8f0d715f8c | |||
45dcf643bf | |||
5468b79562 | |||
08a731673b | |||
94e384c83c | |||
a594e8a049 | |||
fd055cd7c6 | |||
d4df72afe2 | |||
442d35eac8 | |||
154e21fae6 | |||
1a8f9eda18 | |||
128dd05b9a | |||
181fbf924f | |||
8d1eb03ffc | |||
baeff66aaf | |||
1709468f1f | |||
b46b56159b | |||
b8390c4ac6 | |||
36af26a647 | |||
cdf5663b16 | |||
8fbfa75144 | |||
5a0cf73218 | |||
44bd8045b8 | |||
8a32841f9d | |||
e0bb8127f4 | |||
1610acfbe7 | |||
fff9b5b65f | |||
d64659d653 | |||
f92084d399 | |||
f4560c0be5 | |||
fe529c2242 | |||
3509b9348f | |||
83027245e8 | |||
248b346f78 | |||
191f01a398 | |||
408531bec3 | |||
be24daf998 | |||
020d554019 | |||
dd30726d10 | |||
59b6c29508 | |||
2f7ee48930 | |||
caebf1b53b | |||
b76ecf57dc | |||
0dc8f39f07 | |||
e82dd59c34 | |||
0836584192 | |||
b490cd8b25 | |||
a512f8e162 | |||
7bfbbd9309 | |||
6c7e62bcb0 | |||
f4138510cd | |||
ac9b0a00e8 | |||
db5262d655 | |||
ff07551762 | |||
40e466aa82 | |||
5b65bc5d9f | |||
4b3ab56565 | |||
eee3f53672 | |||
fe57e8c6b3 | |||
fe292802cd | |||
da5f0051c8 | |||
47ce7e3bd8 | |||
e6770172ac | |||
fbbb400892 | |||
85746f2d4d | |||
09bc8e7670 | |||
8a1334bae5 | |||
63b51fd92c | |||
e2c716f576 | |||
61e4c341f3 | |||
a485994a72 | |||
6d3173cd1f | |||
e047b0a23c | |||
60a6f3e781 | |||
6bcb22ea00 | |||
1e7afc034e | |||
ea8611771b | |||
6e0238eef7 | |||
ac6fc6bc0e | |||
025b9239c3 | |||
8799446e57 | |||
44465c2783 | |||
0b445ee1c5 | |||
8ad179c61c | |||
f0f046d3cb | |||
a9e9966c93 | |||
2e78d39f12 | |||
de1bae8620 | |||
b330d991c6 | |||
2245eb4939 | |||
eb3e4730bf | |||
2faea3b007 | |||
50d77b0108 | |||
f8b487cebd | |||
fc367c05a3 | |||
bed975e944 | |||
e508e71b81 | |||
498ecd5ec1 | |||
01dbb9667a | |||
f85a8b777f | |||
3bd7219ca2 | |||
087f9c84bf | |||
![]() |
0c322400c2 | ||
b0ae4abc4d | |||
751b89c01d | |||
58211913f4 | |||
250bfd8a33 | |||
b8d1520c54 | |||
9aa5b390f8 | |||
2df7f6fc4b | |||
d526b944bd | |||
916f963e7b | |||
8887a1970c | |||
b04e7e8f45 | |||
b1caed8b15 | |||
ff0a17c776 | |||
9c3b328de0 | |||
d02505a70b | |||
9fcdc5a52a | |||
b1b424897c | |||
ead7483e19 | |||
f909a78e74 | |||
e3f2e63435 | |||
eb05a7de6a | |||
7c7149c5a1 | |||
94760279e7 | |||
70bbaad3c7 | |||
eed099245b | |||
31bc076989 | |||
b5f37c9de9 | |||
b9e964435d | |||
c492876c06 | |||
7eb7dd04d7 | |||
45757f0ae1 | |||
45e8a189cf | |||
fd2c1b2970 | |||
2587c759fb | |||
2a1394a5c4 | |||
56eb59ddeb | |||
354079519a | |||
2ca91addb0 | |||
c46073ed06 | |||
df0b66bf65 | |||
641eb6a4d3 | |||
e598e1496b | |||
085d72b4f8 | |||
c54a0b361f | |||
2a5c215f40 | |||
584cebb902 | |||
d4bffd1df8 | |||
94c2baff07 | |||
7b36aa0b0c | |||
5feb2ff22f | |||
d0ffcda226 | |||
1f2ab91bd3 | |||
184b53cfc8 | |||
345be9c688 | |||
30eb822201 | |||
76f2af2ef9 | |||
9f93a17053 | |||
83016d38b0 | |||
cc734866c5 | |||
c31b808f05 | |||
95a9a404d2 | |||
57b8d6bcce | |||
ac4d5895be | |||
131bf33a73 | |||
5a4b933f11 | |||
bea8de2c8c | |||
92782be7f6 | |||
22cbac14f1 | |||
bddaf223e4 | |||
4b2ed9f90e | |||
cad8dffbcf | |||
c4eb4563d5 | |||
cef38cf69c | |||
8a0f8fbe13 | |||
9abeb98239 | |||
fab7695e6c | |||
2486826dba | |||
1b82700db3 | |||
635cecedb7 | |||
5c97fc9e70 | |||
8e885c18d8 | |||
b5d23c6740 | |||
f778a4f24e | |||
acc21091f9 | |||
ec10bdca92 | |||
f84e1f2954 | |||
df05b31b86 | |||
1b16669512 | |||
d170f9e46e | |||
f5f9838fc3 | |||
c58f24d2d0 | |||
e75fcc562a | |||
6dae6afe95 | |||
1c5b8ecb29 | |||
00b41afa5a | |||
1324898483 | |||
ba22988026 | |||
9c9b1dc6cb | |||
73f02dfff0 | |||
bbb57e1d7f | |||
2996cf4100 | |||
97ec11331b | |||
8c9a0ee4c1 | |||
01d5abdd99 | |||
![]() |
f9e55b38a5 | ||
![]() |
3ad9500f23 | ||
![]() |
538cc84e10 | ||
4e7e46f92d | |||
61e756f9e5 | |||
![]() |
be945b0eee | ||
![]() |
b5f4443836 | ||
c53e342f54 | |||
ff213bd90d | |||
![]() |
1e443ea2ca | ||
![]() |
c1af6909c4 | ||
![]() |
e31c375867 | ||
![]() |
6d10fbc0bf | ||
96eea84997 | |||
10273e2159 | |||
0b55fa8109 | |||
![]() |
9fc47513c2 | ||
![]() |
ff332fadc1 | ||
e106faceda | |||
![]() |
5ef5e93543 | ||
![]() |
177ba193de | ||
88e3532418 | |||
07289b01e9 | |||
5c1fa931eb | |||
![]() |
82f5862063 | ||
![]() |
7eeeae6a1e | ||
744b867af3 | |||
![]() |
52bea8f9b6 | ||
![]() |
d2fde9df83 | ||
![]() |
80a28f4162 | ||
![]() |
1586a1190a | ||
![]() |
a998f76d44 | ||
![]() |
b845637064 | ||
![]() |
6fc7021317 | ||
![]() |
728c54b3f3 | ||
917e3e1df3 | |||
517b95f14f | |||
2337ad9a37 | |||
99f327445e | |||
b4ca119f9a | |||
9d9ebd75b5 | |||
b79548624f | |||
![]() |
fbae6770df | ||
5f565a3f5a | |||
![]() |
69cd306263 | ||
bf3f697299 | |||
53691f6a30 | |||
9259248caf | |||
9f6f36e2e6 | |||
1204a80b3c | |||
b9702a736e | |||
4283eae3be | |||
28f2b3b498 | |||
079b21af04 | |||
ffd4570d44 | |||
82ad4dd910 | |||
e334234c9f | |||
3340de941b | |||
3770d728c3 | |||
c86eb97cb9 | |||
d91d46c589 | |||
449579a768 | |||
bb29e34b1b | |||
![]() |
078e29a01f | ||
189342d785 | |||
003cb86ec0 | |||
12b77de018 | |||
5453b1158f | |||
18ede25c16 | |||
6d58524823 | |||
2a57fdc1e9 | |||
ddd8d57d2b | |||
781ef8a7a1 | |||
43f2a1e928 | |||
97139905cc | |||
438071eea3 | |||
937e7ec16c | |||
9d96010752 | |||
4e7c1232b0 | |||
9b06839798 | |||
4a59b8e146 | |||
![]() |
39e1eaddcf | ||
![]() |
5ca11324a0 | ||
![]() |
758c425f91 | ||
2d7a90f6b2 | |||
11d18ad4a5 | |||
2beda0bf5b | |||
48e1a04bae | |||
f0f05f8361 | |||
800fed2097 | |||
![]() |
203b70e2ef | ||
![]() |
bf703489fd | ||
c57fd0436d | |||
d04650facf | |||
4ee91ed5a0 | |||
32d84879c7 | |||
6f1b4581ce | |||
0659f67e84 | |||
42f0cc11d4 | |||
05d13008fb | |||
5921767654 | |||
475d2a6cd9 | |||
9781d63a60 | |||
057170118d | |||
0c79d3b002 | |||
105335a773 | |||
749940233d | |||
d9e8264cd0 | |||
9babf1975f | |||
716d1ca6fa | |||
388beba5cc | |||
75b7507bbe | |||
9e7eb89014 | |||
808980d77e | |||
66984043bc | |||
05f2777a49 | |||
725a599b6a | |||
1c5cabb253 | |||
31dadcc10b | |||
70755ba0a2 | |||
8fc1a3b256 | |||
814295e8ee | |||
![]() |
fefd052a8e | ||
![]() |
ab7e44fd85 | ||
b66c2fe19d | |||
9cf4a117df | |||
0b427e4796 | |||
85238695c7 | |||
e9321678e2 | |||
43b0b04859 | |||
5036c2baa9 | |||
b19556fd39 | |||
35b0533664 | |||
![]() |
16e5075825 | ||
0665770972 | |||
1ccfbe11a7 | |||
4376586a23 | |||
d16a8de5ac | |||
10f4fefb0c | |||
f3ee5ea7d9 | |||
5b2c489f2d | |||
e7100121d4 | |||
e0a64d3653 | |||
fe2d8608cb | |||
e7c90a4899 | |||
0a51ccba2a | |||
988bf266e8 | |||
![]() |
3941dc0fd2 | ||
![]() |
1a8448ca45 | ||
9954dbd66a | |||
![]() |
14361a858e | ||
8f8733cb7b | |||
aab05541b2 | |||
![]() |
5b6fd933e3 | ||
9634f51054 | |||
80fbbd510d | |||
c278e0a7a5 | |||
f55ac3a4ff | |||
![]() |
e1aa6e2f68 | ||
71b4c1c38d | |||
a7a1f69c5a | |||
3a894f2965 | |||
381909fb7e | |||
17cc127f2e | |||
9991337b87 | |||
b58261bbf0 | |||
![]() |
b09d284a1d | ||
5a4a1ff391 | |||
72b3d1e4af | |||
ca3af75b5a | |||
![]() |
f50d4b975d | ||
![]() |
bf3b888e71 | ||
cadd9de7a0 | |||
![]() |
ccdba6efd4 | ||
dc339fb025 | |||
![]() |
962d6ec58a | ||
![]() |
8d3f686fa1 | ||
![]() |
148f0e5244 | ||
129d52d6d6 | |||
22e4253ea9 | |||
121dfa4c49 | |||
![]() |
9bf68050a7 | ||
![]() |
615c9427b9 | ||
023cef2bf3 | |||
2426638414 | |||
d18de9e4c0 | |||
6f2721a0f2 | |||
70aaadd901 | |||
daa998c89e | |||
c2ce43d295 | |||
d19c83289d | |||
2eac2a9554 | |||
599d55b684 | |||
ea6596a5b4 | |||
![]() |
3203f48f76 | ||
4acc2b0605 | |||
![]() |
55a94cb05b | ||
ddb09d56e7 | |||
![]() |
835cb14042 | ||
474e6871e3 | |||
![]() |
13a445ef64 | ||
![]() |
ee7cdc8d10 | ||
e712d3265f | |||
11ec71cd7e | |||
7b94e05d0a | |||
bc8e6cad10 | |||
![]() |
9e55955970 | ||
![]() |
334da613fa | ||
![]() |
1593a84b34 | ||
![]() |
a340647df4 | ||
![]() |
c8054a5272 | ||
![]() |
b56d82fff1 | ||
![]() |
9e1ea6299d | ||
![]() |
78a5e8ad61 | ||
![]() |
e61ad02dc2 | ||
![]() |
bb122c5e39 | ||
![]() |
2b68c2ea8d | ||
![]() |
d52382c1dc | ||
![]() |
f9f72cf830 | ||
eea1f2c3a2 | |||
aa70fa1c8d | |||
![]() |
896baf18dd | ||
![]() |
1a961c0732 | ||
![]() |
6005cc01b7 | ||
![]() |
323b77f6dc | ||
![]() |
f572b5a6bc | ||
![]() |
733e13ff66 | ||
![]() |
f8484959d6 | ||
![]() |
cf82e1e21e | ||
![]() |
b76f114ab0 | ||
![]() |
1b519ca440 | ||
![]() |
f67232f55c | ||
![]() |
426052ba09 | ||
![]() |
85f0a5a06b | ||
cf77fc5e61 | |||
![]() |
3e426d088d | ||
![]() |
4da7ff2431 | ||
![]() |
4906d2bb4d | ||
![]() |
69b244d074 | ||
![]() |
155a86975c | ||
![]() |
5c134989d2 | ||
![]() |
3f34483fd5 | ||
![]() |
e0d5bc5739 | ||
![]() |
f4d269721a | ||
a88e7ffb87 | |||
![]() |
60e8725ac3 | ||
![]() |
c0dd9c1124 | ||
![]() |
8284b793d3 | ||
be4ea4906a | |||
![]() |
f0a1a68144 | ||
![]() |
098b23b864 | ||
![]() |
cdb8522f65 | ||
b1f1444a0c | |||
![]() |
4939dbbd83 | ||
![]() |
25d5830462 | ||
![]() |
ac13e0a3f2 | ||
![]() |
1aa112aac2 | ||
![]() |
7468ca9086 | ||
![]() |
11cd073a51 | ||
![]() |
50cdbe57e8 | ||
![]() |
a3a4ecdd33 | ||
![]() |
6a00c6db22 | ||
![]() |
401c0e888f | ||
![]() |
75401556aa | ||
![]() |
53a203b067 | ||
![]() |
33d59073e3 | ||
c06a3ed38c | |||
eda9d5ce6c | |||
![]() |
4160f72615 | ||
![]() |
498c550a15 | ||
![]() |
b733100269 | ||
![]() |
8502fb72d9 | ||
![]() |
0d5551406a | ||
![]() |
72bbaac9a6 | ||
![]() |
ee916afdfd | ||
![]() |
ece866a3ec | ||
![]() |
77bdccdf86 | ||
![]() |
c8768665e0 | ||
f2dee0359f | |||
![]() |
5b18461bd9 | ||
![]() |
b0f25de000 | ||
![]() |
509ceaeefe | ||
![]() |
bcb1e1b2c8 | ||
![]() |
aa416b7ee4 | ||
![]() |
9e554b0a65 | ||
![]() |
b2e84204ce | ||
![]() |
dd1b66bd06 | ||
![]() |
8d5e780f94 | ||
dce0620365 | |||
323ab09238 | |||
3a2ffde0ab | |||
![]() |
a9bb6df711 | ||
![]() |
0410e844b1 | ||
![]() |
2d302d0116 | ||
![]() |
e4a08f5aed | ||
![]() |
70235970ab | ||
![]() |
67aadf157f | ||
![]() |
54e515cb7a | ||
![]() |
c82fdeee96 | ||
![]() |
34e4fd6bb5 | ||
![]() |
9fb5275007 | ||
![]() |
667d7dbddb | ||
![]() |
f7f06cfa3a | ||
![]() |
1779f573ec | ||
![]() |
fba73636de | ||
![]() |
3814022411 | ||
![]() |
53b998f1e5 | ||
86d2c0e9f6 | |||
8b4e07d66e | |||
420387cdb7 | |||
763fd3f646 | |||
7975528317 | |||
![]() |
89c9a85204 | ||
2f397c88d4 | |||
![]() |
3bf776b6f7 | ||
![]() |
0ec99a8cf5 | ||
![]() |
6f532eaf05 | ||
bc7b7e2f22 | |||
![]() |
b700239e18 | ||
0200160aa8 |
190 changed files with 14274 additions and 3152 deletions
9
.directory
Normal file
9
.directory
Normal file
|
@ -0,0 +1,9 @@
|
|||
[Dolphin]
|
||||
HeaderColumnWidths=372,72,103
|
||||
SortRole=modificationtime
|
||||
Timestamp=2022,6,1,16,36,48
|
||||
Version=4
|
||||
ViewMode=1
|
||||
|
||||
[Settings]
|
||||
HiddenFilesShown=true
|
BIN
.docker-compose.yml.swp
Normal file
BIN
.docker-compose.yml.swp
Normal file
Binary file not shown.
|
@ -4,11 +4,15 @@ APP_KEY=
|
|||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
VITE_DEV_SERVER_URL=http://vite:5173
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
USERID=1000
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=db
|
||||
DB_PORT=3306
|
||||
DB_PORT_EXPOSED=3306
|
||||
DB_DATABASE=pedi2
|
||||
DB_USERNAME=pedi2
|
||||
DB_PASSWORD=pedi2
|
||||
|
@ -47,4 +51,5 @@ MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|||
|
||||
WEB_CLIENT_EMAIL=informaticamps@buzon.uy
|
||||
WEB_CLIENT_NAME=web
|
||||
WEB_CLIENT_PASS=pass
|
||||
WEB_CLIENT_PASS=pass
|
||||
NGINX_PORT=8000
|
||||
|
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -10,3 +10,11 @@ Homestead.json
|
|||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
.idea
|
||||
/resources/csv/exports/*.csv
|
||||
/resources/csv/canastas/*.csv
|
||||
/storage/csv/exports/*.csv
|
||||
/storage/csv/canastas/*.csv
|
||||
/public/css/
|
||||
/public/js/
|
||||
/public/mix-manifest.json
|
||||
|
|
11
Dockerfile
11
Dockerfile
|
@ -1,4 +1,4 @@
|
|||
FROM php:7.4-fpm
|
||||
FROM php:8.3-fpm
|
||||
|
||||
# Arguments defined in docker-compose.yml
|
||||
ARG user
|
||||
|
@ -12,13 +12,18 @@ RUN apt-get update && apt-get install -y \
|
|||
libonig-dev \
|
||||
libxml2-dev \
|
||||
zip \
|
||||
unzip
|
||||
unzip \
|
||||
libzip-dev
|
||||
|
||||
# Install node
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
||||
apt-get install -y nodejs
|
||||
|
||||
# Clear cache
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install PHP extensions
|
||||
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
|
||||
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip
|
||||
|
||||
# Get latest Composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
|
100
README.md
100
README.md
|
@ -1,14 +1,15 @@
|
|||
# Pedi2
|
||||
|
||||
Aplicación de compras del Mercado Popular de Subsistencia.
|
||||
Aplicación de pedidos del Mercado Popular de Subsistencia.
|
||||
|
||||
Pedi2 está hecha en Laravel 7 y utiliza laravel7-docker de dyarleniber.
|
||||
Pedi2 está hecha en Laravel 12 y Vue 2 con Vite y Vuex.
|
||||
|
||||
Se utilizan los siguientes servicios, separadamente:
|
||||
|
||||
- `app`, un servicio que corre PHP7.4-FPM.
|
||||
- `app`, un servicio que corre PHP8.3-FPM.
|
||||
- `db`, un servicio que corre MySQL 5.7.
|
||||
- `nginx`, un servicio que usa el servicio app para parsear código PHP antes de servir la aplicación de Laravel al usuario final.
|
||||
- `vite`, un servicio que corre el frontend de la aplicación.
|
||||
|
||||
## Pre-requisitos
|
||||
- docker
|
||||
|
@ -17,107 +18,50 @@ Se utilizan los siguientes servicios, separadamente:
|
|||
## Instalación
|
||||
1. Una vez descargado el proyecto, hacé una copia del archivo `.env.example` que se encuentra en la raíz del proyecto y nombrala `.env`. Seteá los valores correctos - específicamente, para las variables, `APP_URL`, `DB_USERNAME` y `DB_PASSWORD`. Prestá atención a que `DB_HOST` sea el nombre del servicio que corre MySQL (por defecto `DB_HOST=db`).
|
||||
|
||||
2. Construí la imagen de la app
|
||||
2. Levantá los contenedores, construyendo la imagen de la app primero:
|
||||
|
||||
```bash
|
||||
docker-compose build app
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
3. Cuando termine, levantá los contenedores:
|
||||
El ambiente ahora está andando, deberías ver los logs de cada servicio en la terminal. Falta ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
El ambiente ahora está andando, pero necesitamos ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
||||
|
||||
4. Terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`.
|
||||
3. Abrí una nueva terminal, y terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`:
|
||||
|
||||
|
||||
```bash
|
||||
docker-compose exec app composer update
|
||||
docker-compose exec app composer install
|
||||
```
|
||||
|
||||
5. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles.
|
||||
4. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles:
|
||||
|
||||
```bash
|
||||
docker-compose exec app php artisan key:generate
|
||||
```
|
||||
|
||||
6. Corré las migraciones y seeders de Laravel
|
||||
5. Corré las migraciones y seeders de Laravel:
|
||||
|
||||
```bash
|
||||
docker-compose exec app php artisan migrate --seed
|
||||
docker-compose exec app php artisan migrate:fresh --seed
|
||||
```
|
||||
|
||||
7. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
||||
6. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
||||
|
||||
7. Instala las dependencias de npm:
|
||||
```bash
|
||||
docker-compose exec app npm install
|
||||
```
|
||||
|
||||
Ahora la aplicación está corriendo y la podés ver en el puerto 8000 de tu dominio o IP. En caso de que estés en tu máquina local, la vas a ver accediendo a `http://localhost:8000` desde tu navegador.
|
||||
|
||||
Podés usar el comando `logs` para ver los logs generados por tus servicios:
|
||||
|
||||
```bash
|
||||
docker-compose logs nginx
|
||||
```
|
||||
---
|
||||
|
||||
## Services description
|
||||
|
||||
### Dockerfile
|
||||
|
||||
Although both `db` service and `nginx` service, will be based on default images obtained from the Docker Hub, the `app` service will be based on a custom image created by the `Dockerfile`.
|
||||
|
||||
The `Dockerfile` starts by defining the base image `php:7.4-fpm`.
|
||||
|
||||
After installing system packages and PHP extensions, the Composer will be installed by copying the composer executable from its latest official image.
|
||||
|
||||
A new system user is then created and set up using the `user` and `uid` arguments that were declared at the beginning of the `Dockerfile`. These values will be injected by Docker Compose at build time.
|
||||
|
||||
> This new system user is necessary to execute Laravel Artisan and Composer commands while developing the application. The `uid` setting ensures that the user inside the container has the same `uid` as your system user on your host machine. This way, any files created by these commands are replicated in the host with the correct permissions. This also means that you’ll be able to use your code editor of choice in the host machine to develop the application that is running inside containers.
|
||||
|
||||
Finally, the default working dir as `/var/www` and the newly created user are set. This will make sure you’re connecting as a regular user, and that you’re on the right directory, when running Laravel Artisan and Composer commands on the application container.
|
||||
|
||||
### PHP service
|
||||
|
||||
The `app` service will build an image called `laravel-image`, based on the `Dockerfile` previously created. The container defined by this service will run a php-fpm server to parse PHP code and send the results back to the nginx service, which will be running on a separate container. The mysql service defines a container running a MySQL 5.7 server. All these services will share a bridge network named `app-network`.
|
||||
|
||||
The application files will be synchronized on both the `app` and the `nginx` services via bind mounts. Bind mounts are useful in development environments because they allow for a performant two-way sync between host machine and containers.
|
||||
|
||||
Inside the `app` container you will be able to execute command line tasks with the Laravel Artisan and Composer.
|
||||
|
||||
The `app` service will set up a container named `laravel-app`. It builds a new Docker image based on a `Dockerfile` located in the same path as the `docker-compose.yml` file. The new image will be saved locally under the name `laravel-image`.
|
||||
|
||||
The `volumes` setting creates a shared volume that will synchronize contents from the current directory to `/var/www` inside the container. Notice that this is not your document root, since that will live in the nginx container.
|
||||
|
||||
Another file which will be synchronized is the `local.ini` file from the directory `./php/local.ini` to `/usr/local/etc/php/conf.d/local.ini` inside the container.
|
||||
|
||||
The `local.ini` is the configuration file (php.ini) that is read when PHP starts up.
|
||||
|
||||
### Nginx service
|
||||
|
||||
The `nginx` service uses a pre-built Nginx image on top of Alpine, a lightweight Linux distribution. It creates a container named `laravel-nginx`, and it uses the ports definition to create a redirection from port `8000` on the host system to port `80` inside the container.
|
||||
|
||||
The `volumes` setting creates two shared volumes. The first one will synchronize contents from the current directory to `/var/www` inside the container. This way, when you make local changes to the application files, they will be quickly reflected in the application being served by Nginx inside the container. The second volume will make sure the Nginx configuration file, located at `./nginx/conf.d/app.conf`, is copied to the container’s Nginx configuration folder. This configuration file will configure Nginx to listen on port `80` and use `index.php` as default index page. It will set the document root to `/var/www/public`, and then configure Nginx to use the `app` service on port `9000` to process all the php files.
|
||||
|
||||
### MySQL service
|
||||
|
||||
The `db` service uses a pre-built MySQL 5.7 image from Docker Hub. Because Docker Compose automatically loads `.env` variable files located in the same directory as the `docker-compose.yml` file, you can obtain the database settings from the Laravel `.env` file.
|
||||
|
||||
The `volumes` setting creates two shared volumes. The first one will make sure the MySQL configuration file, located at `./mysql/my.cnf`, is copied to the container’s MySQL configuration folder. The second volume will share a `.sql` database dump that will be used to initialize the application database. The MySQL image will automatically import `.sql` files placed in the `/docker-entrypoint-initdb.d` directory inside the container.
|
||||
|
||||
The `environment` setting defines environment variables in the new container. You can use values obtained from the Laravel `.env` file to set up the MySQL service, which will automatically create a new database and user based on the provided environment variables:
|
||||
|
||||
```bash
|
||||
DB_HOST=db
|
||||
DB_DATABASE=laravelapp
|
||||
DB_USERNAME=laravelapp_user
|
||||
DB_PASSWORD=password
|
||||
Si estás actualizando o no te anda, probá limpiar los caches:
|
||||
```
|
||||
docker-compose exec app php artisan optimize:clear
|
||||
docker-compose exec app composer dump-autoload
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- https://www.digitalocean.com/community/tutorials/how-to-install-and-set-up-laravel-with-docker-compose-on-ubuntu-20-04
|
||||
- https://docs.docker.com/
|
||||
- https://docs.docker.com/compose/
|
||||
- https://github.com/dyarleniber/laravel7-docker
|
||||
- https://laravel.com/docs/7.x/installation
|
11
app/CanastaLog.php
Normal file
11
app/CanastaLog.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CanastaLog extends Model
|
||||
{
|
||||
protected $fillable = ["path", "descripcion"];
|
||||
protected $table = "carga_de_canastas";
|
||||
}
|
72
app/Console/Commands/AgregarEsBonoAPedidosAprobados.php
Normal file
72
app/Console/Commands/AgregarEsBonoAPedidosAprobados.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AgregarEsBonoAPedidosAprobados extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:AgregarEsBonoAPedidosAprobados';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Agrega "producto_bono" a la view PedidosAprobados';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
DB::statement("
|
||||
ALTER VIEW pedidos_aprobados(
|
||||
grupo_de_compra_id,
|
||||
grupo_de_compra_nombre,
|
||||
grupo_de_compra_region,
|
||||
producto_id,
|
||||
producto_nombre,
|
||||
producto_precio,
|
||||
cantidad_pedida,
|
||||
total_por_producto,
|
||||
producto_es_bono
|
||||
) AS
|
||||
SELECT
|
||||
g.id as grupo_de_compra_id,
|
||||
g.nombre as grupo_de_compra_nombre,
|
||||
g.region as grupo_de_compra_region,
|
||||
pr.id AS producto_id,
|
||||
pr.nombre as producto_nombre,
|
||||
pr.precio as producto_precio,
|
||||
SUM(ps.cantidad) as cantidad_pedida,
|
||||
pr.precio*SUM(ps.cantidad) as total_por_producto,
|
||||
pr.bono
|
||||
FROM grupos_de_compra g
|
||||
JOIN subpedidos s ON (s.grupo_de_compra_id = g.id AND s.aprobado=1)
|
||||
JOIN producto_subpedido ps ON (ps.subpedido_id = s.id)
|
||||
JOIN productos pr ON (pr.id = ps.producto_id)
|
||||
GROUP BY
|
||||
g.id, g.nombre, pr.id, pr.nombre
|
||||
;");
|
||||
return 0;
|
||||
}
|
||||
}
|
62
app/Console/Commands/CrearPedidosAprobadosViewCommand.php
Normal file
62
app/Console/Commands/CrearPedidosAprobadosViewCommand.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CrearPedidosAprobadosViewCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'view:CrearPedidosAprobadosView';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Crea view "pedidos_aprobados"';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
DB::statement("
|
||||
CREATE OR REPLACE VIEW pedidos_aprobados
|
||||
AS
|
||||
SELECT
|
||||
g.id as grupo_de_compra_id,
|
||||
g.nombre as grupo_de_compra_nombre,
|
||||
g.region as grupo_de_compra_region,
|
||||
pr.id AS producto_id,
|
||||
pr.nombre as producto_nombre,
|
||||
pr.precio as producto_precio,
|
||||
SUM(ps.cantidad) as cantidad_pedida,
|
||||
pr.precio*SUM(ps.cantidad) as total_por_producto
|
||||
FROM grupos_de_compra g
|
||||
JOIN subpedidos s ON (s.grupo_de_compra_id = g.id AND s.aprobado=1)
|
||||
JOIN producto_subpedido ps ON (ps.subpedido_id = s.id)
|
||||
JOIN productos pr ON (pr.id = ps.producto_id)
|
||||
GROUP BY
|
||||
g.id, g.nombre, pr.id, pr.nombre
|
||||
;");
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -5,12 +5,14 @@ namespace App\Filtros;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Throwable;
|
||||
use TypeError;
|
||||
|
||||
class Filtro extends Model
|
||||
{
|
||||
protected $request;
|
||||
protected $builder;
|
||||
protected $MENSAJES_ERROR = [
|
||||
protected Request $request;
|
||||
protected array $MENSAJES_ERROR = [
|
||||
'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
|
||||
];
|
||||
|
||||
|
@ -22,10 +24,10 @@ class Filtro extends Model
|
|||
/**
|
||||
* Apply all existing filters, if available.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
* @param Builder $builder
|
||||
* @return Builder
|
||||
*/
|
||||
public function aplicar(Builder $builder)
|
||||
public function aplicar(Builder $builder): Builder
|
||||
{
|
||||
$this->builder = $builder;
|
||||
|
||||
|
@ -43,17 +45,24 @@ class Filtro extends Model
|
|||
//Obtener nombre del método (snake_case a camelCase)
|
||||
$metodo = str_replace('_', '', lcfirst(ucwords($filtro, '_')));
|
||||
|
||||
if(!method_exists($this, $metodo)) { continue; }
|
||||
if (!method_exists($this, $metodo))
|
||||
continue;
|
||||
|
||||
//Llamar métodos sin argumentos
|
||||
if ($valor === null|| (is_a($valor,'String') && trim($valor)=='')){ $this->$metodo(); continue; }
|
||||
|
||||
if ($valor === null || (is_a($valor,'String') && trim($valor)=='')) {
|
||||
$this->$metodo();
|
||||
continue;
|
||||
}
|
||||
|
||||
//Llamar métodos con argumentos
|
||||
try {
|
||||
$this->$metodo($valor);
|
||||
} catch (\Throwable $th) {
|
||||
if (is_a($th,'TypeError') ) { throw new HttpException(400, sprintf($this->MENSAJES_ERROR['ARGUMENTO'],$filtro)); }
|
||||
throw $th;
|
||||
} catch (Throwable $error) {
|
||||
if (is_a($error,'TypeError')) {
|
||||
$mensaje = sprintf($this->MENSAJES_ERROR['ARGUMENTO'], $filtro);
|
||||
throw new HttpException(400, $mensaje);
|
||||
}
|
||||
throw $error;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,12 +72,16 @@ class Filtro extends Model
|
|||
//Buscar un término en el nombre
|
||||
public function nombre(String $valor)
|
||||
{
|
||||
$this->builder->where('nombre', "LIKE", "%" . $valor . "%")->orderByRaw("IF(nombre = '{$valor}',2,IF(nombre LIKE '{$valor}%',1,0)) DESC");
|
||||
$this->builder
|
||||
->where('nombre', "LIKE", "%" . $valor . "%")
|
||||
->orderByRaw("IF(nombre = '$valor',2,IF(nombre LIKE '$valor%',1,0)) DESC");
|
||||
}
|
||||
|
||||
public function alfabetico(String $order = 'asc')
|
||||
{
|
||||
if(!in_array($order,['asc','desc'])) { throw new TypeError(); }
|
||||
if (!in_array($order,['asc','desc']))
|
||||
throw new TypeError();
|
||||
|
||||
$this->builder->orderBy('nombre', $order);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Filtros;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class FiltroDeProducto extends Filtro {
|
||||
|
||||
|
@ -10,4 +9,4 @@ class FiltroDeProducto extends Filtro {
|
|||
$this->builder->where('categoria', $valor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,23 @@
|
|||
|
||||
namespace App\Filtros;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use TypeError;
|
||||
|
||||
class FiltroDeSubpedido extends Filtro
|
||||
{
|
||||
public function grupoDeCompra(String $valor)
|
||||
{
|
||||
if (!is_numeric($valor)) { throw new TypeError();}
|
||||
if (!is_numeric($valor))
|
||||
throw new TypeError();
|
||||
|
||||
$this->builder->where('grupo_de_compra_id', intval($valor));
|
||||
}
|
||||
|
||||
public function tipoPedido(String $valor)
|
||||
{
|
||||
if (!is_numeric($valor))
|
||||
throw new TypeError();
|
||||
|
||||
$this->builder->where('tipo_pedido_id', intval($valor));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,207 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use App\Helpers\CsvHelper;
|
||||
use App\Helpers\PdfHelper;
|
||||
use App\Helpers\TransporteHelper;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Csv\Exception;
|
||||
use Mpdf\MpdfException;
|
||||
|
||||
class GrupoDeCompra extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $fillable = [ "nombre","region","telefono","correo","referente_finanzas","cantidad_de_nucleos"];
|
||||
protected $table = 'grupos_de_compra';
|
||||
protected $hidden = ['password'];
|
||||
protected $fillable = ["nombre", "region", "devoluciones_habilitadas", "saldo"];
|
||||
protected $table = 'grupos_de_compra';
|
||||
|
||||
public function subpedidos() {
|
||||
return $this->hasMany('App\Subpedido');
|
||||
}
|
||||
|
||||
public function subpedidos(): HasMany
|
||||
{
|
||||
return $this->hasMany(Subpedido::class);
|
||||
}
|
||||
|
||||
public function users(): HasMany
|
||||
{
|
||||
return $this->hasMany(User::class);
|
||||
}
|
||||
|
||||
public function toggleDevoluciones(): bool
|
||||
{
|
||||
$this->devoluciones_habilitadas = !$this->devoluciones_habilitadas;
|
||||
$this->save();
|
||||
return $this->devoluciones_habilitadas;
|
||||
}
|
||||
|
||||
public function pedidosAprobados()
|
||||
{
|
||||
return $this->pedidosHogares()
|
||||
->where('aprobado', 1);
|
||||
}
|
||||
|
||||
public function pedidosHogares()
|
||||
{
|
||||
return $this->subpedidos
|
||||
->where('tipo_pedido_id', '=', 1);
|
||||
}
|
||||
|
||||
public function totalARecaudar()
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->total();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalSinDevoluciones() {
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->totalSinDevoluciones();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalBarrial()
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->totalBarrial();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalDevoluciones()
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->devoluciones_total;
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalDePedido()
|
||||
{
|
||||
return $this->totalCentralesQueNoPaganTransporte()
|
||||
+ $this->totalCentralesQuePaganTransporte()
|
||||
+ $this->totalTransporte()
|
||||
;
|
||||
}
|
||||
|
||||
public function totalATransferir()
|
||||
{
|
||||
return $this->totalDePedido() - $this->saldo;
|
||||
}
|
||||
|
||||
public function totalCentralesQueNoPaganTransporte()
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->totalCentralesQueNoPaganTransporte();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalCentralesQuePaganTransporte()
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->totalCentralesQuePaganTransporte();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalTransporte()
|
||||
{
|
||||
return TransporteHelper::totalTransporte($this->totalCentralesQuePaganTransporte());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* Calcula la cantidad de bonos de transporte del barrio
|
||||
*/
|
||||
public function cantidadTransporte(): int
|
||||
{
|
||||
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MpdfException
|
||||
*/
|
||||
public function exportarPedidosAPdf()
|
||||
{
|
||||
$fecha = now()->format('Y-m-d');
|
||||
$filepath = $this->nombre . '-' . $fecha . '.pdf';
|
||||
$pedidoOllas = $this->subpedidos
|
||||
->where('tipo_pedido_id', '=', TipoPedido::firstOrCreate(['nombre' => 'olla'])->id);
|
||||
$pedidos = $this->pedidosAprobados()->concat($pedidoOllas);
|
||||
PdfHelper::exportarPedidos($filepath, $pedidos);
|
||||
}
|
||||
|
||||
function pedidoParaPdf(): array
|
||||
{
|
||||
$productos = $this->productosPedidos(true, 'producto_id');
|
||||
$pedido = [];
|
||||
$pedido['productos'] = [];
|
||||
|
||||
$pedido['nombre'] = $this->nombre;
|
||||
foreach ($productos as $producto) {
|
||||
$productoParaPdf = [];
|
||||
$productoParaPdf['pivot'] = [];
|
||||
$productoParaPdf['nombre'] = $producto->producto_nombre;
|
||||
$productoParaPdf['pivot']['cantidad'] = $producto->cantidad_pedida;
|
||||
$productoParaPdf['pivot']['notas'] = false;
|
||||
$productoParaPdf['bono'] = $producto->producto_es_bono;
|
||||
|
||||
$pedido['productos'][] = $productoParaPdf;
|
||||
}
|
||||
|
||||
return $pedido;
|
||||
}
|
||||
|
||||
public function generarHTML()
|
||||
{
|
||||
$view = view("pdfgen.pedido_tabla", ["pedido" => $this->pedidoParaPdf()]);
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MpdfException
|
||||
*/
|
||||
public static function exportarPedidosBarrialesAPdf()
|
||||
{
|
||||
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
||||
$fecha = now()->format('Y-m-d');
|
||||
$filepath = 'pedidos_por_barrio-' . $fecha . '.pdf';
|
||||
PdfHelper::exportarPedidos($filepath, $barrios);
|
||||
}
|
||||
|
||||
public static function barriosMenosPrueba(): Builder
|
||||
{
|
||||
return self::where('nombre', '<>', 'PRUEBA')
|
||||
->orderBy('region')
|
||||
->orderBy('nombre');
|
||||
}
|
||||
|
||||
public function productosPedidos($excluirBonos = false, $orderBy = 'producto_nombre'): Collection
|
||||
{
|
||||
$query = DB::table('pedidos_aprobados')
|
||||
->where('grupo_de_compra_id', $this->id)
|
||||
->where('producto_nombre','NOT LIKE','%barrial%');
|
||||
|
||||
if ($excluirBonos)
|
||||
$query = $query->where('producto_es_bono',false);
|
||||
|
||||
return $query
|
||||
->orderBy($orderBy)
|
||||
->get()
|
||||
->keyBy('producto_id');
|
||||
}
|
||||
|
||||
public function setSaldo(float $saldo) {
|
||||
$this->saldo = $saldo;
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
|
144
app/Helpers/CanastaHelper.php
Normal file
144
app/Helpers/CanastaHelper.php
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Producto;
|
||||
use App\CanastaLog;
|
||||
use DatabaseSeeder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Csv\Exception;
|
||||
|
||||
class CanastaHelper
|
||||
{
|
||||
const TIPO = "Tipo";
|
||||
const PRODUCTO = 'Producto';
|
||||
const PRECIO = 'Precio';
|
||||
const REGEX_BONO = "/^[BF]/i";
|
||||
const ARCHIVO_SUBIDO = 'Archivo subido';
|
||||
const CANASTA_CARGADA = 'Canasta cargada';
|
||||
const PRODUCTO_TALLE_COLOR = "PTC";
|
||||
|
||||
public static function canastaActual() {
|
||||
$result = [];
|
||||
$log = CanastaLog::where('descripcion', self::CANASTA_CARGADA)
|
||||
->orderBy('created_at', 'desc')
|
||||
->first();
|
||||
$nombre = str_replace(storage_path(), "", $log->path);
|
||||
$nombre = str_replace("/csv/canastas/", "", $nombre);
|
||||
$result["nombre"] = str_replace(".csv", "", $nombre);
|
||||
$result["fecha"] = $log->created_at;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function guardarCanasta($data, $path): string {
|
||||
if (!File::exists(storage_path('csv/canastas'))) {
|
||||
File::makeDirectory(storage_path('csv/canastas'), 0755, true);
|
||||
}
|
||||
|
||||
$nombre = $data->getClientOriginalName();
|
||||
|
||||
$storage_path = storage_path($path);
|
||||
$data->move($storage_path, $nombre);
|
||||
|
||||
self::log($storage_path . $nombre, self::ARCHIVO_SUBIDO);
|
||||
|
||||
return $nombre;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cargarCanasta($archivo) {
|
||||
self::limpiarTablas();
|
||||
|
||||
$registros = CsvHelper::getRecords($archivo, "No se pudo leer el archivo.");
|
||||
|
||||
$toInsert = [];
|
||||
$categoria = '';
|
||||
|
||||
foreach($registros as $i => $registro) {
|
||||
// saltear bono de transporte y filas que no tienen tipo
|
||||
if (self::noTieneTipo($registro) || $registro[self::TIPO] == "T")
|
||||
continue;
|
||||
|
||||
// obtener categoria si no hay producto
|
||||
if ($registro[self::PRODUCTO] == '') {
|
||||
// no es la pregunta de la copa?
|
||||
if (!Str::contains($registro[self::TIPO],"¿"))
|
||||
$categoria = $registro[self::TIPO];
|
||||
continue; // saltear si es la pregunta de la copa
|
||||
}
|
||||
|
||||
// completar producto
|
||||
$toInsert[] = DatabaseSeeder::addTimestamps([
|
||||
'fila' => $i,
|
||||
'categoria' => $categoria,
|
||||
'nombre' => trim(str_replace('*', '',$registro[self::PRODUCTO])),
|
||||
'precio' => $registro[self::PRECIO],
|
||||
'es_solidario' => Str::contains($registro[self::PRODUCTO],"*"),
|
||||
'bono' => preg_match(self::REGEX_BONO, $registro[self::TIPO]),
|
||||
'requiere_notas'=> $registro[self::TIPO] == self::PRODUCTO_TALLE_COLOR,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
Producto::insert($chunk);
|
||||
|
||||
self::agregarBonoBarrial();
|
||||
|
||||
self::log($archivo, self::CANASTA_CARGADA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $descripcion
|
||||
* @return void
|
||||
*/
|
||||
private static function log($path, $descripcion): void
|
||||
{
|
||||
$log = new CanastaLog([
|
||||
'path' => $path,
|
||||
'descripcion' => $descripcion,
|
||||
]);
|
||||
$log->save();
|
||||
}
|
||||
|
||||
private static function limpiarTablas()
|
||||
{
|
||||
DB::delete('delete from producto_subpedido');
|
||||
DB::delete('delete from productos');
|
||||
DB::delete('delete from subpedidos');
|
||||
}
|
||||
|
||||
private static function agregarBonoBarrial()
|
||||
{
|
||||
$categoria = Producto::all()
|
||||
->pluck('categoria')
|
||||
->unique()
|
||||
->flatten()
|
||||
->first(function ($c) {
|
||||
return Str::contains($c, 'BONO');
|
||||
});
|
||||
|
||||
Producto::create([
|
||||
'nombre' => "Bono barrial",
|
||||
'precio' => 20,
|
||||
'categoria' => $categoria,
|
||||
'bono' => 1,
|
||||
'es_solidario' => 0,
|
||||
'requiere_notas'=> false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $registro
|
||||
* @return bool
|
||||
*/
|
||||
public static function noTieneTipo($registro): bool
|
||||
{
|
||||
return !Arr::has($registro, self::TIPO) || trim($registro[self::TIPO]) == '';
|
||||
}
|
||||
}
|
101
app/Helpers/CsvHelper.php
Normal file
101
app/Helpers/CsvHelper.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Http\Controllers\ComisionesController;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Iterator;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use League\Csv\Exception;
|
||||
use League\Csv\InvalidArgument;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Writer;
|
||||
|
||||
class CsvHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getRecords($filePath, $message): Iterator {
|
||||
try {
|
||||
$csv = self::getReader($filePath);
|
||||
return $csv->getRecords();
|
||||
} catch (InvalidArgument|Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
throw new Exception($message, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cambiarParametro(string $id, string $valor): void
|
||||
{
|
||||
try {
|
||||
$updated = false;
|
||||
$filePath = resource_path(ComisionesController::PARAMETROS_PATH);
|
||||
$csv = self::getReader($filePath);
|
||||
$headers = $csv->getHeader();
|
||||
$records = array_map(fn($r) => (array) $r, iterator_to_array($csv->getRecords()));
|
||||
|
||||
foreach ($records as &$record) {
|
||||
if ($record['id'] === $id) {
|
||||
$record['valor'] = $valor;
|
||||
$updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset($record);
|
||||
|
||||
if (!$updated)
|
||||
throw new Exception("Parametro '{$id}' no encontrado.");
|
||||
|
||||
self::generarCsv($filePath, $records, $headers, "|", "'", false);
|
||||
} catch (CannotInsertRecord | InvalidArgument $e) {
|
||||
Log::error("Error al actualizar csv: " . $e->getMessage());
|
||||
throw new Exception("Error al actualizar csv", $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
*/
|
||||
public static function generarCsv($filePath, $contenido, $headers = null, $delimiter = null, $enclosure = null, $export = true): void
|
||||
{
|
||||
$path = $filePath;
|
||||
|
||||
if ($export) {
|
||||
if (!File::exists(storage_path('csv/exports')))
|
||||
File::makeDirectory(storage_path('csv/exports'), 0755, true);
|
||||
$path = storage_path($filePath);
|
||||
}
|
||||
|
||||
$writer = Writer::createFromPath($path, 'w');
|
||||
if ($delimiter)
|
||||
$writer->setDelimiter($delimiter);
|
||||
if ($enclosure)
|
||||
$writer->setEnclosure($enclosure);
|
||||
if ($headers)
|
||||
$writer->insertOne($headers);
|
||||
|
||||
$writer->insertAll($contenido);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filePath
|
||||
* @return Reader
|
||||
* @throws InvalidArgument
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function getReader(string $filePath): Reader
|
||||
{
|
||||
$csv = Reader::createFromPath($filePath);
|
||||
$csv->setDelimiter("|");
|
||||
$csv->setEnclosure("'");
|
||||
$csv->setHeaderOffset(0);
|
||||
return $csv;
|
||||
}
|
||||
}
|
29
app/Helpers/PdfHelper.php
Normal file
29
app/Helpers/PdfHelper.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Mpdf\Mpdf;
|
||||
use Mpdf\MpdfException;
|
||||
|
||||
class PdfHelper
|
||||
{
|
||||
/**
|
||||
* Requiere que el segundo argumento tenga definida la función generarHTML()
|
||||
* para crear la tabla con los datos del pedido que se inserta en el pdf.
|
||||
*
|
||||
* @return void
|
||||
* @throws MpdfException
|
||||
*/
|
||||
public static function exportarPedidos($filepath, $pedidos)
|
||||
{
|
||||
$mpdf = new Mpdf();
|
||||
|
||||
foreach ($pedidos as $pedido) {
|
||||
$html = $pedido->generarHTML();
|
||||
$mpdf->WriteHTML($html);
|
||||
$mpdf->AddPage();
|
||||
}
|
||||
|
||||
$mpdf->Output($filepath, 'D');
|
||||
}
|
||||
}
|
258
app/Helpers/PedidosExportHelper.php
Normal file
258
app/Helpers/PedidosExportHelper.php
Normal file
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\TipoPedido;
|
||||
use Closure;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use League\Csv\Exception;
|
||||
use League\Csv\InvalidArgument;
|
||||
|
||||
class PedidosExportHelper
|
||||
{
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
static public function pedidosBarriales()
|
||||
{
|
||||
$filePath = "csv/exports/pedidos-por-barrio-" . now()->format('Y-m-d') . ".csv";
|
||||
$barrios = GrupoDeCompra::barriosMenosPrueba()->get();
|
||||
self::exportarCSV(
|
||||
$filePath,
|
||||
$barrios,
|
||||
self::generarContenidoCSV(
|
||||
$barrios,
|
||||
fn ($grupoId) =>
|
||||
"subpedidos.grupo_de_compra_id = $grupoId
|
||||
AND subpedidos.aprobado = 1
|
||||
AND subpedidos.tipo_pedido_id = 1"
|
||||
)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
static public function pedidosDeOllas()
|
||||
{
|
||||
$filePath = "csv/exports/pedidos-de-ollas-" . now()->format('Y-m-d') . ".csv";
|
||||
$barrios = GrupoDeCompra::barriosMenosPrueba()
|
||||
->whereHas('subpedidos', function ($query) {
|
||||
$tipo_olla = self::getTipoId('olla');
|
||||
$query->where('tipo_pedido_id', $tipo_olla);
|
||||
})
|
||||
->get();
|
||||
|
||||
$contenido = self::generarContenidoCSV($barrios,
|
||||
fn($grupoId) => "subpedidos.grupo_de_compra_id = $grupoId
|
||||
AND subpedidos.tipo_pedido_id = 2");
|
||||
$ollas = self::cantidadDeOllasParaCSV($barrios, $contenido);
|
||||
|
||||
self::exportarCSV(
|
||||
$filePath,
|
||||
$barrios,
|
||||
$contenido->concat([$ollas])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cantidadDeOllasParaCSV(Collection $barrios, Collection $contenido)
|
||||
{
|
||||
$tipo_olla = self::getTipoId('olla');
|
||||
|
||||
$parametros = collect(CsvHelper::getRecords(resource_path("csv/parametros.csv"), "No se pudo leer el archivo."));
|
||||
$fila = [
|
||||
"producto" => "Cantidad de ollas",
|
||||
"precio" => $parametros->where('id','monto-olla')->pluck('valor')->first(),
|
||||
"paga_transporte" => false,
|
||||
"fila" => $contenido->last()->fila + 1,
|
||||
];
|
||||
|
||||
foreach ($barrios as $barrio) {
|
||||
$pedido = $barrio->subpedidos()->where('tipo_pedido_id', $tipo_olla)->first();
|
||||
$fila[$barrio->nombre] = $pedido->cantidad_ollas;
|
||||
}
|
||||
|
||||
return (object) $fila;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
static public function pedidoTotalDeBarrio(GrupoDeCompra $grupo)
|
||||
{
|
||||
$filePath = "csv/exports/" . $grupo->nombre . "-" . now()->format('Y-m-d') . ".csv";
|
||||
|
||||
$falsoBarrio = new GrupoDeCompra(['nombre' => 'Total']);
|
||||
$falsoBarrio->id = $grupo->id;
|
||||
$header = collect([$falsoBarrio]);
|
||||
|
||||
self::exportarCSV(
|
||||
$filePath,
|
||||
$header,
|
||||
self::generarContenidoCSV(
|
||||
$header,
|
||||
fn($grupoId) => "subpedidos.grupo_de_compra_id = $grupoId
|
||||
AND subpedidos.aprobado = 1"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
static public function pedidosDeBarrio(GrupoDeCompra $grupo)
|
||||
{
|
||||
$filePath = "csv/exports/" . $grupo->nombre . "-completo-" . now()->format('Y-m-d') . ".csv";
|
||||
$subpedidos = $grupo->subpedidos()->where('aprobado', true)->get();
|
||||
self::exportarCSV(
|
||||
$filePath,
|
||||
$subpedidos,
|
||||
self::generarContenidoCSV(
|
||||
$subpedidos,
|
||||
fn ($subpedidoId) => "subpedidos.id = $subpedidoId",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function exportarCSV(
|
||||
string $filename,
|
||||
Collection $headers,
|
||||
Collection $contenido
|
||||
): void {
|
||||
$nombresColumnas = $headers->pluck('nombre')->toArray();
|
||||
$columnas = array_merge(['Producto'], $nombresColumnas);
|
||||
$filaTransporte = TransporteHelper::filaTransporte();
|
||||
$planilla = [];
|
||||
$ultimaFila = 1;
|
||||
|
||||
foreach ($contenido as $fila) {
|
||||
$filaActual = $fila->fila;
|
||||
while ($filaActual - $ultimaFila > 1) {
|
||||
$ultimaFila++;
|
||||
$planilla[$ultimaFila] = [$ultimaFila === $filaTransporte ? 'Bono de transporte' : '---'];
|
||||
}
|
||||
$planilla[$filaActual] = [$fila->producto];
|
||||
foreach ($nombresColumnas as $nombre)
|
||||
$planilla[$filaActual][] = $fila->$nombre ?? 0;
|
||||
|
||||
$ultimaFila = $filaActual;
|
||||
}
|
||||
|
||||
$planilla[$filaTransporte] = array_merge(['Bono de transporte'], self::cantidadesTransporte($nombresColumnas, $contenido));
|
||||
|
||||
ksort($planilla);
|
||||
CsvHelper::generarCsv($filename, $planilla, $columnas);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $headers
|
||||
* @param Closure $filtroCallback
|
||||
* <br>
|
||||
* Ejemplo de uso:
|
||||
* ``
|
||||
* PedidosExportHelper::generarContenidoCSV(GrupoDeCompra::barriosMenosPrueba(),
|
||||
* fn($gdc_id) => "subpedidos.grupo_de_compra_id = $gdc_id");
|
||||
* ``
|
||||
* @return Collection
|
||||
* Los elementos son de la forma
|
||||
* {
|
||||
* fila: int (fila del producto),
|
||||
* producto: string (nombre del producto),
|
||||
* precio: float (precio del producto),
|
||||
* paga_transporte: bool (1 o 0, calculado a partir de bono y categoria),
|
||||
* barrio_1: string (cantidad pedida por barrio_1),
|
||||
* ...
|
||||
* barrio_n: string (cantidad pedida por barrio_n)
|
||||
* }
|
||||
*/
|
||||
public static function generarContenidoCSV(
|
||||
Collection $headers,
|
||||
Closure $filtroCallback
|
||||
): Collection {
|
||||
$expresionesColumnas = $headers->map(function ($header) use ($filtroCallback) {
|
||||
$id = $header['id'];
|
||||
$nombre = $header['nombre'];
|
||||
$filtro = $filtroCallback($id);
|
||||
return DB::raw("
|
||||
SUM(CASE WHEN $filtro THEN producto_subpedido.cantidad ELSE 0 END) as `$nombre`
|
||||
");
|
||||
})->toArray();
|
||||
|
||||
$query = DB::table('productos')
|
||||
->where('productos.nombre', 'not like', '%barrial%')
|
||||
->leftJoin('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
|
||||
->leftJoin('subpedidos', 'subpedidos.id', '=', 'producto_subpedido.subpedido_id');
|
||||
|
||||
$columnasProducto = [
|
||||
'productos.fila as fila',
|
||||
'productos.nombre as producto',
|
||||
'productos.precio as precio',
|
||||
self::pagaTransporte(),
|
||||
];
|
||||
|
||||
return $query->select(array_merge(
|
||||
$columnasProducto,
|
||||
$expresionesColumnas
|
||||
))->groupBy('productos.fila', 'productos.id', 'productos.nombre')
|
||||
->orderBy('productos.fila')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expression
|
||||
*/
|
||||
public static function pagaTransporte(): Expression
|
||||
{
|
||||
return DB::raw('CASE WHEN productos.bono OR productos.categoria LIKE "%SUBSIDIADO%" THEN 0 ELSE 1 END as paga_transporte');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $nombresColumnas
|
||||
* @param Collection $contenido
|
||||
* @return array
|
||||
*/
|
||||
public static function cantidadesTransporte(array $nombresColumnas, Collection $contenido): array
|
||||
{
|
||||
$transporte = [];
|
||||
foreach ($nombresColumnas as $nombre) {
|
||||
$suma = 0;
|
||||
foreach ($contenido as $fila) {
|
||||
if ($fila->paga_transporte) {
|
||||
$cantidad = $fila->$nombre ?? 0;
|
||||
$precio = $fila->precio ?? 0;
|
||||
$suma += $cantidad * $precio;
|
||||
}
|
||||
}
|
||||
$transporte[] = TransporteHelper::cantidadTransporte($suma);
|
||||
}
|
||||
return $transporte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getTipoId(string $tipo)
|
||||
{
|
||||
$tipo_olla = TipoPedido::where('nombre', $tipo)->first()->id;
|
||||
return $tipo_olla;
|
||||
}
|
||||
}
|
76
app/Helpers/TransporteHelper.php
Normal file
76
app/Helpers/TransporteHelper.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\CanastaLog;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use InvalidArgumentException;
|
||||
use League\Csv\Exception;
|
||||
|
||||
class TransporteHelper
|
||||
{
|
||||
private const COSTO_TRANSPORTE = "bono-transporte";
|
||||
private const MONTO_TRANSPORTE = "monto-transporte";
|
||||
private static ?array $parametros = null;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function cantidadTransporte($monto)
|
||||
{
|
||||
return ceil($monto / self::getParametro(self::MONTO_TRANSPORTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function totalTransporte($monto)
|
||||
{
|
||||
return self::cantidadTransporte($monto) * self::getParametro(self::COSTO_TRANSPORTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function filaTransporte()
|
||||
{
|
||||
$ultimaCanasta = CanastaLog::where('descripcion', CanastaHelper::CANASTA_CARGADA)
|
||||
->orderBy('created_at', 'desc')
|
||||
->pluck('path')
|
||||
->first();
|
||||
|
||||
$registros = CsvHelper::getRecords($ultimaCanasta, "No se encontró la ultima canasta.");
|
||||
$error = 'No hay fila de tipo T en la planilla: ' . $ultimaCanasta;
|
||||
|
||||
foreach ($registros as $key => $registro)
|
||||
if ($registro[CanastaHelper::TIPO] == 'T')
|
||||
return $key;
|
||||
|
||||
Log::error($error);
|
||||
throw new Exception($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getParametro(string $id): int
|
||||
{
|
||||
if (self::$parametros === null) {
|
||||
$records = CsvHelper::getRecords(resource_path('csv/parametros.csv'), "No se pudo leer el archivo.");
|
||||
self::$parametros = [];
|
||||
foreach ($records as $row) {
|
||||
self::$parametros[$row['id']] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset(self::$parametros[$id])) {
|
||||
throw new InvalidArgumentException("Parámetro '$id' no encontrado.");
|
||||
}
|
||||
|
||||
return (int) self::$parametros[$id]['valor'];
|
||||
}
|
||||
|
||||
public static function resetParametros(): void {
|
||||
self::$parametros = null;
|
||||
}
|
||||
}
|
|
@ -2,9 +2,62 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\GrupoDeCompra;
|
||||
use App\Helpers\PedidosExportHelper;
|
||||
use League\Csv\Exception;
|
||||
use Mpdf\MpdfException;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
//
|
||||
public function show()
|
||||
{
|
||||
return view('auth/login');
|
||||
}
|
||||
|
||||
public function index() {
|
||||
return view('auth/admin_subpedidos');
|
||||
}
|
||||
|
||||
public function exportarPedidosAPdf(GrupoDeCompra $gdc) {
|
||||
try {
|
||||
$gdc->exportarPedidosAPdf();
|
||||
return response();
|
||||
} catch (MpdfException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function exportarPedidoACSV(GrupoDeCompra $gdc)
|
||||
{
|
||||
try {
|
||||
PedidosExportHelper::pedidoTotalDeBarrio($gdc);
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()]);
|
||||
}
|
||||
$pattern = storage_path('csv/exports/'. $gdc->nombre . '-*.csv');
|
||||
$files = glob($pattern);
|
||||
|
||||
usort($files, function ($a, $b) {
|
||||
return filemtime($b) <=> filemtime($a);
|
||||
});
|
||||
|
||||
return response()->download($files[0]);
|
||||
}
|
||||
|
||||
public function exportarPedidoConNucleosACSV(GrupoDeCompra $gdc)
|
||||
{
|
||||
try {
|
||||
PedidosExportHelper::pedidosDeBarrio($gdc);
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()]);
|
||||
}
|
||||
$pattern = storage_path('csv/exports/'.$gdc->nombre.'-completo-*.csv');
|
||||
$files = glob($pattern);
|
||||
|
||||
usort($files, function ($a, $b) {
|
||||
return filemtime($b) <=> filemtime($a);
|
||||
});
|
||||
|
||||
return response()->download($files[0]);
|
||||
}
|
||||
}
|
||||
|
|
13
app/Http/Controllers/Api/CanastaController.php
Normal file
13
app/Http/Controllers/Api/CanastaController.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\CanastaHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class CanastaController extends Controller
|
||||
{
|
||||
public function canastaActual() {
|
||||
return response()->json(CanastaHelper::canastaActual());
|
||||
}
|
||||
}
|
48
app/Http/Controllers/Api/GrupoDeCompraController.php
Normal file
48
app/Http/Controllers/Api/GrupoDeCompraController.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\GrupoDeCompraComisionesResource;
|
||||
use App\Http\Resources\GrupoDeCompraResource;
|
||||
|
||||
class GrupoDeCompraController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return GrupoDeCompraResource::collection(GrupoDeCompra::all());
|
||||
}
|
||||
public function show(GrupoDeCompra $grupoDeCompra)
|
||||
{
|
||||
return new GrupoDeCompraResource($grupoDeCompra);
|
||||
}
|
||||
public function regiones()
|
||||
{
|
||||
return GrupoDeCompra::all()->pluck('region')->unique()->flatten();
|
||||
}
|
||||
|
||||
public function region(string $region)
|
||||
{
|
||||
return GrupoDeCompra::where('region', $region)->get();
|
||||
}
|
||||
|
||||
public function toggleDevoluciones(int $gdc) {
|
||||
GrupoDeCompra::find($gdc)->toggleDevoluciones();
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function setSaldo(int $gdc) {
|
||||
$valid = request()->validate([
|
||||
'saldo' => ['required', 'min:0'],
|
||||
]);
|
||||
$grupoDeCompra = GrupoDeCompra::find($gdc);
|
||||
$grupoDeCompra->setSaldo($valid['saldo']);
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function saldos()
|
||||
{
|
||||
return GrupoDeCompraComisionesResource::collection(GrupoDeCompra::all());
|
||||
}
|
||||
}
|
|
@ -2,35 +2,21 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Filtros\FiltroDeProducto;
|
||||
use App\Http\Resources\ProductoResource;
|
||||
use App\Producto;
|
||||
|
||||
class ProductoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mostrar una lista de productos.
|
||||
*
|
||||
* @param App\Filtros\FiltroDeProducto $filtros
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(FiltroDeProducto $filtros, Request $request)
|
||||
{
|
||||
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Producto $producto
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Producto $producto)
|
||||
public function categorias()
|
||||
{
|
||||
return new ProductoResource($producto);
|
||||
return Producto::all()->pluck('categoria')->unique()->flatten();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,54 +3,108 @@
|
|||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Producto;
|
||||
use App\TipoPedido;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Filtros\FiltroDeSubpedido;
|
||||
use App\Subpedido;
|
||||
use App\GrupoDeCompra;
|
||||
use App\Http\Resources\SubpedidoResource;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
|
||||
class SubpedidoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mostrar una lista de productos.
|
||||
*
|
||||
* @param App\Filtros\FiltroDeSubpedido $filtros
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(FiltroDeSubpedido $filtros, Request $request)
|
||||
{
|
||||
return Subpedido::filtrar($filtros)->get();
|
||||
return Subpedido::filtrar($filtros)->select('id','nombre')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function indexResources(FiltroDeSubpedido $filtros, Request $request)
|
||||
{
|
||||
return SubpedidoResource::collection(Subpedido::filtrar($filtros)->get());
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validado = $this->validateSubpedido();
|
||||
if (Subpedido::where("nombre",$validado["nombre"])->where("grupo_de_compra_id",$validado["grupo_de_compra_id"])->get()->count()) {
|
||||
throw new HttpException(400, "Ya existe un subpedido con este nombre");
|
||||
}
|
||||
$s = new Subpedido();
|
||||
$s->nombre = $validado["nombre"];
|
||||
$s->grupo_de_compra_id = $validado["grupo_de_compra_id"];
|
||||
$s->save();
|
||||
return $s;
|
||||
|
||||
if (Subpedido::where([
|
||||
"nombre" => $validado["nombre"],
|
||||
"tipo_pedido_id" => $validado["tipo_id"],
|
||||
"grupo_de_compra_id" => $validado["grupo_de_compra_id"]])
|
||||
->get()
|
||||
->count())
|
||||
throw new HttpException(400, "Ya existe un pedido con este nombre");
|
||||
|
||||
$pedido = new Subpedido();
|
||||
$pedido->nombre = $validado["nombre"];
|
||||
$pedido->grupo_de_compra_id = $validado["grupo_de_compra_id"];
|
||||
$pedido->tipo_pedido_id = $validado["tipo_id"];
|
||||
$pedido->save();
|
||||
|
||||
return $this->show($pedido);
|
||||
}
|
||||
|
||||
protected function validateSubpedido(){
|
||||
protected function validateSubpedido(): array
|
||||
{
|
||||
return request()->validate([
|
||||
'nombre' => 'required|max:255',
|
||||
'grupo_de_compra_id' => [
|
||||
'required',
|
||||
Rule::in(GrupoDeCompra::all()->pluck('id')),
|
||||
]
|
||||
],
|
||||
'tipo_id' => [
|
||||
'required',
|
||||
Rule::in(TipoPedido::all()->pluck('id')),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(Subpedido $subpedido)
|
||||
{
|
||||
return new SubpedidoResource($subpedido);
|
||||
}
|
||||
|
||||
// recibe request, saca producto y cantidad, valida, y pasa a syncProducto en Subpedido
|
||||
public function syncProductos(Subpedido $subpedido) {
|
||||
if ($subpedido->aprobado)
|
||||
abort(400, "No se puede modificar un pedido aprobado.");
|
||||
|
||||
$valid = request()->validate([
|
||||
'cantidad' => ['integer','required','min:0'],
|
||||
'notas' => 'nullable',
|
||||
'producto_id' => [
|
||||
'required',
|
||||
Rule::in(Producto::all()->pluck('id')),
|
||||
]
|
||||
]);
|
||||
|
||||
$producto = Producto::find($valid['producto_id']);
|
||||
$notas = $valid['notas'];
|
||||
$cantidad = $valid['cantidad'];
|
||||
$subpedido->syncProducto($producto, $cantidad, $notas ?? "");
|
||||
return new SubpedidoResource($subpedido);
|
||||
}
|
||||
|
||||
public function toggleAprobacion(Subpedido $subpedido) {
|
||||
$valid = request()->validate([
|
||||
'aprobacion' => 'required | boolean'
|
||||
]);
|
||||
$subpedido->toggleAprobacion($valid['aprobacion']);
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function syncDevoluciones(Subpedido $subpedido) {
|
||||
if ($subpedido->aprobado)
|
||||
abort(400, "No se puede modificar un pedido aprobado.");
|
||||
|
||||
$valid = request()->validate([
|
||||
'total' => 'required|min:0',
|
||||
'notas' => 'min:0'
|
||||
]);
|
||||
$subpedido->syncDevoluciones($valid['total'], $valid['notas'] ?? "");
|
||||
|
||||
return new SubpedidoResource($subpedido);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
|
@ -28,6 +28,11 @@ class LoginController extends Controller
|
|||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
protected function authenticated(Request $request, $user)
|
||||
{
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
|
|
186
app/Http/Controllers/ComisionesController.php
Normal file
186
app/Http/Controllers/ComisionesController.php
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\Helpers\CanastaHelper;
|
||||
use App\Helpers\CsvHelper;
|
||||
use App\Helpers\PedidosExportHelper;
|
||||
use App\Helpers\TransporteHelper;
|
||||
use App\Http\Resources\GrupoDeCompraResource;
|
||||
use App\Producto;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use League\Csv\Exception;
|
||||
use League\Csv\InvalidArgument;
|
||||
use Mpdf\MpdfException;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class ComisionesController
|
||||
{
|
||||
const PARAMETROS_PATH = 'csv/parametros.csv';
|
||||
const CANASTAS_PATH = 'csv/canastas/';
|
||||
const BARRIO = "Barrio";
|
||||
const SALDO = "Saldo";
|
||||
|
||||
public function show()
|
||||
{
|
||||
return view('auth/login');
|
||||
}
|
||||
|
||||
public function descargarPedidos()
|
||||
{
|
||||
try {
|
||||
PedidosExportHelper::pedidosBarriales();
|
||||
} catch (CannotInsertRecord|InvalidArgument|Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
$pattern = storage_path('csv/exports/pedidos-por-barrio-*.csv');
|
||||
$files = glob($pattern);
|
||||
|
||||
usort($files, function ($a, $b) {
|
||||
return filemtime($b) <=> filemtime($a);
|
||||
});
|
||||
|
||||
return response()->download($files[0]);
|
||||
}
|
||||
|
||||
public function descargarPedidosDeOllas()
|
||||
{
|
||||
try {
|
||||
PedidosExportHelper::pedidosDeOllas();
|
||||
} catch (CannotInsertRecord|InvalidArgument|Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
$pattern = storage_path('csv/exports/pedidos-de-ollas-*.csv');
|
||||
$files = glob($pattern);
|
||||
|
||||
usort($files, function ($a, $b) {
|
||||
return filemtime($b) <=> filemtime($a);
|
||||
});
|
||||
|
||||
return response()->download($files[0]);
|
||||
}
|
||||
|
||||
public function descargarNotas()
|
||||
{
|
||||
try {
|
||||
Producto::planillaNotas();
|
||||
} catch (CannotInsertRecord|InvalidArgument $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
$pattern = storage_path('csv/exports/notas-por-barrio-*.csv');
|
||||
$files = glob($pattern);
|
||||
|
||||
usort($files, function ($a, $b) {
|
||||
return filemtime($b) <=> filemtime($a);
|
||||
});
|
||||
|
||||
return response()->download($files[0]);
|
||||
}
|
||||
|
||||
public function pdf() {
|
||||
try {
|
||||
GrupoDeCompra::exportarPedidosBarrialesAPdf();
|
||||
return response();
|
||||
} catch (MpdfException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function cargarCanasta(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'data' => 'required|file|mimes:csv,txt|max:2048',
|
||||
]);
|
||||
|
||||
$nombre = CanastaHelper::guardarCanasta($request->file('data'), self::CANASTAS_PATH);
|
||||
try {
|
||||
CanastaHelper::cargarCanasta(storage_path(self::CANASTAS_PATH . $nombre));
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Canasta cargada exitosamente',
|
||||
]);
|
||||
}
|
||||
|
||||
public function descargarCanastaEjemplo(): BinaryFileResponse
|
||||
{
|
||||
$file = resource_path('csv/productos.csv');
|
||||
return response()->download($file);
|
||||
}
|
||||
|
||||
public function cargarSaldos(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'data' => 'required|file|mimes:csv,txt|max:2048',
|
||||
]);
|
||||
|
||||
$file = $request->file('data')->getPathname();
|
||||
|
||||
try {
|
||||
$records = CsvHelper::getRecords($file, "No se pudo leer el archivo.");
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
$barrio = $record[self::BARRIO];
|
||||
$saldo = $record[self::SALDO];
|
||||
GrupoDeCompra::where('nombre', $barrio)
|
||||
->update(['saldo' => $saldo]);
|
||||
}
|
||||
|
||||
return response()->json(GrupoDeCompraResource::collection(GrupoDeCompra::all()));
|
||||
}
|
||||
|
||||
public function descargarSaldosEjemplo(): BinaryFileResponse
|
||||
{
|
||||
$file = resource_path('csv/saldos.csv');
|
||||
return response()->download($file);
|
||||
}
|
||||
|
||||
public function obtenerParametros(): JsonResponse
|
||||
{
|
||||
try {
|
||||
$records = self::parametrosRecords();
|
||||
$result = [];
|
||||
foreach ($records as $record)
|
||||
$result[] = $record;
|
||||
return response()->json($result);
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function modificarParametros(string $parametro_id, Request $request) {
|
||||
try {
|
||||
if (collect(self::parametrosRecords())
|
||||
->contains('id', $parametro_id)) {
|
||||
$valid = $request->validate([
|
||||
'valor' => ['required', 'numeric', 'gte:0'],
|
||||
]);
|
||||
CsvHelper::cambiarParametro($parametro_id, $valid['valor']);
|
||||
TransporteHelper::resetParametros();
|
||||
return response()->noContent();
|
||||
}
|
||||
return response()->json(['message' => 'Parametro no encontrado.'], 404);
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function parametrosRecords(): array
|
||||
{
|
||||
$records = CsvHelper::getRecords(resource_path(self::PARAMETROS_PATH), "No se pudo leer el archivo.");
|
||||
return iterator_to_array($records);
|
||||
}
|
||||
}
|
43
app/Http/Controllers/OllasController.php
Normal file
43
app/Http/Controllers/OllasController.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\Http\Resources\PedidoOllasResource;
|
||||
use App\TipoPedido;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class OllasController extends Controller
|
||||
{
|
||||
public function show()
|
||||
{
|
||||
return view('auth/login');
|
||||
}
|
||||
|
||||
public function pedido(GrupoDeCompra $gdc)
|
||||
{
|
||||
$tipoOlla = TipoPedido::firstOrCreate(['nombre' => 'olla']);
|
||||
$pedido = $gdc->subpedidos()->firstOrCreate([
|
||||
'nombre' => 'Pedido de Ollas de ' . $gdc->nombre,
|
||||
'tipo_pedido_id' => $tipoOlla->id,
|
||||
]);
|
||||
if (!$pedido->cantidad_ollas) {
|
||||
$pedido->cantidad_ollas = 0;
|
||||
$pedido->save();
|
||||
}
|
||||
return response()->json(new PedidoOllasResource($pedido));
|
||||
}
|
||||
|
||||
public function actualizarCantidadOllas(GrupoDeCompra $gdc, Request $request)
|
||||
{
|
||||
$valid = $request->validate([
|
||||
'cantidad' => 'required|numeric|min:0',
|
||||
]);
|
||||
$pedido = $gdc->subpedidos()->where([
|
||||
'nombre' => 'Pedido de Ollas de ' . $gdc->nombre
|
||||
])->first();
|
||||
$pedido->cantidad_ollas = $valid['cantidad'];
|
||||
$pedido->save();
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProductoController extends Controller
|
||||
{
|
||||
/**
|
||||
|
@ -16,11 +14,6 @@ class ProductoController extends Controller
|
|||
$this->middleware(['auth','subpedido']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('productos');
|
||||
|
|
37
app/Http/Controllers/RouteController.php
Normal file
37
app/Http/Controllers/RouteController.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\UserRole;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RouteController extends Controller
|
||||
{
|
||||
function home(Request $request) {
|
||||
if (!Auth::check())
|
||||
return redirect('/login');
|
||||
|
||||
$barrio = UserRole::where('nombre', 'barrio')->first();
|
||||
$admin = UserRole::where('nombre', 'admin_barrio')->first();
|
||||
$comision = UserRole::where('nombre', 'comision')->first();
|
||||
$ollas = UserRole::where('nombre', 'ollas')->first();
|
||||
|
||||
switch ($request->user()->role_id) {
|
||||
case $barrio->id:
|
||||
return redirect('/pedido');
|
||||
case $admin->id:
|
||||
return redirect('/admin');
|
||||
case $comision->id:
|
||||
return redirect('/comisiones');
|
||||
case $ollas->id:
|
||||
return redirect('/ollas');
|
||||
default:
|
||||
abort(400, 'Rol de usuario invalido');
|
||||
}
|
||||
}
|
||||
|
||||
function main(Request $request) {
|
||||
return view('main');
|
||||
}
|
||||
}
|
35
app/Http/Controllers/SessionController.php
Normal file
35
app/Http/Controllers/SessionController.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Subpedido;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class SessionController extends Controller
|
||||
{
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$grupo_de_compra_id = Auth::user()->grupo_de_compra_id;
|
||||
$validated = $request->validate([
|
||||
'id' => 'required',
|
||||
Rule::in(Subpedido::where('grupo_de_compra_id', $grupo_de_compra_id)->pluck('id')),
|
||||
]);
|
||||
session()->put('pedido_id', $validated["id"]);
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function fetch(): JsonResponse
|
||||
{
|
||||
return response()->json(['id' => session('pedido_id')]);
|
||||
}
|
||||
|
||||
public function destroy(): Response
|
||||
{
|
||||
session()->forget('pedido_id');
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
43
app/Http/Controllers/UserController.php
Normal file
43
app/Http/Controllers/UserController.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\Http\Resources\GrupoDeCompraPedidoResource;
|
||||
use App\Http\Resources\GrupoDeCompraResource;
|
||||
use App\UserRole;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function user(Request $request)
|
||||
{
|
||||
return ['user' => $request->user()->name];
|
||||
}
|
||||
|
||||
public function rol(Request $request) {
|
||||
return ["rol" => UserRole::find($request->user()->role_id)->nombre];
|
||||
}
|
||||
|
||||
public function grupoDeCompra(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$result = [ 'grupo_de_compra' => null, ];
|
||||
$grupo_de_compra = GrupoDeCompra::find($user->grupo_de_compra_id);
|
||||
switch (UserRole::findOrFail($user->role_id)->nombre) {
|
||||
case 'ollas':
|
||||
case 'barrio':
|
||||
$result['grupo_de_compra'] = new GrupoDeCompraPedidoResource($grupo_de_compra);
|
||||
break;
|
||||
case 'admin_barrio':
|
||||
$result['grupo_de_compra'] = new GrupoDeCompraResource($grupo_de_compra);
|
||||
break;
|
||||
case 'comision':
|
||||
break;
|
||||
default:
|
||||
abort(400, 'Rol invalido.');
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\CheckRole;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
|
||||
|
||||
|
@ -17,7 +18,7 @@ class Kernel extends HttpKernel
|
|||
protected $middleware = [
|
||||
// \App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
|
@ -56,6 +57,7 @@ class Kernel extends HttpKernel
|
|||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'role' => \App\Http\Middleware\CheckRole::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
|
|
|
@ -3,19 +3,28 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
protected function redirectTo($request): string
|
||||
{
|
||||
if (! $request->expectsJson()) {
|
||||
if (!$request->expectsJson()) {
|
||||
$path = $request->path();
|
||||
if (preg_match('~^admin.*~i', $path))
|
||||
return route('admin.login');
|
||||
if (preg_match('~^comisiones.*~i', $path))
|
||||
return route('comisiones.login');
|
||||
if (preg_match('~^ollas.*~i', $path))
|
||||
return route('ollas.login');
|
||||
return route('login');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
25
app/Http/Middleware/CheckRole.php
Normal file
25
app/Http/Middleware/CheckRole.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\UserRole;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CheckRole
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param string $role
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $role)
|
||||
{
|
||||
$role_id = UserRole::where('nombre', $role)->first()->id;
|
||||
return $request->user()->role_id == $role_id ? $next($request)
|
||||
: response('No tenés permiso para esto.', 403);
|
||||
}
|
||||
}
|
|
@ -3,17 +3,18 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class Subpedido
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (!session('subpedido_nombre') || !session('subpedido_id')) {
|
||||
return redirect()->route('subpedidos.create');
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
|
@ -19,5 +19,8 @@ class TrustProxies extends Middleware
|
|||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
||||
protected $headers = Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO;
|
||||
}
|
||||
|
|
22
app/Http/Resources/GrupoDeCompraComisionesResource.php
Normal file
22
app/Http/Resources/GrupoDeCompraComisionesResource.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class GrupoDeCompraComisionesResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'saldo' => $this->saldo,
|
||||
];
|
||||
}
|
||||
}
|
23
app/Http/Resources/GrupoDeCompraPedidoResource.php
Normal file
23
app/Http/Resources/GrupoDeCompraPedidoResource.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class GrupoDeCompraPedidoResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
||||
];
|
||||
}
|
||||
}
|
34
app/Http/Resources/GrupoDeCompraResource.php
Normal file
34
app/Http/Resources/GrupoDeCompraResource.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class GrupoDeCompraResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
||||
'pedidos' => SubpedidoResource::collection($this->pedidosHogares()),
|
||||
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
|
||||
'saldo' => number_format($this->saldo, 2, ".", ""),
|
||||
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),
|
||||
'total_barrial' => number_format($this->totalBarrial(),2),
|
||||
'total_devoluciones' => number_format($this->totalDevoluciones(),2),
|
||||
'total_de_pedido' => number_format($this->totalDePedido(),2),
|
||||
'total_a_transferir' => number_format($this->totalATransferir(),2),
|
||||
'total_transporte' => number_format($this->totalTransporte()),
|
||||
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
||||
];
|
||||
}
|
||||
}
|
30
app/Http/Resources/PedidoOllasResource.php
Normal file
30
app/Http/Resources/PedidoOllasResource.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\TipoPedido;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PedidoOllasResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
$productos = $this->productos;
|
||||
foreach ($productos as $producto) {
|
||||
$producto['pivot']['total'] = number_format($producto->pivot->cantidad * $producto->precio, 2);
|
||||
}
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'productos' => $productos,
|
||||
'total' => number_format($this->totalCentralesSinTransporte(),2),
|
||||
'cantidad_de_ollas' => $this->cantidad_ollas,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ProductoResource extends JsonResource
|
||||
|
@ -9,23 +10,19 @@ class ProductoResource extends JsonResource
|
|||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'precio' => $this->precio,
|
||||
'categoria' => $this->categoria,
|
||||
'proveedor' => optional($this->proveedor)->nombre,
|
||||
'economia_solidaria' => optional($this->proveedor)->economia_solidaria,
|
||||
'nacional' => optional($this->proveedor)->nacional,
|
||||
'imagen' => optional($this->poster)->url(),
|
||||
'descripcion' => $this->descripcion,
|
||||
'apto_veganxs' => $this->apto_veganxs,
|
||||
'apto_celiacxs' => $this->apto_celiacxs
|
||||
'economia_solidaria' => $this->es_solidario,
|
||||
'nacional' => $this->es_solidario,
|
||||
'requiere_notas' => $this->requiere_notas,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
40
app/Http/Resources/SubpedidoResource.php
Normal file
40
app/Http/Resources/SubpedidoResource.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\TipoPedido;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class SubpedidoResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
$productos = $this->productos;
|
||||
foreach ($productos as $producto) {
|
||||
$producto['pivot']['total'] = number_format($producto->pivot->cantidad * $producto->precio, 2);
|
||||
}
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nombre' => $this->nombre,
|
||||
'productos' => $productos,
|
||||
'aprobado' => (bool) $this->aprobado,
|
||||
'total' => number_format($this->total(),2),
|
||||
'total_transporte' => number_format($this->totalTransporte()),
|
||||
'cantidad_transporte' => number_format($this->cantidadTransporte()),
|
||||
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),
|
||||
'devoluciones_total' => number_format($this->devoluciones_total,2),
|
||||
'devoluciones_notas' => $this->devoluciones_notas,
|
||||
'tipo' => [
|
||||
'id' => $this->tipo_pedido_id,
|
||||
'nombre' => TipoPedido::find($this->tipo_pedido_id)->nombre
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
118
app/Producto.php
118
app/Producto.php
|
@ -2,35 +2,105 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Filtros\FiltroDeProducto;
|
||||
use App\Helpers\CsvHelper;
|
||||
use App\Helpers\TransporteHelper;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
use League\Csv\Exception;
|
||||
use League\Csv\InvalidArgument;
|
||||
|
||||
class Producto extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $fillable = [ "nombre", "precio", "presentacion", "stock", "categoria" ];
|
||||
static $paginarPorDefecto = 10;
|
||||
protected $fillable = ["nombre", "precio", "categoria", "bono", "es_solidario", "requiere_notas"];
|
||||
|
||||
public function subpedidos()
|
||||
{
|
||||
return $this->belongsToMany('App\Subpedido','productos_subpedidos')->withPivot(["cantidad"]);
|
||||
}
|
||||
|
||||
public function proveedor()
|
||||
{
|
||||
return $this->belongsTo('App\Proveedor');
|
||||
}
|
||||
public function subpedidos(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Subpedido::class, 'productos_subpedidos')
|
||||
->withPivot(["cantidad", "notas"]);
|
||||
}
|
||||
|
||||
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||
public function scopeFiltrar($query, FiltroDeProducto $filtros)
|
||||
{
|
||||
return $filtros->aplicar($query);
|
||||
}
|
||||
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
|
||||
{
|
||||
return $filtros->aplicar($query);
|
||||
}
|
||||
|
||||
public static function getPaginar(Request $request)
|
||||
{
|
||||
return $request->has('paginar') && intval($request->input('paginar')) ? intval($request->input('paginar')) : self::$paginarPorDefecto;
|
||||
}
|
||||
|
||||
public static function getPaginar(Request $request): int
|
||||
{
|
||||
return $request->has('paginar') && intval($request->input('paginar')) ?
|
||||
intval($request->input('paginar')) :
|
||||
self::all()->count();
|
||||
}
|
||||
|
||||
public static function productosFilaID()
|
||||
{
|
||||
return self::noBarriales()->pluck('id', 'fila')->all();
|
||||
}
|
||||
|
||||
public static function productosIDFila()
|
||||
{
|
||||
return self::noBarriales()->pluck('fila', 'id')->all();
|
||||
}
|
||||
|
||||
public static function productosIDNombre()
|
||||
{
|
||||
return self::noBarriales()->pluck('nombre', 'id')->all();
|
||||
}
|
||||
|
||||
public static function noBarriales()
|
||||
{
|
||||
return self::where('nombre', 'not like', '%barrial%');
|
||||
}
|
||||
|
||||
public static function notasPorBarrio(): Collection
|
||||
{
|
||||
return DB::table('productos')
|
||||
->where('productos.nombre', 'not like', '%barrial%')
|
||||
->join('producto_subpedido', 'productos.id', '=', 'producto_subpedido.producto_id')
|
||||
->join('subpedidos', 'producto_subpedido.subpedido_id', '=', 'subpedidos.id')
|
||||
->join('grupos_de_compra', 'subpedidos.grupo_de_compra_id', '=', 'grupos_de_compra.id')
|
||||
->where('productos.requiere_notas', 1)
|
||||
->where('subpedidos.tipo_pedido_id', '=', 1)
|
||||
->select(
|
||||
'productos.nombre as producto',
|
||||
'grupos_de_compra.nombre as barrio',
|
||||
'producto_subpedido.notas'
|
||||
)
|
||||
->get()
|
||||
->groupBy('producto');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgument
|
||||
* @throws CannotInsertRecord
|
||||
*/
|
||||
static public function planillaNotas() {
|
||||
$headers = ['Producto'];
|
||||
$barrios = GrupoDeCompra::barriosMenosPrueba()
|
||||
->pluck('nombre')->toArray();
|
||||
$headers = array_merge($headers, $barrios);
|
||||
|
||||
$notasPorBarrio = self::notasPorBarrio();
|
||||
$planilla = [];
|
||||
|
||||
foreach ($notasPorBarrio as $producto => $notasGrupo) {
|
||||
$fila = [$producto];
|
||||
foreach ($barrios as $barrio) {
|
||||
$notas = $notasGrupo->where('barrio', $barrio)
|
||||
->pluck('notas')
|
||||
->implode('; ');
|
||||
$fila[] = $notas ?: '';
|
||||
}
|
||||
$planilla[] = $fila;
|
||||
}
|
||||
|
||||
$fecha = now()->format('Y-m-d');
|
||||
$filePath = 'csv/exports/notas-por-barrio-' . $fecha . '.csv';
|
||||
CsvHelper::generarCsv($filePath, $planilla, $headers);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Proveedor extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $fillable = [ "nombre","direccion","telefono","correo","comentario" ];
|
||||
protected $table = 'proveedores';
|
||||
|
||||
public function productos()
|
||||
{
|
||||
return $this->hasMany('App\Producto');
|
||||
}
|
||||
}
|
|
@ -2,31 +2,149 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use League\Csv\Reader;
|
||||
use App\Helpers\TransporteHelper;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Log;
|
||||
use App\Filtros\FiltroDeSubpedido;
|
||||
|
||||
class Subpedido extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $fillable = ['grupo_de_compra_id', 'aprobado', 'nombre'];
|
||||
protected $fillable = [
|
||||
'grupo_de_compra_id',
|
||||
'aprobado',
|
||||
'nombre',
|
||||
'devoluciones_total',
|
||||
'devoluciones_notas',
|
||||
'tipo_pedido_id',
|
||||
'cantidad_ollas'
|
||||
];
|
||||
|
||||
public function productos()
|
||||
{
|
||||
return $this->belongsToMany('App\Producto','pedidos_productos')->withPivot(["cantidad"]);
|
||||
}
|
||||
public function productos(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Producto::class)->withPivot(["cantidad", "notas"]);
|
||||
}
|
||||
|
||||
public function grupoDeCompra()
|
||||
{
|
||||
return $this->belongsTo('App\GrupoDeCompra');
|
||||
}
|
||||
public function grupoDeCompra(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(GrupoDeCompra::class);
|
||||
}
|
||||
|
||||
//Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||
public function scopeFiltrar($query, FiltroDeSubpedido $filtros)
|
||||
{
|
||||
return $filtros->aplicar($query);
|
||||
}
|
||||
public function tipoPedido(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TipoPedido::class);
|
||||
}
|
||||
|
||||
// Permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||
public function scopeFiltrar($query, FiltroDeSubpedido $filtros): Builder
|
||||
{
|
||||
return $filtros->aplicar($query);
|
||||
}
|
||||
|
||||
public function total()
|
||||
{
|
||||
return $this->totalSinDevoluciones() - $this->devoluciones_total;
|
||||
}
|
||||
|
||||
public function totalSinDevoluciones()
|
||||
{
|
||||
return $this->totalBarrial() + $this->totalCentral();
|
||||
}
|
||||
|
||||
public function totalBarrial()
|
||||
{
|
||||
return DB::table('producto_subpedido')
|
||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
||||
->where('producto_subpedido.subpedido_id', $this->id)
|
||||
->where('productos.nombre', 'like', '%barrial%')
|
||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
||||
->value('total');
|
||||
}
|
||||
|
||||
public function totalCentral()
|
||||
{
|
||||
return $this->totalCentralesSinTransporte() + $this->totalTransporte();
|
||||
}
|
||||
|
||||
public function totalCentralesSinTransporte() {
|
||||
return $this->totalCentralesQueNoPaganTransporte() + $this->totalCentralesQuePaganTransporte();
|
||||
}
|
||||
|
||||
public function totalCentralesQueNoPaganTransporte()
|
||||
{
|
||||
return DB::table('producto_subpedido')
|
||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
||||
->where('producto_subpedido.subpedido_id', $this->id)
|
||||
->where('productos.nombre', 'not like', '%barrial%')
|
||||
->where(function ($query) {
|
||||
$query->where('productos.categoria', 'like', '%SUBSIDIADO%')
|
||||
->orWhere('productos.bono', true);
|
||||
})
|
||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
||||
->value('total');
|
||||
}
|
||||
|
||||
public function totalCentralesQuePaganTransporte()
|
||||
{
|
||||
return DB::table('producto_subpedido')
|
||||
->join('productos', 'producto_subpedido.producto_id', '=', 'productos.id')
|
||||
->where('producto_subpedido.subpedido_id', $this->id)
|
||||
->where('productos.nombre', 'not like', '%barrial%')
|
||||
->where('productos.bono', false)
|
||||
->where('productos.categoria', 'not like', '%SUBSIDIADO%')
|
||||
->selectRaw('SUM(productos.precio * producto_subpedido.cantidad) as total')
|
||||
->value('total');
|
||||
}
|
||||
|
||||
public function totalTransporte()
|
||||
{
|
||||
return TransporteHelper::totalTransporte($this->totalCentralesQuePaganTransporte());
|
||||
}
|
||||
|
||||
public function cantidadTransporte()
|
||||
{
|
||||
return TransporteHelper::cantidadTransporte($this->totalCentralesQuePaganTransporte());
|
||||
}
|
||||
|
||||
// Actualiza el pedido, agregando o quitando del subpedido según sea necesario. Debe ser llamado desde el controlador de subpedidos, luego de validar que los parámetros $producto y $cantidad son correctos. También calcula el subtotal por producto.
|
||||
public function syncProducto(Producto $producto, int $cantidad, string $notas)
|
||||
{
|
||||
if ($cantidad) {
|
||||
//si la cantidad es 1 o más se agrega el producto o actualiza la cantidad
|
||||
$this->productos()->syncWithoutDetaching([
|
||||
$producto->id => [
|
||||
'cantidad' => $cantidad,
|
||||
'notas' => $notas,
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
//si la cantidad es 0, se elimina el producto del subpedido
|
||||
$this->productos()->detach($producto->id);
|
||||
}
|
||||
|
||||
$this->updated_at = now();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function toggleAprobacion(bool $aprobacion)
|
||||
{
|
||||
$this->aprobado = $aprobacion;
|
||||
$this->update(['aprobado' => $aprobacion]);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function generarHTML()
|
||||
{
|
||||
$view = view("pdfgen.pedido_tabla", ["pedido" => $this]);
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
public function syncDevoluciones(float $total, string $notas)
|
||||
{
|
||||
$this->devoluciones_total = $total;
|
||||
$this->devoluciones_notas = $notas;
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
|
10
app/TipoPedido.php
Normal file
10
app/TipoPedido.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TipoPedido extends Model
|
||||
{
|
||||
protected $fillable = ["nombre"];
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
|
@ -16,7 +16,7 @@ class User extends Authenticatable
|
|||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'email', 'password',
|
||||
'name', 'email', 'password', 'role_id',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -38,8 +38,8 @@ class User extends Authenticatable
|
|||
];
|
||||
|
||||
|
||||
public function grupoDeCompra()
|
||||
public function grupoDeCompra(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo('App\GrupoDeCompra');
|
||||
return $this->belongsTo(GrupoDeCompra::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace App;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Admin extends Model
|
||||
class UserRole extends Model
|
||||
{
|
||||
//
|
||||
protected $fillable = ["nombre"];
|
||||
}
|
|
@ -8,20 +8,20 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2.5|^8.0",
|
||||
"fideloper/proxy": "^4.4",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
||||
"laravel/framework": "^7.29",
|
||||
"laravel/sanctum": "^2.13",
|
||||
"laravel/tinker": "^2.5",
|
||||
"laravel/ui": "*",
|
||||
"league/csv": "^9.8"
|
||||
"php": "^8.3",
|
||||
"doctrine/dbal": "^3.0",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/sanctum": "^4.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.3",
|
||||
"league/csv": "^9.8",
|
||||
"mpdf/mpdf": "^8.2",
|
||||
"prexview/prexview": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"facade/ignition": "^2.0",
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"nunomaduro/collision": "^4.3"
|
||||
"nunomaduro/collision": "^8.0"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
|
|
4988
composer.lock
generated
4988
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -67,7 +67,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'UTC',
|
||||
'timezone' => 'America/Montevideo',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||
/** @var Factory $factory */
|
||||
|
||||
use App\User;
|
||||
use Faker\Generator as Faker;
|
||||
use Illuminate\Database\Eloquent\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,6 +19,8 @@ class CreateUsersTable extends Migration
|
|||
$table->string('email')->unique()->nullable();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->foreignId('grupo_de_compra_id')->nullable();
|
||||
$table->boolean('is_admin');
|
||||
$table->unique(['name', 'is_admin']);
|
||||
$table->string('password');
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
|
|
|
@ -17,7 +17,7 @@ class CreateSubpedidosTable extends Migration
|
|||
$table->id();
|
||||
$table->string('nombre');
|
||||
$table->foreignId('grupo_de_compra_id');
|
||||
$table->boolean('aprobado')->nullable();
|
||||
$table->boolean('aprobado')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarColumnaBonoATablaDeProductos extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->boolean('bono')->after('apto_celiacxs');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn('bono');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarColumnaTotalATablaDeProductoSubpedido extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->double('total',10,2)->after('cantidad')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->dropColumn('total');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarColumnaFilaEnPlanillaATablaDeProductos extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('fila')->after('id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn('fila');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CallCrearPedidosAprobados extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Artisan::call("view:CrearPedidosAprobadosView");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class DevolucionesPedido extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('subpedidos', function (Blueprint $table) {
|
||||
$table->double('devoluciones_total', 10, 2)->default(0);
|
||||
$table->string('devoluciones_notas')->default("");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('subpedidos', function (Blueprint $table) {
|
||||
$table->dropColumn('devoluciones_total');
|
||||
$table->dropColumn('devoluciones_notas');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class HabilitarDevoluciones extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->boolean('devoluciones_habilitadas')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->dropColumn('devoluciones_habilitadas');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarIsComprasAUser extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('is_compras')->after('is_admin')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('is_compras');
|
||||
});
|
||||
}
|
||||
}
|
32
database/migrations/2024_09_17_234635_notas_producto.php
Normal file
32
database/migrations/2024_09_17_234635_notas_producto.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class NotasProducto extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->string('notas')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->dropColumn('notas');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ProductoRequiereNotas extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->boolean('requiere_notas')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn('requiere_notas');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CrearCargaDeCanastas extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('carga_de_canastas', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('path');
|
||||
$table->string('descripcion');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('carga_de_canastas');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class CallAgregarEsBonoAPedidosAprobados extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Artisan::call("command:AgregarEsBonoAPedidosAprobados");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUserRolesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('user_roles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nombre');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
$tipos = ["barrio", "admin_barrio", "comision"];
|
||||
foreach ($tipos as $tipo) {
|
||||
UserRole::create([
|
||||
"nombre" => $tipo,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('user_roles');
|
||||
}
|
||||
}
|
43
database/migrations/2025_05_15_023829_agregar_rol_a_user.php
Normal file
43
database/migrations/2025_05_15_023829_agregar_rol_a_user.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarRolAUser extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->foreignId('role_id');
|
||||
});
|
||||
|
||||
$barrio = UserRole::where('nombre', 'barrio')->first();
|
||||
$admin_barrio = UserRole::where('nombre', 'admin_barrio')->first();
|
||||
$comision = UserRole::where('nombre', 'comision')->first();
|
||||
User::all()->each(function($user) use ($barrio, $comision, $admin_barrio) {
|
||||
$user->role_id = $user->is_admin ? $admin_barrio->id :
|
||||
($user->is_compras ? $comision->id : $barrio->id);
|
||||
$user->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('user', function (Blueprint $table) {
|
||||
$table->dropForeign('role_id');
|
||||
});
|
||||
}
|
||||
}
|
43
database/migrations/2025_05_15_033316_simplificar_users.php
Normal file
43
database/migrations/2025_05_15_033316_simplificar_users.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class SimplificarUsers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn(['is_admin', 'is_compras']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('is_admin')->default(false);
|
||||
$table->boolean('is_compras')->default(false);
|
||||
});
|
||||
|
||||
$admin_barrio = UserRole::where('nombre', 'admin_barrio')->first();
|
||||
$comision = UserRole::where('nombre', 'comision')->first();
|
||||
foreach (User::all() as $user) {
|
||||
$user->is_admin = $user->role_id == $admin_barrio->id;
|
||||
$user->is_compras = $user->role_id == $comision->id;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class SimplificarBarrios extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'cantidad_de_nucleos',
|
||||
'telefono',
|
||||
'correo',
|
||||
'referente_finanzas',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->double('cantidad_de_nucleos');
|
||||
$table->string('telefono');
|
||||
$table->string('correo');
|
||||
$table->string('referente_finanzas');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class SimplificarProductos extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'presentacion',
|
||||
'stock',
|
||||
'imagen_id',
|
||||
'descripcion',
|
||||
'apto_veganxs',
|
||||
'apto_celiacxs',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('presentacion')->nullable();
|
||||
$table->integer('stock')->nullable();
|
||||
$table->foreignId('imagen_id')->nullable();
|
||||
$table->string('descripcion')->nullable();
|
||||
$table->boolean('apto_veganxs')->nullable();
|
||||
$table->boolean('apto_celiacxs')->nullable();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class SimplificarProductoSubpedido extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->dropColumn('total');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('producto_subpedido', function (Blueprint $table) {
|
||||
$table->double('total');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use App\Producto;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarEsSolidario extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->boolean('es_solidario')->default(false);
|
||||
});
|
||||
|
||||
foreach (Producto::all() as $producto) {
|
||||
$producto->es_solidario = $producto->proveedor_id != null;
|
||||
$producto->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn('es_solidario');
|
||||
});
|
||||
}
|
||||
}
|
59
database/migrations/2025_05_15_035807_eliminar_proveedor.php
Normal file
59
database/migrations/2025_05_15_035807_eliminar_proveedor.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
use App\Producto;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class EliminarProveedor extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->dropColumn('proveedor_id');
|
||||
});
|
||||
Schema::dropIfExists('proveedores');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::create('proveedores', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nombre');
|
||||
$table->string('direccion')->nullable();
|
||||
$table->string('telefono')->nullable();
|
||||
$table->string('correo')->nullable();
|
||||
$table->boolean('economia_solidaria')->nullable();
|
||||
$table->boolean('nacional')->nullable();
|
||||
$table->text('detalles_de_pago')->nullable();
|
||||
$table->text('comentario')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->foreignId('proveedor_id')->nullable();
|
||||
});
|
||||
|
||||
$proveedor_id = DB::table('proveedores')->insertGetId([
|
||||
['nombre' => 'Proveedor de economía solidaria',
|
||||
'economia_solidaria' => 1,
|
||||
'nacional' => 1]
|
||||
]);
|
||||
|
||||
foreach (Producto::all() as $producto) {
|
||||
$producto->proveedor_id = $producto->es_solidario ? $proveedor_id : null;
|
||||
$producto->save();
|
||||
}
|
||||
}
|
||||
}
|
35
database/migrations/2025_05_15_041404_eliminar_admin.php
Normal file
35
database/migrations/2025_05_15_041404_eliminar_admin.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class EliminarAdmin extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('admins');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::create('admins', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nombre');
|
||||
$table->foreignId('grupo_de_compra_id');
|
||||
$table->string('email');
|
||||
$table->string('contrasena');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class HacerFilaNullable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('fila')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('fila')->nullable(false)->change();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class QuitarPasswordDeGrupoDeCompra extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->dropColumn('password');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->string('password')->nullable();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AgregarSaldosABarrios extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// Agregar columna 'saldo' a la tabla 'grupos_de_compra'
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->double('saldo', 10, 2)->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
// Remover columna 'saldo' de la tabla 'grupos_de_compra'
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->dropColumn('saldo');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use App\TipoPedido;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateTipoPedidosTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('tipo_pedidos', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string("nombre");
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
$hogar = TipoPedido::firstOrCreate(['nombre' => 'hogar']);
|
||||
TipoPedido::firstOrCreate(['nombre' => 'olla']);
|
||||
|
||||
Schema::table('subpedidos', function (Blueprint $table) use ($hogar) {
|
||||
$table->foreignId('tipo_pedido_id')->default($hogar->id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('tipo_pedidos');
|
||||
Schema::table('subpedidos', function (Blueprint $table) {
|
||||
$table->dropColumn('tipo_pedido_id');
|
||||
});
|
||||
}
|
||||
}
|
40
database/migrations/2025_06_20_040800_user_role_ollas.php
Normal file
40
database/migrations/2025_06_20_040800_user_role_ollas.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserRoleOllas extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$ollasRol = UserRole::firstOrCreate(['nombre' => 'ollas']);
|
||||
$barrios = GrupoDeCompra::all();
|
||||
foreach ($barrios as $barrio) {
|
||||
$barrio->users()->firstOrCreate([
|
||||
'name' => $barrio->nombre . '_ollas',
|
||||
'password' => Hash::make('123'),
|
||||
'role_id' => $ollasRol->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$ollasRol = UserRole::where('nombre', 'ollas')->firstOrFail();
|
||||
User::where('role_id', $ollasRol->id)->delete();
|
||||
$ollasRol->delete();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CantidadOllasPedidos extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('subpedidos', function (Blueprint $table) {
|
||||
$table->integer('cantidad_ollas')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('subpedidos', function (Blueprint $table) {
|
||||
$table->dropColumn('cantidad_ollas');
|
||||
});
|
||||
}
|
||||
}
|
20
database/seeds/CanastaSeeder.php
Normal file
20
database/seeds/CanastaSeeder.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
use App\Helpers\CanastaHelper;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class CanastaSeeder extends Seeder
|
||||
{
|
||||
const ARCHIVO_DEFAULT = 'csv/productos.csv';
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
CanastaHelper::cargarCanasta(resource_path(self::ARCHIVO_DEFAULT));
|
||||
}
|
||||
}
|
|
@ -1,10 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
const CHUNK_SIZE = 100;
|
||||
|
||||
static function addTimestamps($object) {
|
||||
$now = DB::raw('CURRENT_TIMESTAMP');
|
||||
$object['created_at'] = $now;
|
||||
$object['updated_at'] = $now;
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*
|
||||
|
@ -12,7 +21,9 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->call(CanastaSeeder::class);
|
||||
$this->call(GrupoDeCompraSeeder::class);
|
||||
$this->call(ProductoSeeder::class);
|
||||
$this->call(UserSeeder::class);
|
||||
$this->call(UsuarioOllasSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<?php
|
||||
|
||||
use App\Helpers\CsvHelper;
|
||||
use App\GrupoDeCompra;
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Seeder;
|
||||
use League\Csv\Reader;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class GrupoDeCompraSeeder extends Seeder
|
||||
{
|
||||
|
@ -9,41 +13,36 @@ class GrupoDeCompraSeeder extends Seeder
|
|||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$csv = Reader::createFromPath(resource_path('csv/barrios.csv'), 'r');
|
||||
$csv->setDelimiter("|");
|
||||
$csv->setEnclosure("'");
|
||||
$csv->setHeaderOffset(0);
|
||||
$registros = $csv->getRecords();
|
||||
$registros = CsvHelper::getRecords(resource_path('csv/barrios.csv'), 'No se pudo leer la planilla de barrios.');
|
||||
$gdcToInsert = [];
|
||||
$usersToInsert = [];
|
||||
$roles = UserRole::where('nombre', 'barrio')->orWhere('nombre', 'admin_barrio')->get();
|
||||
|
||||
foreach($registros as $key => $registro){
|
||||
$gdcToInsert[] = [
|
||||
$gdcToInsert[] = DatabaseSeeder::addTimestamps([
|
||||
'nombre' => $registro['barrio'],
|
||||
'region' => $registro['region'],
|
||||
'telefono' => $registro['telefono'],
|
||||
'correo' => $registro['correo'],
|
||||
'referente_finanzas' => $registro['referente']
|
||||
];
|
||||
]);
|
||||
|
||||
$usersToInsert[] = [
|
||||
'name' => $registro['barrio'],
|
||||
'password' => Hash::make($registro['barrio']),
|
||||
'grupo_de_compra_id' => $key
|
||||
];
|
||||
foreach($roles as $role) {
|
||||
$nombre = $registro['barrio'] . ($role->nombre == 'barrio' ? '' : '_admin');
|
||||
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||
'name' => $nombre,
|
||||
'password' => Hash::make("123"),
|
||||
'role_id' => $role->id,
|
||||
'grupo_de_compra_id' => $key,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_chunk($gdcToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
{
|
||||
DB::table('grupos_de_compra')->insert($chunk);
|
||||
}
|
||||
foreach (array_chunk($gdcToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
GrupoDeCompra::insert($chunk);
|
||||
|
||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
{
|
||||
DB::table('users')->insert($chunk);
|
||||
}
|
||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
User::insert($chunk);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use League\Csv\Reader;
|
||||
use App\Proveedor;
|
||||
|
||||
class ProductoSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$csv = Reader::createFromPath(resource_path('csv/productos.csv'), 'r');
|
||||
$csv->setDelimiter("|");
|
||||
$csv->setEnclosure("'");
|
||||
$csv->setHeaderOffset(0);
|
||||
$registros = $csv->getRecords();
|
||||
$toInsert = [];
|
||||
|
||||
foreach($registros as $registro){
|
||||
$toInsert[] = [
|
||||
'categoria' => $registro['categoria'],
|
||||
'nombre' => $registro['producto'],
|
||||
'precio' => $registro['precio'],
|
||||
'proveedor_id' => isset($registro['proveedor']) ? Proveedor::firstOrCreate([
|
||||
'nombre' => $registro['proveedor']
|
||||
])->id : null
|
||||
];
|
||||
}
|
||||
|
||||
foreach (array_chunk($toInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
{
|
||||
DB::table('productos')->insert($chunk);
|
||||
}
|
||||
}
|
||||
}
|
29
database/seeds/UserSeeder.php
Normal file
29
database/seeds/UserSeeder.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$usersToInsert = [];
|
||||
|
||||
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||
'name' => 'comision',
|
||||
'password' => Hash::make("123"),
|
||||
'role_id' => UserRole::where('nombre', 'comision')->first()->id,
|
||||
]);
|
||||
|
||||
|
||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
User::insert($chunk);
|
||||
}
|
||||
}
|
34
database/seeds/UsuarioOllasSeeder.php
Normal file
34
database/seeds/UsuarioOllasSeeder.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use App\GrupoDeCompra;
|
||||
use App\User;
|
||||
use App\UserRole;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UsuarioOllasSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$barrios = GrupoDeCompra::all();
|
||||
$usersToInsert = [];
|
||||
$ollas_id = UserRole::where('nombre', 'ollas')->first()->id;
|
||||
|
||||
foreach ($barrios as $barrio) {
|
||||
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||
'name' => $barrio->nombre . '_ollas',
|
||||
'password' => Hash::make('123'),
|
||||
'role_id' => $ollas_id,
|
||||
'grupo_de_compra_id' => $barrio->id,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (array_chunk($usersToInsert,DatabaseSeeder::CHUNK_SIZE) as $chunk)
|
||||
User::insert($chunk);
|
||||
}
|
||||
}
|
2
dev-start
Executable file
2
dev-start
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/bash
|
||||
docker-compose up -d && docker-compose exec app npm run watch
|
|
@ -1,14 +1,15 @@
|
|||
version: "3.7"
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
args:
|
||||
user: www
|
||||
uid: 1000
|
||||
uid: ${USERID}
|
||||
context: ./
|
||||
dockerfile: Dockerfile
|
||||
image: laravel-image
|
||||
container_name: laravel-app
|
||||
container_name: pedi2-app
|
||||
restart: unless-stopped
|
||||
working_dir: /var/www/
|
||||
volumes:
|
||||
|
@ -17,12 +18,26 @@ services:
|
|||
networks:
|
||||
- app-network
|
||||
|
||||
vite:
|
||||
build:
|
||||
args:
|
||||
user: www
|
||||
uid: ${USERID}
|
||||
context: ./
|
||||
container_name: vite
|
||||
working_dir: /var/www
|
||||
command: npm run dev
|
||||
volumes:
|
||||
- ./:/var/www
|
||||
ports:
|
||||
- "5173:5173"
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
db:
|
||||
image: mysql:5.7
|
||||
container_name: laravel-db
|
||||
container_name: pedi2-db
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
MYSQL_DATABASE: ${DB_DATABASE}
|
||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||
|
@ -36,13 +51,15 @@ services:
|
|||
- dbdata:/var/lib/mysql
|
||||
networks:
|
||||
- app-network
|
||||
ports:
|
||||
- ${DB_PORT_EXPOSED}:3306
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: laravel-nginx
|
||||
container_name: pedi2-nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 8000:80
|
||||
- ${NGINX_PORT}:80
|
||||
volumes:
|
||||
- ./:/var/www
|
||||
- ./nginx/conf.d/:/etc/nginx/conf.d/
|
||||
|
@ -56,4 +73,4 @@ networks:
|
|||
#Volumes
|
||||
volumes:
|
||||
dbdata:
|
||||
driver: local
|
||||
driver: local
|
||||
|
|
|
@ -13,6 +13,22 @@ server {
|
|||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
location ^~ /@vite/ {
|
||||
proxy_pass http://vite:5173;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
location ^~ /resources/ {
|
||||
proxy_pass http://vite:5173;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
gzip_static on;
|
||||
|
|
3315
package-lock.json
generated
Normal file
3315
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
30
package.json
30
package.json
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run development",
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "npm run development -- --watch",
|
||||
"watch-poll": "npm run watch -- --watch-poll",
|
||||
|
@ -10,17 +11,24 @@
|
|||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.19",
|
||||
"bootstrap": "^4.0.0",
|
||||
"cross-env": "^7.0",
|
||||
"jquery": "^3.2",
|
||||
"laravel-mix": "^5.0.1",
|
||||
"lodash": "^4.17.19",
|
||||
"popper.js": "^1.12",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"@types/axios": "^0.9.36",
|
||||
"@vitejs/plugin-vue2": "^2.3.3",
|
||||
"axios": "^0.27.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"laravel-vite-plugin": "^1.3.0",
|
||||
"sass": "^1.20.1",
|
||||
"sass-loader": "^8.0.0",
|
||||
"vue": "^2.5.17",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^2.7.16",
|
||||
"vue-template-compiler": "^2.7.16",
|
||||
"animate.css": "^4.1.1",
|
||||
"bulma": "^0.9.4",
|
||||
"bulma-switch": "^2.0.4",
|
||||
"bulma-toast": "^2.4.1",
|
||||
"vue-router": "^3.5.4",
|
||||
"vuex": "^3.6.2"
|
||||
}
|
||||
}
|
||||
|
|
BIN
public/assets/chismosa.png
Normal file
BIN
public/assets/chismosa.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
public/assets/favicon.png
Normal file
BIN
public/assets/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
8
public/css/app.css
vendored
8
public/css/app.css
vendored
|
@ -1,8 +0,0 @@
|
|||
p.navbar-item:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #cc0f35;
|
||||
}
|
||||
|
4
public/css/productos.css
vendored
4
public/css/productos.css
vendored
|
@ -1,4 +0,0 @@
|
|||
figure.image.icono {
|
||||
float: right;
|
||||
margin: 4px;
|
||||
}
|
73
public/js/app.js
vendored
73
public/js/app.js
vendored
|
@ -1,73 +0,0 @@
|
|||
window.Event = new Vue();
|
||||
|
||||
Vue.component('nav-bar', {
|
||||
template: `
|
||||
<nav class="navbar is-danger" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="https://mps.org.uy">
|
||||
<img src="/assets/logoMPS.png" height="28">
|
||||
</a>
|
||||
<p style="margin:0 auto" class="navbar-item"><slot name="subpedido"></slot></p>
|
||||
<a role="button" class="navbar-burger" :class="{'is-active':isActive}" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click="toggleState">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbarBasicExample" class="navbar-menu" :class="{'is-active':isActive}">
|
||||
<div class="navbar-start has-text-right-mobile">
|
||||
<!-- Styles nombre del barrio-->
|
||||
<p class="navbar-item"><slot name="gdc"></slot></p>
|
||||
<a class="navbar-item"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
Cerrar sesión
|
||||
</a>
|
||||
<slot name="logout-form"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</nav>`,
|
||||
data() {
|
||||
return {
|
||||
isActive: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleState() {
|
||||
this.isActive = !this.isActive;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('nav-migas', {
|
||||
data() {
|
||||
return {
|
||||
migas: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible: function() {
|
||||
return this.migas.length > 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('migas-setear-como-inicio', (miga) => {
|
||||
this.migas = [];
|
||||
this.migas.push(miga);
|
||||
});
|
||||
Event.$on('migas-agregar', (miga) => {
|
||||
this.migas.push(miga);
|
||||
});
|
||||
Event.$on('migas-reset', () => {
|
||||
this.migas = [];
|
||||
});
|
||||
Event.$on('migas-pop', () => {
|
||||
this.migas.pop();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
new Vue({
|
||||
el: '#app'
|
||||
});
|
114
public/js/login.js
vendored
114
public/js/login.js
vendored
|
@ -1,114 +0,0 @@
|
|||
window.Event = new Vue();
|
||||
|
||||
Vue.component('region-select', {
|
||||
template: `
|
||||
<div class="block">
|
||||
<div class="field">
|
||||
<label class="label">Seleccioná tu región</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select @change="onRegionSelected" v-model="region">
|
||||
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
||||
<option v-for="region in regiones" v-text="region" :name="region"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
data() {
|
||||
return {
|
||||
regiones: [],
|
||||
isDefaultDisabled: 0,
|
||||
region: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios.get("/api/regiones").then(response => this.regiones = response.data);
|
||||
},
|
||||
methods: {
|
||||
onRegionSelected() {
|
||||
this.isDefaultDisabled = 1;
|
||||
Event.$emit("region-seleccionada",this.region);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('barrio-select', {
|
||||
template: `
|
||||
<div v-show="visible" class="block">
|
||||
<div class="field">
|
||||
<label class="label">Seleccioná tu barrio o grupo de compra</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select @change="onGDCSelected" v-model="gdc" name="name">
|
||||
<option :disabled="isDefaultDisabled==1" value=null>Seleccionar</option>
|
||||
<option v-for="gdc in gdcs" v-text="gdc.nombre" :name="gdc.nombre"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
region: null,
|
||||
gdcs: [],
|
||||
isDefaultDisabled: 0,
|
||||
gdc: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('region-seleccionada', (region)=> {
|
||||
this.region = region;
|
||||
this.fillGDC(region);
|
||||
this.visible = true;
|
||||
});
|
||||
},
|
||||
methods : {
|
||||
fillGDC(region) {
|
||||
axios.get("/api/grupos-de-compra").then(response => {
|
||||
this.gdcs = response.data[this.region];
|
||||
});
|
||||
},
|
||||
onGDCSelected() {
|
||||
this.isDefaultDisabled = 1;
|
||||
Event.$emit("gdc-seleccionado",this.gdc);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Vue.component('login', {
|
||||
template: `
|
||||
<div v-show="visible" class="block">
|
||||
<div class="field">
|
||||
<label class="label">Contraseña del barrio</label>
|
||||
<p class="control">
|
||||
<input required class="input" type="password" name="password" placeholder="Contraseña del barrio">
|
||||
</p>
|
||||
<p class="help">Si no la sabés, consultá a tus compañerxs.</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-success" value="Ingresar">
|
||||
</input>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
gdc: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('gdc-seleccionado', (gdc) => {
|
||||
this.gdc = gdc;
|
||||
this.visible = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
new Vue({
|
||||
el: '#root'
|
||||
});
|
171
public/js/productos.js
vendored
171
public/js/productos.js
vendored
|
@ -1,171 +0,0 @@
|
|||
Vue.component('categorias-container', {
|
||||
template: `
|
||||
<div v-show="visible" class="container">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<div v-for="catego in categorias" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
||||
<div @click.capture="seleccionarCategoria(catego)" class="card" style="height:100%" >
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-content" style="overflow:hidden">
|
||||
<p class="title is-6" v-text="catego"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- END CARD -->
|
||||
</div><!-- END BLOCK COLUMN -->
|
||||
</div><!-- END COLUMNS -->
|
||||
</div><!-- END CONTAINER -->`,
|
||||
data() {
|
||||
return {
|
||||
categorias: null,
|
||||
visible: true,
|
||||
miga: {
|
||||
nombre: "Categorías",
|
||||
href: "/productos"
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios.get("/api/categorias").then(response => {
|
||||
this.categorias = response.data;
|
||||
});
|
||||
Event.$emit("migas-setear-como-inicio",this.miga);
|
||||
},
|
||||
methods: {
|
||||
seleccionarCategoria(categoria) {
|
||||
this.visible = false;
|
||||
Event.$emit("categoria-seleccionada",categoria);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('productos-container', {
|
||||
template: `
|
||||
<div v-show="visible" class="container">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<div v-for="producto in productos" class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
||||
<div @click.capture="seleccionarProducto(producto)" class="card" style="height:100%">
|
||||
<div class="card-image">
|
||||
<figure class="image is-4by3">
|
||||
<img v-bind:src="producto.imagen ? producto.imagen : 'https://bulma.io/images/placeholders/1280x960.png'">
|
||||
</figure>
|
||||
<figure v-show="producto.nacional" class="image icono is-32x32">
|
||||
<img src="/assets/uruguay.png">
|
||||
</figure>
|
||||
<figure v-show="producto.economia_solidaria" class="image icono is-32x32">
|
||||
<img src="/assets/solidaria.png">
|
||||
</figure>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-content">
|
||||
<p class="title is-6" v-text="producto.nombre"></p>
|
||||
<p class="subtitle is-7" v-text="producto.proveedor"></p>
|
||||
<p class="subtitle is-7">$<span v-text="producto.precio"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- END CARD -->
|
||||
</div><!-- END BLOCK COLUMN -->
|
||||
</div><!-- END COLUMNS -->
|
||||
</div><!-- END CONTAINER -->`,
|
||||
data() {
|
||||
return {
|
||||
productos: [],
|
||||
visible: false,
|
||||
categoria: null,
|
||||
paginar: 150
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
miga: function(){
|
||||
return {
|
||||
nombre: this.categoria,
|
||||
href: "#" + this.categoria
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('categoria-seleccionada', (categoria) => {
|
||||
this.categoria = categoria;
|
||||
|
||||
axios.get("/api/productos", {
|
||||
params: {
|
||||
categoria: this.categoria,
|
||||
paginar: this.paginar
|
||||
}
|
||||
}).then(response => {
|
||||
this.productos = response.data.data;
|
||||
});
|
||||
this.visible = true;
|
||||
Event.$emit("migas-agregar",this.miga);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
seleccionarProducto(producto) {
|
||||
Event.$emit("producto-seleccionado",producto);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('producto-container', {
|
||||
template: `
|
||||
<div v-bind:class="visible ? 'is-active modal' : 'modal'">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title" v-text="producto.nombre"></p>
|
||||
<button class="delete" aria-label="close" @click.capture="cerrar"></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="card-image">
|
||||
<figure class="image is-4by3">
|
||||
<img v-bind:src="producto.imagen ? producto.imagen : 'https://bulma.io/images/placeholders/1280x960.png'">
|
||||
</figure>
|
||||
<figure v-show="producto.nacional" class="image icono is-32x32">
|
||||
<img src="/assets/uruguay.png">
|
||||
</figure>
|
||||
<figure v-show="producto.economia_solidaria" class="image icono is-32x32">
|
||||
<img src="/assets/solidaria.png">
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title is-4" v-text="producto.proveedor"></p>
|
||||
<p class="subtitle is-4">$<span v-text="producto.precio"></span></p>
|
||||
<p class="subtitle is-5"><span v-text="producto.descripcion"></span></p>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<button class="button is-success">Agregar a la chismosa</button>
|
||||
<button class="button" @click.capture="cerrar">Cancelar</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>`,
|
||||
data() {
|
||||
return {
|
||||
producto: null,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
miga: function(){
|
||||
return {
|
||||
nombre: this.producto.nombre,
|
||||
href: "#" + this.producto.nombre
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cerrar() {
|
||||
this.visible = false;
|
||||
Event.$emit("migas-pop");
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Event.$on('producto-seleccionado', (producto) => {
|
||||
this.producto = producto;
|
||||
this.visible = true;
|
||||
Event.$emit("migas-agregar",this.miga);
|
||||
});
|
||||
}
|
||||
});
|
52
public/js/subpedidos-create.js
vendored
52
public/js/subpedidos-create.js
vendored
|
@ -1,52 +0,0 @@
|
|||
Vue.component('subpedido-select', {
|
||||
data() {
|
||||
return {
|
||||
subpedido: null,
|
||||
subpedidosExistentes: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
nombresDeSubpedidos: function() {
|
||||
return this.subpedidosExistentes.map(a => a.nombre.toLowerCase())
|
||||
},
|
||||
botonCrearDesabilitado : function() {
|
||||
return !this.subpedido || this.nombresDeSubpedidos.includes(this.subpedido.toLowerCase())
|
||||
}
|
||||
},
|
||||
props: ["gdcid"],
|
||||
mounted() {
|
||||
console.log("ready");
|
||||
},
|
||||
methods: {
|
||||
onType() {
|
||||
if (!this.subpedido){
|
||||
this.subpedidosExistentes = [];
|
||||
return;
|
||||
}
|
||||
axios.get("/api/subpedidos", {
|
||||
params: {
|
||||
nombre: this.subpedido,
|
||||
grupo_de_compra: this.gdcid
|
||||
}
|
||||
}).then(response => {
|
||||
this.subpedidosExistentes = response.data
|
||||
});
|
||||
},
|
||||
submit() {
|
||||
axios.post("/api/subpedidos", {
|
||||
nombre: this.subpedido,
|
||||
grupo_de_compra_id: this.gdcid
|
||||
}).then(response => {
|
||||
//se creo el subpedido, guardamos el subpedido en sesion
|
||||
this.guardarSubpedidoEnSesion(response.data);
|
||||
});
|
||||
},
|
||||
guardarSubpedidoEnSesion(subpedido) {
|
||||
axios.post("/subpedidos/guardar_sesion", {
|
||||
subpedido: subpedido
|
||||
}).then(response => {
|
||||
window.location.href = 'productos';
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,45 +1,4 @@
|
|||
barrio|region|referente|telefono|correo
|
||||
BUCEO|ESTE|||
|
||||
MALVIN NORTE|ESTE|||
|
||||
PINAR|ESTE|||
|
||||
UNION|ESTE|||
|
||||
SANTO DOMINGO|NORTE|||
|
||||
21 DE FEBRERO|NORTE|||
|
||||
PIEDRAS BLANCAS|NORTE|||
|
||||
BELLA ITALIA|NORTE|||
|
||||
JARDINES|NORTE|||
|
||||
LA SOCIALISTA|NORTE|||
|
||||
VILLA GARCIA|NORTE|||
|
||||
LAS ACACIAS|NORTE|||
|
||||
MANGA|NORTE|||
|
||||
CERRITO|OESTE|||
|
||||
LEZICA|OESTE|||
|
||||
PEÑAROL|OESTE|||
|
||||
LAS PIEDRAS|OESTE|||
|
||||
A.C.T.E.O|OESTE|||
|
||||
NUEVO PARIS|OESTE|||
|
||||
SANTA CATALINA|OESTE|||
|
||||
BELVEDERE|OESTE|||
|
||||
BATLLE BERRES|OESTE|||
|
||||
CERRO PTI|OESTE|||
|
||||
COLECTIVO UTU LAVALLEJA|OESTE|||
|
||||
FOGONES|OESTE|||
|
||||
LAVALLEJA|OESTE|||
|
||||
REJUNTE|OESTE|||
|
||||
CAPURRO|OESTE|||
|
||||
PARQUE RODO|SUR|||
|
||||
REDUCTO|SUR|||
|
||||
AGUADA|SUR|||
|
||||
CASA DEL VECINO|SUR|||
|
||||
CIUDAD VIEJA|SUR|||
|
||||
COOP EJIDO|SUR|||
|
||||
COVIREUS|SUR|||
|
||||
LA BLANQUEADA|SUR|||
|
||||
NITEP|SUR|||
|
||||
LA CURVA|SUR|||
|
||||
PANADERIA VIDAL|SUR|||
|
||||
SUA|SUR|||
|
||||
ENTREVERO|SUR|||
|
||||
TRES CRUCES|SUR|||
|
||||
VILLA ESPAÑOLA|SUR|||
|
||||
AUDA|OTRA|||
|
||||
SINTEP|OTRA|||
|
||||
PRUEBA|SIN REGION|||
|
|
4
resources/csv/parametros.csv
Normal file
4
resources/csv/parametros.csv
Normal file
|
@ -0,0 +1,4 @@
|
|||
id|nombre|valor
|
||||
bono-transporte|'Bono de transporte'|15
|
||||
monto-transporte|'Monto para bono de transporte'|500
|
||||
monto-olla|'Monto por olla'|800
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue