380 Commits

Author SHA1 Message Date
360537c638 Prueba de integracion para service worker 2025-06-24 14:24:47 -04:00
a6e6b8acc0 Prueba de integracion para service worker 2025-06-24 12:56:03 -04:00
a4e2b4fc7a Seed TipoEstadoPago 2025-06-24 12:55:46 -04:00
479047cd6a Dependencias para testeo 2025-06-24 12:55:02 -04:00
29d9ea8e4a Correr seeds y botar tablas al final 2025-06-24 12:54:48 -04:00
a7cd661938 Registro de worker 2025-06-24 12:54:32 -04:00
7bdcc7168a Container separado a archivo a parte para poder cargarlo en otros lados 2025-06-24 12:54:19 -04:00
d2dff57531 FIX: id de migracion 2025-06-24 12:53:56 -04:00
39198bbe7c get Uf asincronico 2025-06-24 11:20:53 -04:00
200510d60a Prueba Service Worker 2025-06-24 11:20:21 -04:00
ecc67a43c8 Service Worker, corre metodos de servicios asincronicamente, requiere parametros escalares y no retornar mas que bool o void 2025-06-24 11:19:58 -04:00
64791d1fc5 Alias enqueue 2025-06-24 11:16:29 -04:00
4053854410 Prueba UF 2025-06-24 11:16:19 -04:00
a687743762 FIX: No buscar UF para fechas mayores a hoy o día nueve del mes 2025-06-24 11:04:33 -04:00
38fb6f3bcc Pausa a external 2025-06-19 16:47:24 -04:00
1e6bac61b5 FIX: Limpiar archivos 2025-06-19 16:47:06 -04:00
a611ae247d FIX: prorrateo ingresado en valor % 2025-06-12 11:28:04 -04:00
c02c6eb15c FIX: Add custom HttpException 2025-06-10 19:36:56 -04:00
b7e0217cf3 FIX: remove ext-http 2025-06-10 19:35:17 -04:00
2fd1a44984 FIX: install ext-http with external script 2025-06-10 19:04:32 -04:00
fe912db62b Add ext-http 2025-06-10 18:20:05 -04:00
da90160a2a Add ext-http 2025-06-10 18:02:05 -04:00
64047ef577 TOKU: FIX: exceptions 2025-06-10 17:48:36 -04:00
feef90afd6 TOKU: payments loop through pages 2025-06-10 17:46:16 -04:00
32e1e49a97 FIX: cuerpo para borrar payments 2025-06-10 17:34:04 -04:00
11c64cb10f FIX: url para borrar 2025-06-10 17:29:39 -04:00
823f97ce5f FIX: log levels 2025-06-10 17:24:38 -04:00
4ae72199fc Better external logging 2025-06-10 17:00:20 -04:00
d841b1aeed FIX: url de payments en Toku 2025-06-10 16:57:34 -04:00
666cac1958 FIX: url de payments en Toku 2025-06-10 16:54:46 -04:00
71c189e236 FIX: circular dependency 2025-06-10 16:49:34 -04:00
5b6a1c42e3 Toku: reorden 2025-06-10 16:28:46 -04:00
81bce6fe7f Cleanup 2025-06-10 16:28:13 -04:00
e1072ea252 Toku: Reset payments 2025-06-10 16:26:33 -04:00
21473fe52c Valor cuota en CLP 2025-06-10 15:27:09 -04:00
7d589e0e87 Valor cuota en CLF 2025-06-10 15:24:51 -04:00
c48a0d2381 Valor cuota en CLP 2025-06-10 15:14:25 -04:00
abb1ce7299 Mas logging 2025-06-09 12:44:42 -04:00
f1ed9668fc email -> mail 2025-06-06 18:25:12 -04:00
f9ae809fc4 Data too large 2025-06-06 18:10:59 -04:00
06e5292af1 Log add response 2025-06-06 18:10:06 -04:00
47ba664142 Log customer params 2025-06-06 18:04:57 -04:00
d10ee33215 better format for mysql 2025-06-06 17:55:58 -04:00
5134630525 Correct Exceptions 2025-06-06 17:37:42 -04:00
13b246b998 Merge remote-tracking branch 'origin/feature/cierres' into feature/cierres 2025-06-06 17:11:33 -04:00
d601d7d719 Mas logs y middlewares en Guzzle 2025-06-06 17:11:22 -04:00
dc0ae2746b FIX: Correct HMAC validation 2025-06-03 23:07:47 -04:00
eb402b1b71 FIX: notice logs 2025-06-03 23:07:08 -04:00
c5188a1feb HMAC not static 2025-06-03 23:04:57 -04:00
1c3052219c Debug 2025-06-03 22:59:49 -04:00
9e8a388653 Debug 2025-06-03 22:59:03 -04:00
cbee830f7a Debug 2025-06-03 22:55:35 -04:00
d5b8c7f877 FIX: JSON_SEARCH 2025-06-03 22:51:26 -04:00
b668844fea Debug 2025-06-03 22:29:13 -04:00
f2169c9536 FIX: fetch all values in column 2025-06-03 22:27:15 -04:00
48bcb33bad FIX: event_types -> events 2025-06-03 22:24:09 -04:00
92ae0b4ac2 FIX: Missing connection 2025-06-03 22:22:33 -04:00
44540d0dc3 Validated external query log 2025-06-03 22:19:11 -04:00
d9a2f63691 Use webhook secrets to validate 2025-06-03 22:11:57 -04:00
b10accf602 Store webhooks 2025-06-03 22:01:03 -04:00
981858f251 HMAC implementation for signature validation 2025-06-03 21:53:49 -04:00
8c0bd450ef FIX: delete url 2025-06-03 21:26:10 -04:00
8996765cb4 FIX: maxLogLevel 2025-06-03 21:16:44 -04:00
ec2451cb69 FIX: maxLogLevel 2025-06-03 21:12:43 -04:00
37d30d2aec Cleanup logs 2025-06-03 21:09:13 -04:00
afb6e2526f FIX: Timezone cli 2025-06-03 20:14:15 -04:00
a9b6f2a87b FIX: Error code for missing TOKU_ENV 2025-06-03 19:58:36 -04:00
9aeb6906f6 Debug 2025-06-03 19:43:46 -04:00
879d365baf Not needed 2025-06-03 19:42:23 -04:00
1d03b262ae Debug 2025-06-03 19:35:36 -04:00
2c175c8171 Detailed login errors 2025-06-03 19:20:55 -04:00
a750bdbfaa Detailed login errors 2025-06-03 19:20:44 -04:00
7f6d0232c0 Cleanup files 2025-06-03 19:20:09 -04:00
37cff67a1c Log reseteando 2025-06-03 17:06:39 -04:00
bc3d739af9 Cleanup 2025-06-03 16:52:01 -04:00
46efbb57c1 Log body de reset 2025-06-03 16:25:07 -04:00
d71333b334 Queue cada 2 minutos 2025-06-03 16:13:04 -04:00
688b500f1e Parametros correctos 2025-06-03 16:06:14 -04:00
d4b1a66a9e FIX: ventas_ids vacios 2025-06-03 16:02:04 -04:00
e796d91d95 Si token no existe, no se puede borrar 2025-06-03 16:01:48 -04:00
2a442417ce FIX: Loop frequency 2025-06-03 13:01:40 -04:00
3c161ed4e9 Loop frequency 2025-06-03 12:58:57 -04:00
3c8822e531 FIX: Log job requests 2025-06-03 12:46:47 -04:00
b3b91d3f8f Log job requests 2025-06-03 12:45:36 -04:00
6e34a76a3f FIX: Request log processor no funciona 2025-06-03 12:34:08 -04:00
ed29dfb984 Request Log Processor 2025-06-03 12:17:52 -04:00
7f37dc76e3 Log forbidden 2025-06-03 12:06:35 -04:00
a62293e509 Mejora en separacion 2025-06-03 12:06:02 -04:00
fbfc2cb8ae Cambios de usos de env vars 2025-06-03 12:04:53 -04:00
02665ac6bd Extras ya enviados por processor 2025-06-03 11:52:31 -04:00
300d966f3f Separation of logs in cli 2025-06-03 11:49:03 -04:00
27031035ed Filtro en server params faltante 2025-06-03 11:45:36 -04:00
18fc9a76fd Filtro en server params 2025-06-03 11:37:14 -04:00
cb6fa73a21 FIX: Recargar proyectos si no se encuentra proyecto_id, si aun no existe retornar 0 2025-06-03 10:35:07 -04:00
8796762cfe Mas datos en el registro de accessos 2025-06-03 10:24:54 -04:00
99c9952c93 Mas datos en el registro de logins. 2025-06-03 10:22:52 -04:00
9895fd6a70 FIX: Mas registro de login desde cli 2025-06-02 18:45:11 -04:00
c1149d89be FIX: Cleanup after create, but before initialized query. 2025-06-02 18:03:43 -04:00
7d8e2249de FIX: Detalle en logging. 2025-06-02 17:58:24 -04:00
a54586e870 FIX: valor cuota cuando UF no existe. 2025-05-30 17:10:59 -04:00
734f258382 Validar con headers 2025-05-30 14:18:48 -04:00
f728ed0b55 FIX: Log de envio 2025-05-30 12:48:12 -04:00
6144accb8e FIX: Toku envía complejo el header 2025-05-29 19:56:43 -04:00
f399eb8d47 Validate with service 2025-05-29 19:43:06 -04:00
b4159d1417 Log external tries 2025-05-29 19:24:35 -04:00
2a792a947d More granular control of external validation configuration 2025-05-29 19:22:55 -04:00
25710d616a Registro de success entrantes 2025-05-29 19:15:17 -04:00
3197802264 Cleanup 2025-05-29 19:10:09 -04:00
6c53127c2f Body json 2025-05-29 19:06:54 -04:00
b7391a77d3 DEBUG: body 2025-05-29 17:44:30 -04:00
5b499aee75 Content-type 2025-05-29 17:43:14 -04:00
4505531c5f Output body 2025-05-29 17:42:21 -04:00
3f8adc753c Add body to Enqueue command 2025-05-29 17:40:45 -04:00
ace205798f FIX: Manejo de Errores en Ventas 2025-05-29 16:02:13 -04:00
6e0e1fc75e Parametros faltantes 2025-05-27 19:30:08 -04:00
026474c63c Enqueue ventas para enviar a Toku 2025-05-27 19:24:23 -04:00
f32204df97 FIX: Remove toku concept in database 2025-05-27 18:35:06 -04:00
2852816eae FIX: Parametros extra para Toku 2025-05-27 18:27:37 -04:00
892cdf324f Comando para resetear Toku 2025-05-27 18:17:56 -04:00
a9a10e012d Uso de external Logger para los servicios External 2025-05-27 16:28:34 -04:00
b7089f7a1c Timezone por DI 2025-05-27 16:19:47 -04:00
aed26cfcd8 FIX: Estado cuota abono 2025-05-23 12:15:51 -04:00
896dded6eb Apellido materno en blanco 2025-05-23 12:12:34 -04:00
3b03c4b64b Logging 2025-05-19 16:06:44 -04:00
f34ed03b84 Logging 2025-05-19 14:02:55 -04:00
ce75ec1548 External logs
FIX: Ofuscator
2025-05-19 13:55:59 -04:00
312baa34f6 Access Logs 2025-05-19 13:14:13 -04:00
b7c5e4ebc3 Opcion de enviar update a los servicios externos 2025-05-16 19:14:20 -04:00
105179b4ed Fixes de telefono y apellido de persona 2025-05-16 16:35:17 -04:00
16cd29635d Zona horaria en cli 2025-05-16 14:47:31 -04:00
2bdb2a0ed0 Uso de zona horaria en output de comandos 2025-05-16 14:44:48 -04:00
8ce7d2570d FIX: Check if invoice exists before sending, if exists then save
Send correct UF amount if date in future
2025-05-16 14:36:20 -04:00
8ba54fd3ad Queue command with direct redis access so it's faster 2025-05-16 13:56:32 -04:00
f47f86dd2b BaseLoop different logger 2025-05-16 12:54:52 -04:00
8ca68bf7e8 Crontab para revisar servicios externos 1 vez al dia 2025-05-15 19:33:53 -04:00
8965354528 Cambio en queue para que no quede pegado esperando respuesta en cli.
Chequeo de servicios externos para agregar elementos pendientes.
2025-05-15 19:32:25 -04:00
8d32aecd09 Zona horaria en logs 2025-05-15 16:07:29 -04:00
c8f79e076e Envio de datos editados de Propietario 2025-05-15 16:05:55 -04:00
9e0d604d79 Respuesta 200 a webhook de Toku 2025-05-15 16:05:03 -04:00
331d004040 Eliminar script::type 2025-05-15 16:04:35 -04:00
03317b3aa5 Agregar datos propietario 2025-05-15 15:23:34 -04:00
e33edc4d7b FIX: proyectos minuto 0 de cada hora, en vez de cada minuto de esa hora 2025-05-15 12:08:33 -04:00
bb459a2ff5 FIX: proxy no identificado por web 2025-05-15 11:47:28 -04:00
5e2d2e861f Logs no pasan desbordan de nivel 2025-05-15 10:53:59 -04:00
e9b2fe9963 FIX: monto enviado en UF 2025-05-15 10:12:34 -04:00
2f481ef8a9 FIX: mapeo de datos al actualizar pago 2025-05-15 10:06:35 -04:00
386fe452af Catch error 2025-05-15 10:06:00 -04:00
91ad1e39f8 Endpoint para la prueba 2025-05-14 12:41:59 -04:00
a3a5b58cfb Correctos parametros 2025-05-13 20:19:03 -04:00
1d77d65af2 Ventas con cuotas pendientes 2025-05-13 20:18:51 -04:00
0f0c81e283 Uso de request en queue 2025-05-13 20:18:40 -04:00
ac278ca690 Parametros correctos para persona. 2025-05-13 20:18:20 -04:00
97d34f9ad6 Uso de request original 2025-05-13 20:18:09 -04:00
134588c96d Envio de estado de cuotas. 2025-05-13 20:17:53 -04:00
8b6516241d Manejo de contenido 2025-05-13 20:13:15 -04:00
d6e60efcaf Parametros correctos 2025-05-13 20:12:26 -04:00
3e937ab748 Fetch ventas con cuotas pendientes 2025-05-13 20:11:49 -04:00
fa6881d0a9 Formato correcto de fecha y bool 2025-05-13 20:11:02 -04:00
f07c1f1cbd Formato correcto de fecha 2025-05-13 20:10:46 -04:00
148d08089d Estado Cuota y Pago 2025-05-13 20:10:24 -04:00
45b6ee710e Job mas completo 2025-05-13 20:10:12 -04:00
c84277fdc4 Update services 2025-05-13 20:09:50 -04:00
c0024a4a63 Parse body correctly and test fill 2025-05-13 20:03:20 -04:00
308a84a448 Send current request to queue for parameters 2025-05-13 20:02:50 -04:00
91c74bf113 Min log level 2025-05-13 16:17:47 -04:00
024a6eae54 Jobs not being updated 2025-05-13 16:06:09 -04:00
d536342425 No output on wait 2025-05-13 15:58:49 -04:00
e7f3b33850 Wait till next minute after running jobs 2025-05-13 15:53:13 -04:00
c47d94d475 FIX: missing use 2025-05-13 15:49:41 -04:00
ee74fc7588 FIX: esperar al siguiente minuto 2025-05-13 15:47:18 -04:00
5ac324de6a Hora en output 2025-05-13 15:40:32 -04:00
dfb0ff7aea Missing middlewares 2025-05-13 15:16:29 -04:00
6d1a1c914a Wait for execution 2025-05-13 15:15:20 -04:00
b45d03aa7e Reestructura APIClient 2025-05-13 09:32:48 -04:00
4e0b611bcf FIX: Mayuscula 2025-05-13 09:31:51 -04:00
20ea5d021d FIX: missing text 2025-05-12 19:58:20 -04:00
32dc24a783 Newline 2025-05-12 19:54:03 -04:00
95a6aa96e9 Queue 2025-05-12 19:46:31 -04:00
f14cdd2730 Updates 2025-05-12 19:46:09 -04:00
3006adb0f7 Configuracion servicios 2025-05-12 19:44:58 -04:00
d22480dcb8 User edit and delete 2025-05-12 19:44:16 -04:00
425b85e40d Unify cli logs 2025-05-12 19:44:00 -04:00
2c21e48562 FIX: DEPRECATED 2025-05-12 19:43:39 -04:00
8d3ce99be7 Update env sample 2025-05-12 18:32:30 -04:00
35386724b3 FIX: DEPRECATED 2025-05-12 18:07:14 -04:00
1597657f0e FIX: Toku external 2025-05-12 16:35:33 -04:00
c6bbaf3404 FIX: DEPRECATED 2025-05-12 16:08:10 -04:00
9e2d7277b0 Validacion API/external 2025-05-12 16:01:09 -04:00
abe37227ce API/external 2025-05-12 15:47:51 -04:00
32130f0bc2 Usando variables definidas 2025-05-12 14:04:58 -04:00
d78bdaa7f5 Falta ortografia 2025-05-12 13:57:43 -04:00
1266c3859d Migration for Jobs 2025-05-12 13:54:28 -04:00
c5466b2c4d Ignore optionals 2025-05-12 13:15:22 -04:00
6d8e8a9068 Env sample update 2025-05-12 13:06:44 -04:00
4d5b657b92 Manejo de trabajos en cli por php en vez de cron 2025-05-10 12:40:06 -04:00
4ca1616dfc Integracion Toku a flujo 2025-05-10 12:39:31 -04:00
fb7177fd65 Reorden Toku 2025-05-10 12:38:14 -04:00
1486d6cf38 Toku settings 2025-05-10 12:32:01 -04:00
8b2de31e02 Job Queue 2025-05-10 12:30:35 -04:00
61324f159b Toku endpoint 2025-05-10 12:30:21 -04:00
c95e74d574 Controlador Toku 2025-05-09 18:31:00 -04:00
59ecb6cc79 Se agregan fetchs 2025-05-09 18:05:40 -04:00
db84187461 Pruebas de Toku 2025-05-09 18:05:19 -04:00
c2f98c8b0d Excepcion 2025-05-09 18:04:37 -04:00
8d73987ac3 FIX: Cambios a Servicios Toku 2025-05-09 18:04:17 -04:00
400b2754bf FIX: Totales para multipropietario no sumaban correctamente 2025-05-09 13:33:08 -04:00
418becaeda FIX: onChange 2025-05-08 18:15:32 -04:00
679b401101 Servicio Toku para enviar datos 2025-05-08 17:17:49 -04:00
26b6862955 FIX: prueba Servicio Customer 2025-05-08 17:17:24 -04:00
e239669839 FIX: prueba modelo Customer 2025-05-08 17:16:55 -04:00
adc0e52c1e Fix: estructura interface 2025-05-08 17:16:32 -04:00
d1905194bd rut en Customer en formato Toku 2025-05-08 17:16:03 -04:00
a5c1d60819 Servicios para Toku 2025-05-08 16:17:26 -04:00
5ad4fc4038 Tests de Repositories 2025-05-08 16:17:14 -04:00
ca5354a3ee Cambio en namespace 2025-05-08 11:13:23 -04:00
c1ebac6c0c Pruebas de repositories 2025-05-08 11:13:06 -04:00
f742c7ddd0 Pruebas de modelos 2025-05-08 10:45:31 -04:00
5d5f9866bb Modelos para Toku 2025-05-07 20:05:00 -04:00
0866292d84 Migraciones para guardar datos de Toku 2025-05-07 20:04:27 -04:00
e02ed4684f LoggerAwareInterface abstract 2025-05-07 20:04:06 -04:00
8be5f94b7c Log solo los errores fatales. 2025-05-07 20:01:55 -04:00
878b02ee52 SII falla si fecha está en el futuro. 2025-05-07 19:42:39 -04:00
f3e15b34a8 Persona conectada con Propietario 2025-05-07 19:24:33 -04:00
3903551176 FIX: migraciones fallando 2025-05-07 19:23:37 -04:00
43eb8ec758 FIX: no borra todo 2025-05-07 19:22:39 -04:00
a405b15410 Uso de script central de Rut 2025-05-06 10:00:12 -04:00
a2f2d94e64 Docker image con tag 2025-05-06 09:47:54 -04:00
0587b64d65 Docker image 2025-05-06 09:37:23 -04:00
a6b81f1bff FIX: Not needed 2025-05-06 09:15:46 -04:00
4239bafc26 FIX: echo append 2025-05-05 19:33:46 -04:00
6591e9f80e FIX: debian ftp 2025-05-05 19:33:01 -04:00
b57f32c86b FIX: Circular dependency 2025-05-05 19:10:31 -04:00
0e903f99c4 FIX: Circular dependency 2025-05-05 19:08:44 -04:00
186cd0f5b8 Reparaciones con Prueba 2025-05-05 19:01:15 -04:00
167d8e1ab7 PHP Dom en PHP 8.4 2025-05-05 19:00:41 -04:00
46802507a7 SII como provider de UF 2025-05-05 18:16:18 -04:00
aaf2ed7612 UF service en Venta 2025-05-05 18:15:48 -04:00
3ced9e40b1 const en Money y multi provider 2025-05-05 18:15:29 -04:00
594cb68b09 Provider SII 2025-05-05 18:14:50 -04:00
af68c4b8ec Ine null date 2025-05-05 18:14:20 -04:00
ea8f483dd5 FIX: Repository UF 2025-05-05 18:13:55 -04:00
5f53c77a1f Repository::getConnection 2025-05-05 18:13:12 -04:00
b9adb9108b Provider null date 2025-05-05 18:12:58 -04:00
8be085222a Not Allowed template 2025-05-05 16:46:41 -04:00
d1e4314b35 Valor de UF de hoy cuando no se encuentra valor. 2025-05-05 16:46:14 -04:00
7d04b406ab Grabar UF y capacidad de obtener hoy. 2025-05-05 16:45:43 -04:00
972e57b6f1 Mejora en respuesta cuando no existe algun valor. 2025-05-05 16:43:24 -04:00
5f63bdbf4a Fecha maxima de venta es hoy 2025-05-05 16:41:08 -04:00
a8325c3310 Uso de NumberInput en Edit BonoPie 2025-05-05 15:55:23 -04:00
7e54b72587 NumberInput, para formateo de numeros 2025-05-05 15:45:07 -04:00
ebe31a3d3d Guardar UF en DB 2025-05-05 15:40:55 -04:00
db6445bcf3 Cleanup View 2025-05-05 15:40:26 -04:00
4e1901b7c8 FatalErrors 2025-05-05 15:40:05 -04:00
c3316029c9 Se borra migracion duplicada 2025-05-05 14:01:39 -04:00
cbfc796685 Merge remote-tracking branch 'origin/feature/cierres' into feature/cierres 2025-05-05 11:35:29 -04:00
da56192f97 Formateo de numeros en JS 2025-04-30 23:36:32 -04:00
b5d08620f9 Unidades que no son departamentos 2025-04-30 17:13:40 -04:00
c92b07ee6f Excepcion correcta 2025-04-30 17:13:26 -04:00
ee6956d417 Reorden 2025-04-30 16:18:20 -04:00
21d5e2d03b Api en archivo separado 2025-04-30 16:18:00 -04:00
73a742c01e Nada en public 2025-04-30 10:51:47 -04:00
dd42c12d49 Orden 2025-04-30 10:38:20 -04:00
41ea5f5c15 Update prueba 2025-04-30 10:38:05 -04:00
eeb6f5bcd1 Se agrega condicion 2025-04-30 10:37:57 -04:00
2680f51167 Correccion migracion 2025-04-30 10:37:41 -04:00
019d57a0b0 Nuevas pruebas 2025-04-30 01:12:23 -04:00
1a400d9a5c Watcher solo para unit tests 2025-04-30 01:12:09 -04:00
6276f87274 Pruebas nuevas 2025-04-30 00:14:38 -04:00
28c93a42bc Logs de pruebas 2025-04-30 00:14:24 -04:00
4ff5d28522 Nuevas pruebas 2025-04-29 23:57:59 -04:00
a93642c55d Actualizacion de pruebas con extensiones 2025-04-29 23:57:49 -04:00
87c0d8c8d9 Se mueve todo a extension de pruebas 2025-04-29 23:55:51 -04:00
dd1741a930 Broker test 2025-04-29 23:21:19 -04:00
ad0fd82a9e Assert nuevo 2025-04-29 23:21:13 -04:00
bae5c1740d No mas require 2025-04-29 23:19:05 -04:00
f5f1482b7a Autoload para pruebas 2025-04-29 23:18:55 -04:00
4bd5fe16df Comandos para correr pruebas y consola 2025-04-29 23:18:18 -04:00
61845fbd05 Ignorar datos de pruebas 2025-04-29 22:26:26 -04:00
f8ac0f14f0 Abstracts 2025-04-29 22:25:32 -04:00
acb7a1336d Coverage lento e innecesario 2025-04-29 22:25:11 -04:00
8af56137a8 Seeds al migrar 2025-04-29 21:51:19 -04:00
c3247838b3 Namespace test Servicio Valor 2025-04-29 21:43:21 -04:00
dd82ac6bb7 Tests Home 2025-04-29 21:42:57 -04:00
2acf0362fa Ambiente de testeo 2025-04-29 21:41:49 -04:00
e6892ee085 Valor de PU cuando unidad no tiene valor 2025-04-29 13:01:57 -04:00
86b8d6b3c7 Limpieza 2025-04-29 13:01:21 -04:00
53115b085f Asegurarse que el valor entregado a Pago es en pesos. 2025-04-29 11:29:23 -04:00
c3b7427f60 Cambio en nombre de metodo y uso de valor maximo para UF 2025-04-29 11:20:49 -04:00
5d939f970b Valor con pruebas 2025-04-28 20:20:43 -04:00
4845801b27 Uso de script central de rut 2025-04-28 19:00:40 -04:00
d5bf9a7660 Digito verificador 2025-04-28 18:59:37 -04:00
795dda868b Ya no se incluye UF/m² y se transforman en numeros las UF 2025-04-25 20:03:11 -04:00
53a3633dc7 Menu -> Agregar Venta separado 2025-04-25 20:02:24 -04:00
0143fd11ac Se pasan datos a EmptyResult en base- 2025-04-25 19:41:42 -04:00
55745a8d0a EmptyResult ahora puede llevar los datos. 2025-04-25 19:41:23 -04:00
2a1930c5f7 FIX: Propiedad con unidad_principal 2025-04-25 19:25:16 -04:00
31f49dddb6 FIX: unidad_principal no tiene valor por defecto. 2025-04-25 17:36:12 -04:00
b4ca59fb6d Optimizacion de obtencion de datos. 2025-04-24 19:23:39 -04:00
d910f3eb69 FIX: Propiedad sin unidad_principal 2025-04-24 18:54:54 -04:00
555cdb7138 Promociones en misma tabla para tipo 2025-04-24 18:50:04 -04:00
65088da2f5 Promociones en misma tabla para tipo 2025-04-23 16:49:52 -04:00
966b341b65 Listado de promociones 2025-04-22 18:34:23 -04:00
90b05ca25c Se elimina la comision del excel 2025-04-22 16:28:13 -04:00
bb3a2fffa1 Cuando no existen promociones 2025-04-22 15:38:30 -04:00
8a5e41a722 Normalizacion con profundidad 2025-04-22 15:31:55 -04:00
5736a346e7 Valor debiese ser el último precio. 2025-04-22 15:24:11 -04:00
4f4e69f0c3 FIX: no tiene precio ahora, solo valor 2025-04-22 15:19:25 -04:00
00deebeaa8 FIX: faltaba valor 2025-04-22 15:19:08 -04:00
aee0754b5a Simplificacion de retorno de ventas por unidades 2025-04-22 15:18:59 -04:00
eabdab23c3 Simplificacion de retorno de ventas por unidades 2025-04-22 13:08:15 -04:00
5147450ed6 Manejo de excepciones 2025-04-22 13:07:52 -04:00
ed96f25475 Mayor orden 2025-04-22 11:49:34 -04:00
d5a3512852 Barras de progreso 2025-04-22 11:35:56 -04:00
d6730cd020 Cambio en link 2025-04-22 09:29:14 -04:00
c7dddc818c Definicion de variables una sola vez 2025-04-22 09:28:45 -04:00
33b4182bd3 Optimizacion de queries a cargar de una sola vez 2025-04-22 09:28:12 -04:00
fc776e6cec Ruta para Ventas por unidades 2025-04-21 19:43:20 -04:00
5d79ea83c3 Mostrar valor de venta para unidades vendidas 2025-04-21 19:43:01 -04:00
c34048a53a Ventas por unidades 2025-04-21 19:41:20 -04:00
f7af93b815 Throw Read 2025-04-21 19:40:26 -04:00
993e4ff3b8 Merge branch 'develop' into feature/cierres 2025-04-11 13:35:13 -04:00
bc49ba7629 FIX: Busqueda no funcionaba 2025-04-09 09:29:53 -04:00
3c2b486083 Se agregan columnas y el calculo de promociones de tipo fijo 2025-04-08 19:04:46 -04:00
76f69f3bda Optimizacion simple 2025-04-08 18:38:18 -04:00
8ba3c456b6 Link a contrato en vez del proyecto 2025-04-08 18:35:07 -04:00
98b18fab3e Cambios solicitados 2025-04-08 18:30:14 -04:00
12a4831887 Merge branch 'develop' into feature/cierres 2025-04-04 13:23:00 -03:00
da46914de4 Promociones en Contrato 2025-04-04 12:56:49 -03:00
596bc71cf8 Mejoras UI 2025-04-04 12:54:51 -03:00
7f8e4ea943 FIX: query fallaba 2025-04-04 12:36:03 -03:00
5456485f71 FIX: ya no existe relacion con contratos 2025-04-04 12:08:46 -03:00
836503a71b Menus nuevos 2025-04-04 12:08:24 -03:00
4df0cca675 Filtro en excel 2025-04-04 11:53:25 -03:00
00a0adb4ac Espacio mas ajustado 2025-04-04 11:53:11 -03:00
037fcd60f3 Orden de queries 2025-04-04 11:52:50 -03:00
7a97fc9dfe Precios con promociones para listado brokers 2025-04-03 17:22:38 -03:00
7b2df74e4d Promociones para cada subdivicion 2025-04-03 17:22:11 -03:00
b5d6d0acb9 Mostrar porcentajes en venta 2025-04-03 13:56:11 -03:00
8a1e6a7761 Conecciones de Promociones 2025-04-03 13:15:56 -03:00
ced673e452 Correcto nombre de tabla 2025-04-03 13:12:57 -03:00
8a7a1d4e64 Merge branch 'develop' into feature/cierres 2025-03-27 11:44:54 -03:00
9be20ab1cd UF 0 o nula actualizadas para Pago y Pie 2025-03-26 16:54:53 -03:00
1c40f18624 Pagos sin uf retornan 0 2025-03-26 16:49:27 -03:00
db36549699 Agregar Pie 2025-03-26 16:41:54 -03:00
4ce83fb270 Merge branch 'develop' into feature/cierres 2025-03-26 15:42:47 -03:00
b191a01313 Promociones 2025-03-25 19:22:38 -03:00
d3b0026ca4 Agregar, editar y eliminar promociones 2025-03-18 19:13:47 -03:00
2b3f476df7 Agregar, editar y eliminar promociones 2025-03-18 19:12:59 -03:00
39c148b7b3 Cambio nombre archivo 2025-03-17 23:03:06 -03:00
bae0f1f555 Separacion de Promocion de Contrato y Precio
"Simplificacion" de datos en listado de precios
2025-03-17 22:49:48 -03:00
2e49e2c947 Listados separados por hojas (tabs) 2025-03-13 13:16:20 -03:00
68aebdb4fe Listado de Precios para Contrato Broker 2025-03-13 12:18:08 -03:00
346001db8e SearchBuilder configuration centralizada
FIX: CentroCosto TipoCuenta
2025-03-13 09:33:42 -03:00
8b04eb262f FIX: Editar datos Broker 2025-03-12 18:31:21 -03:00
7c7c8315e2 Editar Brokers y sus contratos 2025-03-11 17:41:11 -03:00
510e05e5ca FIX: rut con otros caracteres y maximo largo 2025-03-07 17:26:36 -03:00
5055d2703c Broker Contact 2025-03-07 17:11:59 -03:00
2bc30ab9e8 Formatear porcentajes menores a 1 2025-03-07 17:11:15 -03:00
c7ee440e03 Listado de brokers 2025-03-06 20:34:43 -03:00
18dd8c4ec0 Merge branch 'develop' into feature/cierres 2025-03-06 16:23:58 -03:00
8ea4995f6b Contratos desde proyectos 2025-03-03 21:46:53 -03:00
aeeca65d94 Correcciones 2025-03-03 21:41:43 -03:00
5f69069aa0 Rutas Reservations 2025-03-03 16:53:36 -03:00
095a65a643 Cleanup por recomendaciones 2025-03-03 16:37:40 -03:00
928d2e57be Merge branch 'develop' into feature/cierres 2025-03-03 15:32:25 -03:00
2a0335f834 Reservation Controller 2025-03-03 15:21:18 -03:00
9ccf53fa4e Reservation Service 2025-03-03 15:21:12 -03:00
ef54c36edc Cleanup 2025-03-03 14:56:18 -03:00
4aa88d5164 Rutas API Contratos 2025-03-03 11:26:45 -03:00
8ea13c3efd API Contratos 2025-03-03 10:47:48 -03:00
12e3d7ed3b Servicio Contratos 2025-03-01 13:26:55 -03:00
a7fc89ac29 Merge branch 'develop' into feature/cierres 2025-02-24 21:36:35 -03:00
a71df4e70d Controlador y ruta de operadores para API 2025-02-24 12:41:50 -03:00
f17b7a758a withJson con error 2025-02-24 12:41:34 -03:00
7fb28cd44c Servicio operadores 2025-02-24 12:41:13 -03:00
a44bd610ad Excepciones de servicios 2025-02-24 12:41:00 -03:00
28bba8a438 Actualizacion de Modelos 2025-02-24 12:40:40 -03:00
0ec6ebdafe Actualizacion de Repos 2025-02-24 12:39:42 -03:00
3ebe256a66 Actualizacion de migraciones 2025-02-24 12:39:25 -03:00
9d135e2c26 Base de Datos 2025-02-18 16:02:10 -03:00
345 changed files with 16534 additions and 872 deletions

View File

@ -1,4 +1,4 @@
FROM php:8.2-cli
FROM php:8.4-cli
ENV TZ "${TZ}"
ENV APP_NAME "${APP_NAME}"
@ -6,11 +6,14 @@ ENV API_URL "${API_URL}"
RUN apt-get update && apt-get install -y --no-install-recommends cron rsyslog nano && rm -r /var/lib/apt/lists/*
RUN pecl install xdebug-3.2.2 \
RUN pecl install xdebug-3.4.2 \
&& docker-php-ext-enable xdebug \
&& echo "#/bin/bash\nprintenv >> /etc/environment\ncron -f -L 11" > /root/entrypoint && chmod a+x /root/entrypoint
&& echo $TZ > /etc/timezone
COPY --chmod=550 ./cli/entrypoint /root/entrypoint
COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini
COPY ./php-timezone.ini /usr/local/etc/php/conf.d/docker-php-timezone.ini
WORKDIR /code/bin

View File

@ -1,11 +1,12 @@
FROM php:8.2-fpm
FROM php:8.4-fpm
ENV TZ=America/Santiago
RUN apt-get update && apt-get install -y --no-install-recommends libzip-dev libicu-dev git libpng-dev unzip tzdata \
RUN apt-get update && apt-get install -y --no-install-recommends libzip-dev libicu-dev git \
libpng-dev unzip tzdata libxml2-dev \
&& rm -r /var/lib/apt/lists/* \
&& docker-php-ext-install pdo pdo_mysql zip intl gd bcmath \
&& pecl install xdebug-3.3.2 \
&& docker-php-ext-install pdo pdo_mysql zip intl gd bcmath dom \
&& pecl install xdebug-3.4.2 \
&& docker-php-ext-enable xdebug \
&& echo $TZ > /etc/timezone

View File

@ -2,17 +2,18 @@
APP_URL=
MYSQL_HOST=db
COOKIE_NAME=
COOKIE_DOMAIN=
COOKIE_PATH=/
MAX_LOGIN_HOURS=120
REDIS_HOST=redis
REDIS_PORT=6379
#REDIS_HOST=redis
#REDIS_PORT=6379
DB_HOST=db
DB_DATABASE=incoviba
DB_USER=incoviba
DB_PASSWORD=
TOKU_URL=
TOKU_TOKEN=

1
app/.gitignore vendored
View File

@ -1 +1,2 @@
**/bin
**/public/tests

View File

@ -10,5 +10,5 @@ notifications:
failingTests: false
hideManual: true
phpunit:
arguments: '--log-events-text /logs/output.txt --stop-on-failure'
arguments: '--testsuite unit --log-events-text /logs/output.txt --stop-on-failure'
timeout: 180

3
app/bin/console Normal file
View File

@ -0,0 +1,3 @@
#!/usr/bin/bash
php -d auto_prepend_file=test.bootstrap.php -a

View File

@ -0,0 +1,3 @@
#!/usr/bin/bash
bin/phpunit --testsuite acceptance $@

View File

@ -0,0 +1,3 @@
#!/usr/bin/bash
bin/phpunit --testsuite performance $@

3
app/bin/unit_tests Normal file
View File

@ -0,0 +1,3 @@
#!/usr/bin/bash
./bin/phpunit --testsuite unit $@

View File

@ -1,9 +1,6 @@
<?php
namespace Incoviba\Common\Alias;
use Illuminate\Events\Dispatcher;
use Slim\Views\Blade;
class View extends Blade
{
}
class View extends Blade {}

View File

@ -8,9 +8,9 @@ interface Provider
{
/**
* @param string $money_symbol
* @param DateTimeInterface $dateTime
* @param ?DateTimeInterface $dateTime = null
* @return float
* @throws EmptyResponse
*/
public function get(string $money_symbol, DateTimeInterface $dateTime): float;
public function get(string $money_symbol, ?DateTimeInterface $dateTime = null): float;
}

View File

@ -0,0 +1,18 @@
<?php
namespace Incoviba\Common\Ideal;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
abstract class LoggerEnabled implements LoggerAwareInterface
{
protected LoggerInterface $logger;
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
public function getLogger(): LoggerInterface
{
return $this->logger;
}
}

View File

@ -24,6 +24,11 @@ abstract class Repository implements Define\Repository
return $this;
}
public function getConnection(): Define\Connection
{
return $this->connection;
}
public function load(array $data_row): Define\Model
{
$model = $this->create($data_row);
@ -189,7 +194,7 @@ abstract class Repository implements Define\Repository
try {
$this->connection->execute($query, $values);
} catch (PDOException $exception) {
throw new EmptyResult($query, $exception);
throw new EmptyResult($query, $exception, $data);
}
return $this->fetchById($this->getIndex($model));
}
@ -205,10 +210,10 @@ abstract class Repository implements Define\Repository
try {
$result = $this->connection->execute($query, $data)->fetch(PDO::FETCH_ASSOC);
if ($result === false) {
throw new EmptyResult($query);
throw new EmptyResult($query, null, $data);
}
} catch (PDOException $exception) {
throw new EmptyResult($query, $exception);
throw new EmptyResult($query, $exception, $data);
}
return $this->load($result);
}
@ -224,7 +229,7 @@ abstract class Repository implements Define\Repository
try {
$results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $exception) {
throw new EmptyResult($query, $exception);
throw new EmptyResult($query, $exception, $data);
}
return array_map([$this, 'load'], $results);
}
@ -240,7 +245,7 @@ abstract class Repository implements Define\Repository
try {
$results = $this->connection->execute($query, $data)->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $exception) {
throw new EmptyResult($query, $exception);
throw new EmptyResult($query, $exception, $data);
}
return $results;
}

View File

@ -0,0 +1,56 @@
<?php
namespace Incoviba\Common\Ideal\Service;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Exception\ServiceAction;
abstract class API extends Ideal\Service
{
public function __construct(LoggerInterface $logger)
{
parent::__construct($logger);
}
/**
* @param string|array|null $order
* @return array
*/
abstract public function getAll(null|string|array $order = null): array;
/**
* @param int $id
* @return Define\Model
* @throws ServiceAction\Read
*/
abstract public function get(int $id): Define\Model;
/**
* @param array $data
* @return Define\Model
* @throws ServiceAction\Create
*/
abstract public function add(array $data): Define\Model;
/**
* @param Define\Model $model
* @param array $new_data
* @return Define\Model
* @throws ServiceAction\Update
*/
abstract public function edit(Define\Model $model, array $new_data): Define\Model;
/**
* @param int $id
* @return Define\Model
* @throws ServiceAction\Delete
*/
abstract public function delete(int $id): Define\Model;
/**
* @param Define\Model $model
* @return Define\Model
*/
abstract protected function process(Define\Model $model): Define\Model;
}

View File

@ -81,6 +81,9 @@ class Insert extends Ideal\Query implements Define\Query\Insert
if ($value === (int) $value) {
return $value;
}
if (str_starts_with($value, ':')) {
return $value;
}
return "'{$value}'";
}, $this->values)) . ')';
}

View File

@ -6,10 +6,15 @@ use Throwable;
class EmptyResult extends Exception
{
public function __construct(public string $query, ?Throwable $previous = null)
public function __construct(public string $query, ?Throwable $previous = null, protected ?array $data = null)
{
$message = "Empty results for {$query}";
$code = 700;
parent::__construct($message, $code, $previous);
}
public function getData(): ?array
{
return $this->data;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Incoviba\Common\Implement\Exception;
use Throwable;
use Exception;
class HttpException extends Exception
{
public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace Incoviba\Common\Implement\Log\Formatter;
use Throwable;
use Monolog\Formatter\JsonFormatter;
use Monolog\LogRecord;
class PDO extends JsonFormatter
{
public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = true)
{
parent::__construct($batchMode, $appendNewline, $ignoreEmptyContextAndExtra, $includeStacktraces);
}
public function format(LogRecord $record): string
{
if (is_a($record->message, Throwable::class)) {
$exception = $record->message;
$message = $this->normalizeException($exception);
$context = $record->context;
$context['exception'] = $exception;
if ($exception->getPrevious()) {
$context['previous'] = $this->walkException($exception);
}
$new_record = new LogRecord(
$record->datetime,
$record->channel,
$record->level,
json_encode($message),
$context,
$record->extra
);
$record = $new_record;
}
$normalized = $this->normalize($record, $this->maxNormalizeDepth);
return $normalized['message'];
}
protected function walkException(Throwable $exception, int $depth = 0): array
{
$output = [];
$currentDepth = $depth;
while ($previous = $exception->getPrevious() and $currentDepth < $this->maxNormalizeDepth) {
$output []= $this->normalizeException($previous);
}
return $output;
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace Incoviba\Common\Implement\Log;
namespace Incoviba\Common\Implement\Log\Handler;
use PDOStatement;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\LogRecord;
use Monolog\Level;
use Incoviba\Common\Define\Connection;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Level;
use Monolog\LogRecord;
use PDOStatement;
class MySQLHandler extends AbstractProcessingHandler
class MySQL extends AbstractProcessingHandler
{
private bool $initialized = false;
private PDOStatement $statement;
@ -19,9 +19,12 @@ class MySQLHandler extends AbstractProcessingHandler
public function write(LogRecord $record): void
{
if (!$this->initialized) {
if (!$this->checkTableExists()) {
$this->createTable();
}
$this->cleanup();
$this->initialized();
}
$this->cleanup();
$this->statement->execute([
'channel' => $record->channel,
'level' => $record->level->getName(),
@ -35,6 +38,21 @@ class MySQLHandler extends AbstractProcessingHandler
private function initialized(): void
{
$query = <<<QUERY
INSERT INTO monolog (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
$this->statement = $this->connection->getPDO()->prepare($query);
$this->initialized = true;
}
private function checkTableExists(): bool
{
$query = "SHOW TABLES LIKE 'monolog'";
$result = $this->connection->query($query);
return $result->rowCount() > 0;
}
private function createTable(): void
{
$query = <<<QUERY
CREATE TABLE IF NOT EXISTS monolog (
channel VARCHAR(255),
level VARCHAR(100),
@ -45,12 +63,6 @@ CREATE TABLE IF NOT EXISTS monolog (
)
QUERY;
$this->connection->getPDO()->exec($query);
$query = <<<QUERY
INSERT INTO monolog (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
$this->statement = $this->connection->getPDO()->prepare($query);
$this->initialized = true;
}
private function cleanup(): void
{

View File

@ -1,19 +0,0 @@
<?php
namespace Incoviba\Common\Implement\Log;
use Monolog\Formatter\JsonFormatter;
use Monolog\LogRecord;
class PDOFormatter extends JsonFormatter
{
public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = true)
{
parent::__construct($batchMode, $appendNewline, $ignoreEmptyContextAndExtra, $includeStacktraces);
}
public function format(LogRecord $record): string
{
$normalized = $this->normalize($record);
return $normalized['message'];
}
}

View File

@ -0,0 +1,139 @@
<?php
namespace Incoviba\Common\Implement\Log\Processor;
use DateInvalidTimeZoneException;
use DateMalformedStringException;
use DateTimeImmutable;
use DateTimeZone;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Monolog\Formatter;
use Monolog\Handler;
use Monolog\Level;
use Predis;
use Incoviba;
use Throwable;
class ArrayBuilder
{
public function __construct(protected ContainerInterface $container) {}
public function build(array $data): array
{
$handlers = [];
foreach ($data as $handlerData) {
if (in_array($handlerData['handler'], [Handler\StreamHandler::class, Handler\RotatingFileHandler::class,])) {
$params = [
"/logs/{$handlerData['filename']}",
];
if ($handlerData['handler'] === Handler\RotatingFileHandler::class) {
$params []= 10;
}
try {
$formatter = Formatter\LineFormatter::class;
if (array_key_exists('formatter', $handlerData)) {
$formatter = $handlerData['formatter'];
}
$handler = new $handlerData['handler'](...$params)
->setFormatter($this->container->get($formatter));
} catch (NotFoundExceptionInterface | ContainerExceptionInterface $exception) {
$this->log($exception, ['handlerData' => $handlerData]);
continue;
}
} elseif ($handlerData['handler'] === Incoviba\Common\Implement\Log\Handler\MySQL::class) {
try {
$params = [
$this->container->get(Incoviba\Common\Define\Connection::class)
];
$formatter = Incoviba\Common\Implement\Log\Formatter\PDO::class;
if (array_key_exists('formatter', $handlerData)) {
$formatter = $handlerData['formatter'];
}
$handler = new $handlerData['handler'](...$params)
->setFormatter($this->container->get($formatter));
} catch (NotFoundExceptionInterface | ContainerExceptionInterface $exception) {
$this->log($exception, ['handlerData' => $handlerData]);
continue;
}
} elseif ($handlerData['handler'] === Handler\RedisHandler::class) {
try {
$params = [
$this->container->get(Predis\ClientInterface::class),
"logs:{$handlerData['name']}"
];
} catch (NotFoundExceptionInterface | ContainerExceptionInterface $exception) {
$this->log($exception, ['handlerData' => $handlerData]);
continue;
}
$handler = new $handlerData['handler'](...$params);
}
if (!isset($handler)) {
$this->log("Invalid handler", ['handlerData' => $handlerData]);
continue;
}
$params = [
$handler,
];
if (is_array($handlerData['levels'])) {
foreach ($handlerData['levels'] as $level) {
$params []= $level;
}
} else {
$params []= $handlerData['levels'];
$params []= Level::Emergency;
}
$params []= false;
$handlers []= new Handler\FilterHandler(...$params);
}
return $handlers;
}
protected function log(string|Throwable $message, array $context = []): void
{
try {
$dateTime = new DateTimeImmutable('now', new DateTimeZone($_ENV['TZ'] ?? 'America/Santiago'));
} catch (DateMalformedStringException | DateInvalidTimeZoneException $exception) {
$dateTime = new DateTimeImmutable();
}
if (is_a($message, Throwable::class)) {
$exception = $message;
$message = $exception->getMessage();
}
$context = json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if ($context === false) {
$context = '[]';
}
$extra = [];
$extra['from'] = __FILE__;
if (isset($exception)) {
$extra['file'] = $exception->getFile();
$extra['line'] = $exception->getLine();
$extra['trace'] = $exception->getTrace();
}
$extra = json_encode($extra, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$code = 0;
if (isset($exception)) {
$code = $exception->getCode();
}
if ($extra === false) {
$extra = '[]';
}
$output = "[{$dateTime->format('Y-m-d H:i:s P')}] [{$code}] {$message} {$context} {$extra}";
$filename = '/logs/error.json';
$fileContents = [];
if (file_exists($filename)) {
$fileContents = file_get_contents($filename);
$fileContents = json_decode($fileContents, true);
if ($fileContents === false) {
$fileContents = [];
}
}
$fileContents[$dateTime->getTimestamp()] = $output;
$fileContents = json_encode($fileContents, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if ($fileContents === false) {
$fileContents = '[]';
}
file_put_contents($filename, $fileContents);
}
}

View File

@ -1,11 +1,11 @@
<?php
namespace Incoviba\Common\Implement\Log;
namespace Incoviba\Common\Implement\Log\Processor;
use Incoviba\Service;
use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
use Incoviba\Service;
class UserProcessor implements ProcessorInterface
class User implements ProcessorInterface
{
public function __construct(protected Service\Login $loginService) {}
public function __invoke(LogRecord $record): LogRecord

View File

@ -4,6 +4,7 @@
"type": "project",
"require": {
"ext-curl": "*",
"ext-dom": "*",
"ext-gd": "*",
"ext-openssl": "*",
"ext-pdo": "*",
@ -18,7 +19,8 @@
"predis/predis": "^2",
"robmorgan/phinx": "^0.16",
"slim/slim": "^4",
"symfony/string": "^7.2"
"symfony/string": "^7.2",
"tedivm/jshrink": "^1.7"
},
"require-dev": {
"fakerphp/faker": "^1",

View File

@ -28,16 +28,15 @@
<directory>common</directory>
</include>
</source>
<coverage pathCoverage="false" ignoreDeprecatedCodeUnits="true" disableCodeCoverageIgnore="true">
<!--<coverage pathCoverage="false" ignoreDeprecatedCodeUnits="true" disableCodeCoverageIgnore="true">
<report>
<html outputDirectory="/code/public/coverage/html"/>
<php outputFile="/code/public/coverage/coverage.php"/>
</report>
</coverage>
</coverage>-->
<logging>
<junit outputFile="/code/cache/tests/junit.xml"/>
<teamcity outputFile="/code/cache/tests/teamcity.txt"/>
<testdoxHtml outputFile="/code/cache/tests/testdox.html"/>
<!--<testdoxHtml outputFile="/code/public/tests/testdox.html"/>-->
<testdoxText outputFile="/code/cache/tests/testdox.txt"/>
</logging>
</phpunit>

View File

@ -13,3 +13,12 @@ try {
$app->getContainer()->get(Psr\Log\LoggerInterface::class)->notice($exception);
header('Location: /construccion');
}
register_shutdown_function(function() {
$error = error_get_last();
$fatal_errors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
if ($error !== null and in_array($error['type'], $fatal_errors, true)) {
error_log(json_encode($error).PHP_EOL,3, '/logs/fatal.log');
}
error_clear_last();
});

View File

@ -18,7 +18,7 @@ class CreateAgente extends Phinx\Migration\AbstractMigration
->addColumn('telefono', 'integer', ['length' => 11, 'default' => null, 'null' => true])
->addColumn('correo', 'string', ['length' => 50, 'default' => null, 'null' => true])
->addColumn('direccion', 'integer', ['length' => 11, 'default' => null, 'null' => true])
->addColumn('giro', 'mediumtext', ['default' => null, 'null' => true])
->addColumn('giro', 'text', ['default' => null, 'null' => true])
->addColumn('abreviacion', 'string', ['length' => 20, 'default' => null, 'null' => true])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');

View File

@ -13,9 +13,9 @@ class CreateCartolas extends Phinx\Migration\AbstractMigration
$this->table('cartolas')
->addColumn('cuenta_id', 'integer', ['length' => 10, 'null' => false, 'signed' => false])
->addColumn('fecha', 'date', ['null' => false])
->addColumn('cargos', 'bigint', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('abonos', 'bigint', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('saldo', 'bigint', ['length' => 20, 'default' => 0, 'null' => false])
->addColumn('cargos', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('abonos', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('saldo', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false])
->addForeignKey('cuenta_id', 'cuenta', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');

View File

@ -15,7 +15,7 @@ class CreateCentrosCostos extends Phinx\Migration\AbstractMigration
->addColumn('categoria_id', 'integer', ['length' => 10, 'null' => false, 'signed' => false])
->addColumn('tipo_cuenta_id', 'integer', ['length' => 10, 'default' => null, 'null' => true, 'signed' => false])
->addColumn('cuenta_contable', 'string', ['length' => 100, 'null' => false])
->addColumn('descripcion', 'mediumtext', ['null' => false])
->addColumn('descripcion', 'text', ['null' => false, 'limit' => MysqlAdapter::TEXT_MEDIUM])
->addForeignKey('tipo_centro_id', 'tipos_centros_costos', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->addForeignKey('categoria_id', 'categorias_centros_costos', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();

View File

@ -19,7 +19,7 @@ class CreateCobro extends Phinx\Migration\AbstractMigration
->addColumn('iva', 'float', ['default' => 0])
->addColumn('uf', 'float', ['default' => null, 'null' => true])
->addColumn('identificador', 'string', ['length' => 50, 'default' => null, 'null' => true])
->addColumn('glosa', 'mediumtext', ['default' => null, 'null' => true])
->addColumn('glosa', 'text', ['default' => null, 'null' => true, 'limit' => MysqlAdapter::TEXT_MEDIUM])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}

View File

@ -11,7 +11,7 @@ class CreateEscritura extends Phinx\Migration\AbstractMigration
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('escritura')
->addColumn('valor', 'bigint', ['length' => 20, 'null' => false])
->addColumn('valor', 'biginteger', ['length' => 20, 'null' => false])
->addColumn('fecha', 'date', ['null' => false])
->addColumn('uf', 'float', ['default' => null, 'null' => true])
->addColumn('abonado', 'integer', ['length' => 11, 'default' => 0])

View File

@ -13,7 +13,7 @@ class CreateEstadoProblema extends Phinx\Migration\AbstractMigration
$this->table('estado_problema')
->addColumn('problema', 'integer', ['length' => 11, 'default' => null, 'null' => true])
->addColumn('fecha', 'date', ['default' => null, 'null' => true])
->addColumn('estado', 'enum', ['length' => 'ingreso','revision','correccion','ok', 'default' => null, 'null' => true])
->addColumn('estado', 'enum', ['values' => ['ingreso','revision','correccion','ok'], 'default' => null, 'null' => true])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}

View File

@ -15,7 +15,7 @@ class CreateInmobiliariasNubox extends Phinx\Migration\AbstractMigration
->addColumn('alias', 'string', ['length' => 100, 'null' => false])
->addColumn('usuario', 'string', ['length' => 100, 'null' => false])
->addColumn('contraseña', 'string', ['length' => 100, 'null' => false])
->addForeignKey('inmobiliaria_rut', 'inmobiliaria', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
#->addForeignKey('inmobiliaria_rut', 'inmobiliaria', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}

View File

@ -15,9 +15,9 @@ class CreateMovimientos extends Phinx\Migration\AbstractMigration
->addColumn('fecha', 'date', ['null' => false])
->addColumn('glosa', 'text', ['null' => false])
->addColumn('documento', 'string', ['length' => 50, 'null' => false])
->addColumn('cargo', 'bigint', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('abono', 'bigint', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('saldo', 'bigint', ['length' => 20, 'default' => 0, 'null' => false])
->addColumn('cargo', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('abono', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false, 'signed' => false])
->addColumn('saldo', 'biginteger', ['length' => 20, 'default' => 0, 'null' => false])
->addForeignKey('cuenta_id', 'cuenta', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');

View File

@ -12,7 +12,7 @@ class CreateProblema extends Phinx\Migration\AbstractMigration
$this->table('problema')
->addColumn('venta', 'integer', ['length' => 11, 'default' => null, 'null' => true])
->addColumn('descripcion', 'mediumtext', ['default' => null, 'null' => true])
->addColumn('descripcion', 'text', ['default' => null, 'null' => true, 'limit' => MysqlAdapter::TEXT_MEDIUM])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}

View File

@ -12,7 +12,7 @@ class CreateProyecto extends Phinx\Migration\AbstractMigration
$this->table('proyecto')
->addColumn('inmobiliaria', 'integer', ['length' => 10, 'default' => null, 'null' => true, 'signed' => false])
->addColumn('descripcion', 'mediumtext', ['null' => false])
->addColumn('descripcion', 'text', ['null' => false, 'limit' => MysqlAdapter::TEXT_MEDIUM])
->addColumn('direccion', 'integer', ['length' => 10, 'null' => false, 'signed' => false])
->addColumn('superficie_terreno', 'float', ['default' => 0, 'null' => false, 'signed' => false])
->addColumn('valor_terreno', 'float', ['default' => 0, 'null' => false, 'signed' => false])

View File

@ -18,7 +18,7 @@ class CreateProyectoTipoUnidad extends Phinx\Migration\AbstractMigration
->addColumn('m2', 'float', ['default' => null, 'null' => true])
->addColumn('logia', 'float', ['default' => 0])
->addColumn('terraza', 'float', ['default' => 0])
->addColumn('descripcion', 'mediumtext', ['default' => null, 'null' => true])
->addColumn('descripcion', 'text', ['default' => null, 'null' => true, 'limit' => MysqlAdapter::TEXT_MEDIUM])
->addForeignKey('proyecto', 'proyecto', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');

View File

@ -10,7 +10,8 @@ class CreateTipoEstadoPago extends Phinx\Migration\AbstractMigration
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('tipo_estado_pago')
$this->table('tipo_estado_pago', ['id' => false, 'primary_key' => 'id'])
->addColumn('id', 'integer', ['signed' => true])
->addColumn('descripcion', 'string', ['length' => 20, 'default' => null, 'null' => true])
->addColumn('active', 'integer', ['length' => 1, 'default' => 0])
->create();

View File

@ -33,7 +33,7 @@ class CreateVenta extends Phinx\Migration\AbstractMigration
->addColumn('resciliacion', 'integer', ['length' => 10, 'default' => null, 'null' => true, 'signed' => false])
->addColumn('devolucion', 'integer', ['length' => 10, 'default' => null, 'null' => true, 'signed' => false])
->addForeignKey('propiedad', 'propiedad', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->addForeignKey('propietario', 'propietario', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
#->addForeignKey('propietario', 'propietario', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}

View File

@ -1,22 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class CreateVentaAbonoCuotas extends Phinx\Migration\AbstractMigration
{
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('venta_abono_cuotas')
->addColumn('venta_id', 'integer', ['length' => 11, 'null' => false, 'signed' => false])
->addColumn('pago_id', 'integer', ['length' => 11, 'null' => false, 'signed' => false])
->addColumn('numero', 'integer', ['length' => 11, 'default' => 1, 'null' => false, 'signed' => false])
->addForeignKey('venta_id', 'venta', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->addForeignKey('pago_id', 'pago', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateBroker extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('brokers', ['id' => false, 'primary_key' => ['rut']])
->addColumn('rut', 'integer', ['identity' => true, 'signed' => false, 'null' => false])
->addColumn('digit', 'string', ['length' => 1, 'null' => false])
->addColumn('name', 'string', ['length' => 255, 'null' => false])
->create();
}
}

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateBrokerContract extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('broker_contracts')
->addColumn('broker_rut', 'integer', ['signed' => false, 'null' => false])
->addColumn('project_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('commission', 'decimal', ['precision' => 10, 'scale' => 2, 'null' => false])
->addForeignKey('broker_rut', 'brokers', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
->addForeignKey('project_id', 'proyecto', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateBrokerData extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('broker_data')
->addColumn('broker_rut', 'integer', ['signed' => false, 'null' => false])
->addColumn('representative_id', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addColumn('legal_name', 'string', ['length' => 255, 'default' => null, 'null' => true])
->addForeignKey('broker_rut', 'brokers', ['rut'], ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('representative_id', 'broker_contacts', ['id'], ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotion extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('promotions')
->addColumn('price_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('amount', 'decimal', ['precision' => 10, 'scale' => 2, 'null' => false])
->addColumn('start_date', 'date', ['null' => false])
->addColumn('end_date', 'date', ['null' => false])
->addColumn('valid_until', 'date', ['null' => false])
->addColumn('state', 'integer', ['length' => 1, 'null' => false, 'default' => 1])
->addForeignKey('price_id', 'prices', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateReservation extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('reservation')
->addColumn('buyer_rut', 'integer', ['signed' => false, 'null' => false])
->addColumn('date', 'date', ['null' => false])
->addForeignKey('buyer_rut', 'personas', 'rut', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateBrokerContractState extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('broker_contract_states')
->addColumn('contract_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('date', 'date', ['null' => false])
->addColumn('type', 'integer', ['length' => 1, 'null' => false, 'default' => 0])
->addForeignKey('contract_id', 'broker_contracts', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateReservationDatas extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('reservation_data')
->addColumn('reservation_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('type', 'integer', ['length' => 1, 'signed' => false, 'null' => false])
->addColumn('reference_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('value', 'decimal', ['precision' => 10, 'scale' => 2, 'signed' => false, 'default' => 0.00, 'null' => true])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateReservationStates extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('reservation_states')
->addColumn('reservation_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('date', 'date', ['null' => false])
->addColumn('type', 'integer', ['length' => 3, 'null' => false, 'default' => 0])
->addForeignKey('reservation_id', 'reservation', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateBrokerContacts extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';");
$this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';");
$this->table('broker_contacts')
->addColumn('rut', 'integer', ['signed' => false, 'null' => true])
->addColumn('digit', 'string', ['length' => 1, 'null' => true])
->addColumn('name', 'string', ['length' => 255, 'null' => true])
->addColumn('email', 'string', ['length' => 255, 'null' => true])
->addColumn('phone', 'string', ['length' => 255, 'null' => true])
->addColumn('address_id', 'integer', ['signed' => false, 'null' => true])
->addForeignKey('address_id', 'direccion', ['id'], ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AlterPromotionsRemovePrice extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function up(): void
{
if ($this->table('promotions')->hasColumn('price_id')) {
$this->table('promotions')
->dropForeignKey('price_id')
->removeColumn('price_id')
->update();
}
}
public function down(): void {}
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotionUnit extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotion_units')
->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('unit_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('created_at', 'datetime', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('unit_id', 'unidad', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
}
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AlterPromotionsNullDates extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function up(): void
{
$this->table('promotions')
->changeColumn('end_date', 'date', ['null' => true])
->changeColumn('valid_until', 'date', ['null' => true])
->update();
}
public function down(): void {}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AlterPromotionsAddDescriptionAndType extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotions')
->addColumn('description', 'string', ['limit' => 255, 'null' => false, 'after' => 'id'])
->addColumn('type', 'integer', ['limit' => 1, 'null' => false, 'default' => 0, 'after' => 'description'])
->update();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotionProjects extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotion_projects')
->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('project_id', 'integer', ['signed' => false, 'null' => false])
->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->addForeignKey('project_id', 'proyecto', 'id', ['delete' => 'cascade', 'update' => 'cascade'])
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotionBrokers extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotion_brokers')
->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('broker_rut', 'integer', ['signed' => false, 'null' => false])
->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('broker_rut', 'brokers', 'rut', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotionUnitLines extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotion_unit_lines')
->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('unit_line_id', 'integer', ['signed' => false, 'null' => false])
->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('unit_line_id', 'proyecto_tipo_unidad', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePromotionUnitTypes extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('promotion_unit_types')
->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('project_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('unit_type_id', 'integer', ['signed' => false, 'null' => false])
->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('project_id', 'proyecto', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->addForeignKey('unit_type_id', 'tipo_unidad', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateTokuCustomers extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('toku_customers')
->addColumn('rut', 'string', ['length' => 9])
->addColumn('toku_id', 'string', ['length' => 255])
->addTimestamps()
->addIndex(['rut'], ['unique' => true])
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateTokuSubscriptions extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('toku_subscriptions')
->addColumn('venta_id', 'integer', ['signed' => false])
->addColumn('toku_id', 'string', ['length' => 255])
->addTimestamps()
->addIndex(['venta_id'], ['unique' => true])
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateTokuInvoices extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('toku_invoices')
->addColumn('cuota_id', 'integer', ['signed' => false])
->addColumn('toku_id', 'string', ['length' => 255])
->addTimestamps()
->addIndex(['cuota_id'], ['unique' => true])
->create();
}
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateJobs extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('jobs')
->addColumn('configuration', 'json')
->addColumn('executed', 'boolean', ['default' => false])
->addTimestamps()
->create();
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateTokuWebhooks extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$this->table('toku_webhooks')
->addColumn('secret', 'string', ['length' => 255])
->addColumn('events', 'json')
->addColumn('enabled', 'boolean', ['default' => true])
->addTimestamps()
->create();
}
}

View File

@ -0,0 +1,391 @@
<?php
declare(strict_types=1);
use Phinx\Seed\AbstractSeed;
class Comuna extends AbstractSeed
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* https://book.cakephp.org/phinx/0/en/seeding.html
*/
public function run(): void
{
/*id descripcion provincia
1101 Iquique 11
1107 Alto Hospicio 11
1401 Pozo Almonte 14
1402 Camiña 14
1403 Colchane 14
1404 Huara 14
1405 Pica 14
2101 Antofagasta 21
2102 Mejillones 21
2103 Sierra Gorda 21
2104 Taltal 21
2201 Calama 22
2202 Ollagüe 22
2203 San Pedro de Atacama 22
2301 Tocopilla 23
2302 María Elena 23
3101 Copiapó 31
3102 Caldera 31
3103 Tierra Amarilla 31
3201 Chañaral 32
3202 Diego de Almagro 32
3301 Vallenar 33
3302 Alto del Carmen 33
3303 Freirina 33
3304 Huasco 33
4101 La Serena 41
4102 Coquimbo 41
4103 Andacollo 41
4104 La Higuera 41
4105 Paiguano 41
4106 Vicuña 41
4201 Illapel 42
4202 Canela 42
4203 Los Vilos 42
4204 Salamanca 42
4301 Ovalle 43
4302 Combarbalá 43
4303 Monte Patria 43
4304 Punitaqui 43
4305 Río Hurtado 43
5101 Valparaíso 51
5102 Casablanca 51
5103 Concón 51
5104 Juan Fernández 51
5105 Puchuncaví 51
5107 Quintero 51
5109 Viña del Mar 51
5201 Isla de Pascua 52
5301 Los Andes 53
5302 Calle Larga 53
5303 Rinconada 53
5304 San Esteban 53
5401 La Ligua 54
5402 Cabildo 54
5403 Papudo 54
5404 Petorca 54
5405 Zapallar 54
5501 Quillota 55
5502 Calera 55
5503 Hijuelas 55
5504 La Cruz 55
5506 Nogales 55
5601 San Antonio 56
5602 Algarrobo 56
5603 Cartagena 56
5604 El Quisco 56
5605 El Tabo 56
5606 Santo Domingo 56
5701 San Felipe 57
5702 Catemu 57
5703 Llaillay 57
5704 Panquehue 57
5705 Putaendo 57
5706 Santa María 57
5801 Quilpué 58
5802 Limache 58
5803 Olmué 58
5804 Villa Alemana 58
6101 Rancagua 61
6102 Codegua 61
6103 Coinco 61
6104 Coltauco 61
6105 Doñihue 61
6106 Graneros 61
6107 Las Cabras 61
6108 Machalí 61
6109 Malloa 61
6110 Mostazal 61
6111 Olivar 61
6112 Peumo 61
6113 Pichidegua 61
6114 Quinta de Tilcoco 61
6115 Rengo 61
6116 Requínoa 61
6117 San Vicente 61
6201 Pichilemu 62
6202 La Estrella 62
6203 Litueche 62
6204 Marchihue 62
6205 Navidad 62
6206 Paredones 62
6301 San Fernando 63
6302 Chépica 63
6303 Chimbarongo 63
6304 Lolol 63
6305 Nancagua 63
6306 Palmilla 63
6307 Peralillo 63
6308 Placilla 63
6309 Pumanque 63
6310 Santa Cruz 63
7101 Talca 71
7102 Constitución 71
7103 Curepto 71
7104 Empedrado 71
7105 Maule 71
7106 Pelarco 71
7107 Pencahue 71
7108 Río Claro 71
7109 San Clemente 71
7110 San Rafael 71
7201 Cauquenes 72
7202 Chanco 72
7203 Pelluhue 72
7301 Curicó 73
7302 Hualañé 73
7303 Licantén 73
7304 Molina 73
7305 Rauco 73
7306 Romeral 73
7307 Sagrada Familia 73
7308 Teno 73
7309 Vichuquén 73
7401 Linares 74
7402 Colbún 74
7403 Longaví 74
7404 Parral 74
7405 Retiro 74
7406 San Javier 74
7407 Villa Alegre 74
7408 Yerbas Buenas 74
8101 Concepción 81
8102 Coronel 81
8103 Chiguayante 81
8104 Florida 81
8105 Hualqui 81
8106 Lota 81
8107 Penco 81
8108 San Pedro de la Paz 81
8109 Santa Juana 81
8110 Talcahuano 81
8111 Tomé 81
8112 Hualpén 81
8201 Lebu 82
8202 Arauco 82
8203 Cañete 82
8204 Contulmo 82
8205 Curanilahue 82
8206 Los Álamos 82
8207 Tirúa 82
8301 Los Ángeles 83
8302 Antuco 83
8303 Cabrero 83
8304 Laja 83
8305 Mulchén 83
8306 Nacimiento 83
8307 Negrete 83
8308 Quilaco 83
8309 Quilleco 83
8310 San Rosendo 83
8311 Santa Bárbara 83
8312 Tucapel 83
8313 Yumbel 83
8314 Alto Biobío 83
8401 Chillán 84
8402 Bulnes 84
8403 Cobquecura 84
8404 Coelemu 84
8405 Coihueco 84
8406 Chillán Viejo 84
8407 El Carmen 84
8408 Ninhue 84
8409 Ñiquén 84
8410 Pemuco 84
8411 Pinto 84
8412 Portezuelo 84
8413 Quillón 84
8414 Quirihue 84
8415 Ránquil 84
8416 San Carlos 84
8417 San Fabián 84
8418 San Ignacio 84
8419 San Nicolás 84
8420 Treguaco 84
8421 Yungay 84
9101 Temuco 91
9102 Carahue 91
9103 Cunco 91
9104 Curarrehue 91
9105 Freire 91
9106 Galvarino 91
9107 Gorbea 91
9108 Lautaro 91
9109 Loncoche 91
9110 Melipeuco 91
9111 Nueva Imperial 91
9112 Padre las Casas 91
9113 Perquenco 91
9114 Pitrufquén 91
9115 Pucón 91
9116 Saavedra 91
9117 Teodoro Schmidt 91
9118 Toltén 91
9119 Vilcún 91
9120 Villarrica 91
9121 Cholchol 91
9201 Angol 92
9202 Collipulli 92
9203 Curacautín 92
9204 Ercilla 92
9205 Lonquimay 92
9206 Los Sauces 92
9207 Lumaco 92
9208 Purén 92
9209 Renaico 92
9210 Traiguén 92
9211 Victoria 92
10101 Puerto Montt 101
10102 Calbuco 101
10103 Cochamó 101
10104 Fresia 101
10105 Frutillar 101
10106 Los Muermos 101
10107 Llanquihue 101
10108 Maullín 101
10109 Puerto Varas 101
10201 Castro 102
10202 Ancud 102
10203 Chonchi 102
10204 Curaco de Vélez 102
10205 Dalcahue 102
10206 Puqueldón 102
10207 Queilén 102
10208 Quellón 102
10209 Quemchi 102
10210 Quinchao 102
10301 Osorno 103
10302 Puerto Octay 103
10303 Purranque 103
10304 Puyehue 103
10305 Río Negro 103
10306 San Juan de la Costa 103
10307 San Pablo 103
10401 Chaitén 104
10402 Futaleufú 104
10403 Hualaihué 104
10404 Palena 104
11101 Coihaique 111
11102 Lago Verde 111
11201 Aisén 112
11202 Cisnes 112
11203 Guaitecas 112
11301 Cochrane 113
11302 OHiggins 113
11303 Tortel 113
11401 Chile Chico 114
11402 Río Ibáñez 114
12101 Punta Arenas 121
12102 Laguna Blanca 121
12103 Río Verde 121
12104 San Gregorio 121
12201 Cabo de Hornos (Ex Navarino) 122
12202 Antártica 122
12301 Porvenir 123
12302 Primavera 123
12303 Timaukel 123
12401 Natales 124
12402 Torres del Paine 124
13101 Santiago 131
13102 Cerrillos 131
13103 Cerro Navia 131
13104 Conchalí 131
13105 El Bosque 131
13106 Estación Central 131
13107 Huechuraba 131
13108 Independencia 131
13109 La Cisterna 131
13110 La Florida 131
13111 La Granja 131
13112 La Pintana 131
13113 La Reina 131
13114 Las Condes 131
13115 Lo Barnechea 131
13116 Lo Espejo 131
13117 Lo Prado 131
13118 Macul 131
13119 Maipú 131
13120 Ñuñoa 131
13121 Pedro Aguirre Cerda 131
13122 Peñalolén 131
13123 Providencia 131
13124 Pudahuel 131
13125 Quilicura 131
13126 Quinta Normal 131
13127 Recoleta 131
13128 Renca 131
13129 San Joaquín 131
13130 San Miguel 131
13131 San Ramón 131
13132 Vitacura 131
13201 Puente Alto 132
13202 Pirque 132
13203 San José de Maipo 132
13301 Colina 133
13302 Lampa 133
13303 Tiltil 133
13401 San Bernardo 134
13402 Buin 134
13403 Calera de Tango 134
13404 Paine 134
13501 Melipilla 135
13502 Alhué 135
13503 Curacaví 135
13504 María Pinto 135
13505 San Pedro 135
13601 Talagante 136
13602 El Monte 136
13603 Isla de Maipo 136
13604 Padre Hurtado 136
13605 Peñaflor 136
14101 Valdivia 141
14102 Corral 141
14103 Lanco 141
14104 Los Lagos 141
14105 Máfil 141
14106 Mariquina 141
14107 Paillaco 141
14108 Panguipulli 141
14201 La Unión 142
14202 Futrono 142
14203 Lago Ranco 142
14204 Río Bueno 142
15101 Arica 151
15102 Camarones 151
15201 Putre 152
15202 General Lagos 152
*/
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$table = $this->table('comuna');
$table->truncate();
$data = [
['id' => 1101, 'descripcion' => 'Iquique', 'provincia' => 11],
['id' => 1107, 'descripcion' => 'Alto Hospicio', 'provincia' => 11],
['id' => 1401, 'descripcion' => 'Pozo Almonte', 'provincia' => 14],
['id' => 1402, 'descripcion' => 'Camiña', 'provincia' => 14],
['id' => 1403, 'descripcion' => 'Colchane', 'provincia' => 14],
['id' => 1404, 'descripcion' => 'Huara', 'provincia' => 14],
['id' => 1405, 'descripcion' => 'Pica', 'provincia' => 14],
['id' => 2101, 'descripcion' => 'Antofagasta', 'provincia' => 21],
['id' => 2102, 'descripcion' => 'Mejillones', 'provincia' => 21],
['id' => 2103, 'descripcion' => 'Sierra Gorda', 'provincia' => 21],
['id' => 2104, 'descripcion' => 'Taltal', 'provincia' => 21],
['id' => 2201, 'descripcion' => 'Calama', 'provincia' => 22],
['id' => 2202, 'descripcion' => 'Ollagüe', 'provincia' => 22],
['id' => 2203, 'descripcion' => 'San Pedro de Alcántara', 'provincia' => 22],
['id' => 2301, 'descripcion' => 'Tocopilla', 'provincia' => 23],
['id' => 2302, 'descripcion' => 'María Elena', 'provincia' => 23],
];
}
}

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Phinx\Seed\AbstractSeed;
class TipoEstadoPago extends AbstractSeed
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* https://book.cakephp.org/phinx/0/en/seeding.html
*/
public function run(): void
{
$this->execute('SET unique_checks=0; SET foreign_key_checks=0;');
$table = $this->table('tipo_estado_pago');
$table->truncate();
$data = [
['id' => -3, 'descripcion' => 'anulado'],
['id' => -2, 'descripcion' => 'reemplazado'],
['id' => -1, 'descripcion' => 'devuelto'],
['id' => 0, 'descripcion' => 'no pagado', 'active' => 1],
['id' => 1, 'descripcion' => 'depositado', 'active' => 1],
['id' => 2, 'descripcion' => 'abonado', 'active' => 1],
];
$table->insert($data)->saveData();
$this->execute('SET unique_checks=1; SET foreign_key_checks=1;');
}
}

View File

@ -2,6 +2,16 @@
use Incoviba\Controller\Proyectos;
$app->group('/proyectos', function($app) {
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'proyectos']);
if (file_exists($folder)) {
$files = new FilesystemIterator($folder);
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
include_once $file->getRealPath();
}
}
$app->get('/unidades[/]', [Proyectos::class, 'unidades']);
$app->get('[/]', Proyectos::class);
})->add($app->getContainer()->get(Incoviba\Middleware\Authentication::class));

View File

@ -23,6 +23,7 @@ $app->group('/venta/{venta_id:[0-9]+}', function($app) {
$app->get('[/]', [Ventas::class, 'propiedad']);
});
$app->group('/pie', function($app) {
$app->get('/add[/]', [Ventas\Pies::class, 'add']);
$app->group('/cuotas', function($app) {
$app->get('[/]', [Ventas::class, 'cuotas']);
});

View File

@ -7,4 +7,4 @@ $app->group('/contabilidad', function($app) {
}
include_once $file->getRealPath();
}
});
})->add($app->getContainer()->get(Incoviba\Middleware\Authentication::class));

View File

@ -7,4 +7,4 @@ $app->group('/admin', function($app) {
}
include_once $file->getRealPath();
}
});
})->add($app->getContainer()->get(Incoviba\Middleware\Authentication::class));

View File

@ -2,5 +2,9 @@
use Incoviba\Controller\API\Admin\Users;
$app->group('/users', function($app) {
$app->post('/add[/]', Users::class . ':add');
$app->post('/add[/]', [Users::class, 'add']);
});
$app->group('/user/{user_id}', function($app) {
$app->post('/edit[/]', [Users::class, 'edit']);
$app->delete('[/]', [Users::class, 'delete']);
});

View File

@ -0,0 +1,16 @@
<?php
use Incoviba\Controller\API\External;
$app->group('/external', function($app) {
$files = new FilesystemIterator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'external']));
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
include_once $file->getRealPath();
}
$app->group('/services', function($app) {
$app->get('/check[/]', [External::class, 'check']);
$app->get('/update[/]', [External::class, 'update']);
});
});

View File

@ -0,0 +1,10 @@
<?php
use Incoviba\Controller\API\Ventas\MediosPago\Toku;
$app->group('/toku', function($app) {
$app->post('/cuotas/{venta_id}[/]', [Toku::class, 'cuotas']);
$app->post('/success[/]', [Toku::class, 'success']);
$app->get('/test[/]', [Toku::class, 'test']);
$app->delete('/reset[/]', [Toku::class, 'reset']);
$app->post('/enqueue[/]', [Toku::class, 'enqueue']);
});

View File

@ -3,6 +3,13 @@ use Incoviba\Controller\API\Proyectos;
$app->group('/proyectos', function($app) {
$app->get('/escriturando[/]', [Proyectos::class, 'escriturando']);
$files = new FilesystemIterator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'proyectos']));
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
include_once $file->getRealPath();
}
$app->get('[/]', [Proyectos::class, 'list']);
});
$app->group('/proyecto/{proyecto_id}', function($app) {
@ -14,10 +21,13 @@ $app->group('/proyecto/{proyecto_id}', function($app) {
$app->get('/vendible[/]', [Proyectos::class, 'superficies']);
});
$app->group('/unidades', function($app) {
$app->post('/precios[/]', [Proyectos\Unidades::class, 'precios']);
$app->post('/estados[/]', [Proyectos\Unidades::class, 'estados']);
$app->get('/disponibles[/]', [Proyectos::class, 'disponibles']);
$app->get('[/]', [Proyectos::class, 'unidades']);
});
$app->group('/terreno', function($app) {
$app->post('/edit[/]', [Proyectos::class, 'terreno']);
});
$app->get('/brokers', [Proyectos::class, 'brokers']);
});

View File

@ -0,0 +1,30 @@
<?php
use Incoviba\Controller\API\Proyectos\Brokers;
use Incoviba\Controller\API\Proyectos\Brokers\Contracts;
$app->group('/brokers', function($app) {
$app->group('/contracts', function($app) {
$app->post('/add[/]', [Contracts::class, 'add']);
$app->get('[/]', Contracts::class);
});
$app->group('/contract/{contract_id}', function($app) {
$app->post('/edit[/]', [Contracts::class, 'edit']);
$app->post('/inactive[/]', [Contracts::class, 'inactive']);
$app->delete('[/]', [Contracts::class, 'delete']);
$app->get('[/]', [Contracts::class, 'get']);
});
$app->post('/add[/]', [Brokers::class, 'add']);
$app->post('/edit[/]', [Brokers::class, 'edit']);
$app->get('[/]', Brokers::class);
});
$app->group('/broker/{broker_rut}', function($app) {
$app->group('/contracts', function($app) {
$app->post('/add[/]', [Contracts::class, 'add']);
$app->get('[/]', [Contracts::class, 'getByBroker']);
});
$app->group('/contract/{contract_id}', function($app) {
$app->post('/promotions[/]', [Contracts::class, 'promotions']);
});
$app->delete('[/]', [Brokers::class, 'delete']);
$app->get('[/]', [Brokers::class, 'get']);
});

View File

@ -0,0 +1,10 @@
<?php
use Incoviba\Controller\API\Queues;
$app->group('/queue', function($app) {
$app->get('/jobs[/]', [Queues::class, 'jobs']);
$app->group('/run', function($app) {
$app->get('/{job_id:[0-9]+}[/]', [Queues::class, 'run']);
$app->get('[/]', Queues::class);
});
});

View File

@ -21,6 +21,7 @@ $app->group('/ventas', function($app) {
});
$app->group('/by', function($app) {
$app->get('/unidad/{unidad_id}', [Ventas::class, 'unidad']);
$app->post('/unidades[/]', [Ventas::class, 'byUnidades']);
});
$app->post('/get[/]', [Ventas::class, 'getMany']);
$app->post('[/]', [Ventas::class, 'proyecto']);
@ -55,6 +56,9 @@ $app->group('/venta/{venta_id}', function($app) {
$app->group('/propietario', function($app) {
$app->put('/edit[/]', [Ventas::class, 'propietario']);
});
$app->group('/pie', function($app) {
$app->post('/add[/]', [Ventas\Pies::class, 'add']);
});
$app->post('[/]', [Ventas::class, 'edit']);
$app->get('[/]', [Ventas::class, 'get']);
});

View File

@ -0,0 +1,28 @@
<?php
use Incoviba\Controller\API\Ventas\Promotions;
$app->group('/promotions', function($app) {
$app->post('/add[/]', [Promotions::class, 'add']);
$app->post('/edit[/]', [Promotions::class, 'edit']);
});
$app->group('/promotion/{promotion_id}', function($app) {
$app->delete('/remove[/]', [Promotions::class, 'remove']);
$app->group('/connections', function($app) {
$app->post('/add[/]', [Promotions::class, 'addConnections']);
$app->group('/project/{project_id}', function($app) {
$app->delete('[/]', [Promotions::class, 'removeProject']);
$app->group('/unit-type/{unit_type_id}', function($app) {
$app->delete('[/]', [Promotions::class, 'removeUnitType']);
});
});
$app->group('/broker/{broker_rut}', function($app) {
$app->delete('[/]', [Promotions::class, 'removeBroker']);
});
$app->group('/unit-line/{unit_line_id}', function($app) {
$app->delete('[/]', [Promotions::class, 'removeUnitLine']);
});
$app->group('/unit/{unit_id}', function($app) {
$app->delete('[/]', [Promotions::class, 'removeUnit']);
});
});
});

View File

@ -0,0 +1,12 @@
<?php
use Incoviba\Controller\API\Ventas\Reservations;
$app->group('/reservations', function($app) {
$app->post('/add[/]', [Reservations::class, 'add']);
$app->get('[/]', Reservations::class);
});
$app->group('/reservation/{reservation_id}', function($app) {
$app->post('/edit[/]', [Reservations::class, 'edit']);
$app->delete('[/]', [Reservations::class, 'delete']);
$app->get('[/]', [Reservations::class, 'get']);
});

View File

@ -0,0 +1,12 @@
<?php
use Incoviba\Controller\Proyectos\Brokers;
$app->group('/brokers', function($app) {
$app->get('[/]', Brokers::class);
});
$app->group('/broker/{broker_rut}', function($app) {
$app->group('/contract/{contract_id}', function($app) {
$app->get('[/]', [Brokers\Contracts::class, 'show']);
});
$app->get('[/]', [Brokers::class, 'show']);
});

View File

@ -0,0 +1,9 @@
<?php
use Incoviba\Controller\Ventas\Promotions;
$app->group('/promotions', function($app) {
$app->get('[/]', Promotions::class);
});
$app->group('/promotion/{promotion_id}', function($app) {
$app->get('[/]', [Promotions::class, 'show']);
});

View File

@ -14,15 +14,15 @@
</th>
</tr>
</thead>
<tbody>
<tbody id="users">
@foreach($users as $user)
<tr>
<tr data-user="{{ $user->id }}">
<td>{{ $user->name }}</td>
<td class="right aligned">
<button class="ui mini blue icon button">
<button class="ui mini blue icon button edit" data-user="{{ $user->id }}">
<i class="edit icon"></i>
</button>
<button class="ui mini red icon button">
<button class="ui mini red icon button remove" data-user="{{ $user->id }}">
<i class="trash icon"></i>
</button>
</td>
@ -50,6 +50,10 @@
<label>Contraseña</label>
<input type="password" name="password" placeholder="Contraseña">
</div>
<div class="field">
<label>Confirmar contraseña</label>
<input type="password" name="password_confirmation" placeholder="Confirmar contraseña">
</div>
</form>
</div>
<div class="actions">
@ -62,6 +66,45 @@
</div>
</div>
</div>
<div class="ui modal" id="edit-user-modal">
<i class="close icon"></i>
<div class="header">
Editar usuario
</div>
<div class="content">
<form class="ui form">
<input type="hidden" name="id" />
<div class="field">
<label>Contraseña Antigua</label>
<input type="password" name="old_password" placeholder="Contraseña Antigua">
</div>
<div class="field">
<label>Force Change?</label>
<div class="ui checkbox">
<input type="checkbox" name="force" >
<label>Yes</label>
</div>
</div>
<div class="field">
<label>Contraseña</label>
<input type="password" name="password" placeholder="Contraseña">
</div>
<div class="field">
<label>Confirmar contraseña</label>
<input type="password" name="password_confirmation" placeholder="Confirmar contraseña">
</div>
</form>
</div>
<div class="actions">
<div class="ui black deny button">
Cancelar
</div>
<div class="ui positive right labeled icon button">
Guardar
<i class="checkmark icon"></i>
</div>
</div>
</div>
@endsection
@include('layout.body.scripts.cryptojs')
@ -74,12 +117,20 @@
return [passphrase, encrypted.toString()].join('')
}
$(document).ready(function () {
$('#create-user-modal').modal({
const $createUserModal = $('#create-user-modal')
$createUserModal.modal({
onApprove: function() {
const form = document.querySelector('#create-user-modal form')
const password = form.querySelector('[name="password"]').value
const password_confirmation = form.querySelector('[name="password_confirmation"]').value
if (password !== password_confirmation) {
alert('Las contraseñas no coinciden')
return
}
const url = '{{$urls->api}}/admin/users/add'
const method = 'post'
const body = new FormData(document.querySelector('#create-user-modal form'))
body.set('password', encryptPassword(body.get('password')))
const body = new FormData(form)
body.set('password', encryptPassword(password))
fetchAPI(url, {method, body}).then(response => {
if (!response) {
return;
@ -92,8 +143,64 @@
})
}
})
$('#create-user-button').on('click', function () {
$('#create-user-modal').modal('show')
const $editUserModal = $('#edit-user-modal')
$editUserModal.modal({
onApprove: function() {
const form = document.querySelector('#edit-user-modal form')
const user_id = form.querySelector('[name="id"]').value
const old_password = form.querySelector('[name="old_password"]').value
const password = form.querySelector('[name="password"]').value
const password_confirmation = form.querySelector('[name="password_confirmation"]').value
if (password !== password_confirmation) {
alert('Las nuevas contraseñas no coinciden')
return
}
const url = `{{$urls->api}}/admin/user/${user_id}/edit`
const method = 'post'
const body = new FormData(form)
body.set('old_password', encryptPassword(old_password))
body.set('password', encryptPassword(password))
if (form.querySelector('[name="force"]').checked) {
body.set('force', 'true')
}
fetchAPI(url, {method, body}).then(response => {
if (!response) {
return;
}
response.json().then(result => {
if (result.success) {
location.reload()
}
})
})
}
})
document.getElementById('create-user-modal').addEventListener('submit', event => {
$createUserModal.modal('show')
})
document.querySelectorAll('.button.edit').forEach(button => {
button.addEventListener('click', clickEvent => {
const user_id = clickEvent.currentTarget.dataset.user
$editUserModal.find('input[name="id"]').val(user_id)
$editUserModal.modal('show')
})
})
document.querySelectorAll('.button.remove').forEach(button => {
button.addEventListener('click', clickEvent => {
const user_id = clickEvent.currentTarget.dataset.user
const url = `{{$urls->api}}/admin/user/${user_id}`
const method = 'delete'
fetchAPI(url, {method}).then(response => {
if (!response) {
return;
}
response.json().then(result => {
if (result.success) {
location.reload()
}
})
})
})
})
});
</script>

View File

@ -96,26 +96,7 @@
columnDefs,
order,
language: Object.assign(dtD.language, {
searchBuilder: {
add: 'Filtrar',
condition: 'Comparador',
clearAll: 'Resetear',
delete: 'Eliminar',
deleteTitle: 'Eliminar Titulo',
data: 'Columna',
left: 'Izquierda',
leftTitle: 'Titulo Izquierdo',
logicAnd: 'Y',
logicOr: 'O',
right: 'Derecha',
rightTitle: 'Titulo Derecho',
title: {
0: 'Filtros',
_: 'Filtros (%d)'
},
value: 'Opciones',
valueJoiner: 'y'
}
searchBuilder
}),
layout: {
top1: {

View File

@ -20,7 +20,7 @@
@endsection
@push('page_scripts')
<script type="text/javascript">
<script>
const cuotas = {
get: function() {
return {

View File

@ -2,7 +2,7 @@
<div class="ui divided list" id="alertas_escrituras"></div>
@push('page_scripts')
<script type="text/javascript">
<script>
const alertas_escrituras = {
id: '#alertas_escrituras',
data: {

View File

@ -2,7 +2,7 @@
<div class="ui divided list" id="cierres_vigentes"></div>
@push('page_scripts')
<script type="text/javascript">
<script>
const cierres_vigentes = {
get: function() {
const list = $('#cierres_vigentes')

View File

@ -2,7 +2,7 @@
<div class="ui divided list" id="cuotas_por_vencer"></div>
@push('page_scripts')
<script type="text/javascript">
<script>
const cuotas_por_vencer = {
get: function() {
const list = $('#cuotas_por_vencer')

View File

@ -3,5 +3,6 @@
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{$urls->base}}/proyectos/unidades">Unidades</a>
<a class="item" href="{{ $urls->base }}/proyectos/brokers">Operadores</a>
</div>
</div>

View File

@ -11,7 +11,7 @@
</div>
@push('page_scripts')
<script type="text/javascript">
<script>
function logout() {
return fetch('{{$urls->base}}/logout').then(response => {
if (response.ok) {

View File

@ -3,6 +3,7 @@
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{$urls->base}}/ventas/precios">Precios</a>
<a class="item" href="{{ $urls->base }}/ventas/promotions">Promociones</a>
<a class="item" href="{{$urls->base}}/ventas/cierres">Cierres</a>
<div class="item">
Cuotas
@ -33,6 +34,7 @@
{{--<a class="item" href="{{$urls->base}}/ventas/precios/importar">Importar Precios</a>--}}
{{--<a class="item" href="{{$urls->base}}/ventas/cierres/evaluar">Evaluar Cierre</a>--}}
<a class="item" href="{{$urls->base}}/ventas/facturacion">Facturación</a>
<div class="divider"></div>
<a class="item" href="{{$urls->base}}/ventas/add">
Nueva Venta
<i class="plus icon"></i>

View File

@ -1,33 +1,9 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.3/semantic.min.js" integrity="sha512-gnoBksrDbaMnlE0rhhkcx3iwzvgBGz6mOEj4/Y5ZY09n55dYddx6+WYc72A55qEesV8VX2iMomteIwobeGK1BQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
class APIClient {
static fetch(url, options=null, showErrors=false) {
return fetchAPI(url, options, showErrors)
}
}
function fetchAPI(url, options=null, showErrors=false) {
if (options === null) {
options = {}
}
if (!Object.hasOwn(options, 'headers')) {
options['headers'] = {}
}
if (!Object.hasOwn(options['headers'], 'Authorization')) {
options['headers']['Authorization'] = 'Bearer {{md5($API_KEY)}}{{($login->isIn()) ? $login->getSeparator() . $login->getToken() : ''}}'
}
return fetch(url, options).then(response => {
if (response.ok) {
return response
}
throw new Error(JSON.stringify({code: response.status, message: response.statusText, url}))
}).catch(error => {
if (showErrors) {
console.error(error)
}
})
}
@include('layout.body.scripts.api')
<script>
const datatables_defaults = {
language: {
emptyTable: 'No hay datos disponibles',

View File

@ -0,0 +1,32 @@
<script>
class APIClient {
static getApiKey() {
return '{{md5($API_KEY)}}{{($login->isIn()) ? $login->getSeparator() . $login->getToken() : ''}}'
}
static fetch(url, options=null, showErrors=false) {
if (options === null) {
options = {}
}
if (!Object.hasOwn(options, 'headers')) {
options['headers'] = {}
}
if (!Object.hasOwn(options['headers'], 'Authorization')) {
options['headers']['Authorization'] = `Bearer ${APIClient.getApiKey()}`
}
return fetch(url, options).then(response => {
if (response.ok) {
return response
}
throw new Error(JSON.stringify({code: response.status, message: response.statusText, url}))
}).catch(error => {
if (showErrors) {
console.error(error)
}
})
}
}
function fetchAPI(url, options=null, showErrors=false) {
return APIClient.fetch(url, options, showErrors)
}
</script>

View File

@ -1,4 +1,4 @@
@push('page_scripts')
<script type="text/javascript" src="https://cdn.datatables.net/2.0.3/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.0.3/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.0.3/js/dataTables.semanticui.min.js"></script>
@endpush

View File

@ -2,4 +2,26 @@
<script src="https://cdn.datatables.net/datetime/1.5.2/js/dataTables.dateTime.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.7.0/js/dataTables.searchBuilder.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.7.0/js/searchBuilder.semanticui.js"></script>
<script>
const searchBuilder = {
add: 'Filtrar',
condition: 'Comparador',
clearAll: 'Resetear',
delete: 'Eliminar',
deleteTitle: 'Eliminar Titulo',
data: 'Columna',
left: 'Izquierda',
leftTitle: 'Titulo Izquierdo',
logicAnd: 'Y',
logicOr: 'O',
right: 'Derecha',
rightTitle: 'Titulo Derecho',
title: {
0: 'Filtros',
_: 'Filtros (%d)'
},
value: 'Opciones',
valueJoiner: 'y'
}
</script>
@endpush

View File

@ -0,0 +1,45 @@
@push('page_scripts')
<script>
Intl.NumberFormat.prototype.parse = function(valueString) {
const format = new Intl.NumberFormat(this.resolvedOptions().locale);
const parts = format.formatToParts(-12345.6);
const numerals = Array.from({ length: 10 }).map((_, i) => format.format(i));
const index = new Map(numerals.map((d, i) => [d, i]));
_minusSign = new RegExp(`[${parts.find(d => d.type === 'minusSign').value}]`);
_group = new RegExp(`[${parts.find(d => d.type === 'group').value}]`, 'g');
_decimal = new RegExp(`[${parts.find(d => d.type === 'decimal').value}]`);
_numeral = new RegExp(`[${numerals.join('')}]`, 'g');
_index = d => index.get(d);
const DIRECTION_MARK = /\u061c|\u200e/g
return +(
valueString.trim()
.replace(DIRECTION_MARK, '')
.replace(_group, '')
.replace(_decimal, '.')
.replace(_numeral, _index)
.replace(_minusSign, '-')
)
}
Intl.NumberFormat.prototype.isLocale = function(stringValue) {
const format = new Intl.NumberFormat(this.resolvedOptions().locale);
const parts = format.formatToParts(-12345.6);
const group = parts.find(d => d.type === 'group').value;
const decimal = parts.find(d => d.type === 'decimal').value;
if (stringValue.includes(group)) {
if (stringValue.includes(decimal)) {
return stringValue.indexOf(group) < stringValue.indexOf(decimal)
}
if (stringValue.split(group).map(d => d.length).filter(d => d > 3).length > 0) {
return false
}
return stringValue.split(group).length > 2;
}
if (stringValue.includes(decimal)) {
return stringValue.split(decimal).length <= 2;
}
return false
}
</script>
@endpush

View File

@ -0,0 +1,76 @@
@push('page_scripts')
<script>
if (typeof Intl.NumberFormat.isLocale === 'undefined' || typeof Intl.NumberFormat.isLocale !== 'function') {
// Load Intl.NumberFormat custom methods
@include('layout.body.scripts.number_format')
}
class NumberInput {
input
isRational
outputLocale
currentValue
formatters
constructor({input, isRational, outputLocale}) {
this.input = input
this.isRational = isRational
this.outputLocale = outputLocale || 'es-CL'
this.formatters = {}
const locales = ['es-CL', 'en-US']
locales.forEach(locale => {
this.formatters[locale] = {
rational: new Intl.NumberFormat(locale, {minimumFractionDigits: 2, maximumFractionDigits: 2}),
integer: new Intl.NumberFormat(locale)
}
})
if (this.input.value !== '') {
this.currentValue = this.process(this.input.value)
this.input.value = this.format(this.currentValue)
}
}
watch() {
this.input.addEventListener('change', event => {
this.currentValue = this.process(event.currentTarget.value)
this.input.value = this.format(this.currentValue)
})
}
process(stringValue) {
if (stringValue === '') {
return ''
}
if (typeof stringValue !== 'string') {
return stringValue
}
return this.formatters[this.detectLocale(stringValue)][this.isRational ? 'rational' : 'integer'].parse(stringValue)
}
detectLocale(stringValue) {
if (stringValue === '') {
return ''
}
if (typeof stringValue !== 'string') {
return stringValue
}
const outputFormat = this.formatters[this.outputLocale][this.isRational ? 'rational' : 'integer'].isLocale(stringValue)
const otherFormats = Object.entries(this.formatters).filter(formatter => formatter[0] !== this.outputLocale).map(formatter => {
return {
locale: formatter[0],
value: formatter[1][this.isRational ? 'rational' : 'integer'].isLocale(stringValue)
}
}).filter(formatter => formatter.value)
if (outputFormat) {
return this.outputLocale
}
if (otherFormats.length > 0) {
return otherFormats[0].locale
}
return 'en-US'
}
format(value) {
return this.formatters[this.outputLocale][this.isRational ? 'rational' : 'integer'].format(value)
}
}
</script>
@endpush

View File

@ -28,7 +28,7 @@
if (!(typeof digito === 'string' || digito instanceof String)) {
digito = digito.toString()
}
return Rut.digitoVerificador(rut) === digito
return Rut.digitoVerificador(rut).toString().toUpperCase() === digito.toUpperCase()
}
}
</script>

View File

@ -0,0 +1,6 @@
@prepend('page_scripts')
<script src='https://unpkg.com/simple-statistics@7.8.8/dist/simple-statistics.min.js'></script>
<script>
const Stat = ss
</script>
@endprepend

View File

@ -1,9 +1,9 @@
<head>
<meta charset="utf8" />
@hasSection('page_title')
<title>Incoviba - @yield('page_title')</title>
<title>Incoviba - @yield('page_title')</title>
@else
<title>Incoviba</title>
<title>Incoviba</title>
@endif
<link rel="icon" href="{{$urls->images}}/Isotipo 16.png" />
@include('layout.head.styles')

View File

@ -19,7 +19,7 @@
@include('layout.body.scripts.cryptojs')
@push('page_scripts')
<script type="text/javascript">
<script>
function encryptPassword(password) {
const passphrase = Math.floor(Math.random() * Date.now()).toString()
const encrypted = CryptoJS.AES.encrypt(password, passphrase)

View File

@ -0,0 +1,14 @@
@extends('layout.base')
@section('page_title')
405 - Método No Permitido
@endsection
@section('page_content')
<div class="ui container">
<div class="ui message">
<i class="exclamation triangle icon"></i>
No se ha encontrado la página solicitada para el método solicitado.
</div>
</div>
@endsection

View File

@ -0,0 +1,219 @@
@extends('proyectos.brokers.base')
@section('brokers_content')
<table id="brokers" class="ui table">
<thead>
<tr>
<th>RUT</th>
<th>Nombre</th>
<th>Contacto</th>
<th>Contratos</th>
<th class="right aligned">
<button class="ui small tertiary green icon button" id="add_button">
<i class="plus icon"></i>
</button>
</th>
</tr>
</thead>
@foreach($brokers as $broker)
<tr>
<td class="top aligned">
<span
@if ($broker->data()?->legalName !== '')
data-tooltip="{{ $broker->data()?->legalName }}" data-position="right center"
@endif
>
{{$broker->rutFull()}}
</span>
</td>
<td class="top aligned">
<a href="{{ $urls->base }}/proyectos/broker/{{ $broker->rut }}">
{{$broker->name}}
<i class="angle right icon"></i>
</a>
</td>
<td class="top aligned">
<span
@if ($broker->data()?->representative?->email !== '' || $broker->data()?->representative?->phone !== '')
data-tooltip="{{ ($broker->data()?->representative?->email !== '') ? "Email: " . $broker->data()?->representative?->email : '' }}{{ ($broker->data()?->representative?->phone !== '') ? ' Teléfono: ' . $broker->data()?->representative?->phone : '' }}" data-position="right center"
@endif
>
{{ $broker->data()?->representative?->name }}
</span>
</td>
<td class="top aligned">
<div class="ui list">
@foreach($broker->contracts() as $contract)
<div class="item">
<a href="{{$urls->base}}/proyectos/broker/{{$broker->rut}}/contract/{{$contract->id}}" data-tooltip="{{$contract->current()->date->format('d-m-Y')}}" data-position="right center">
{{$contract->project->descripcion}} ({{$format->percent($contract->commission, 2, true)}})
</a>
</div>
@endforeach
</div>
</td>
<td class="top aligned right aligned">
<button class="ui small tertiary icon button edit_button" data-index="{{$broker->rut}}">
<i class="edit icon"></i>
</button>
<button class="ui small tertiary red icon button remove_button" data-index="{{$broker->rut}}">
<i class="remove icon"></i>
</button>
</td>
</tr>
@endforeach
</table>
@include('proyectos.brokers.add_modal')
@include('proyectos.brokers.edit_modal')
@endsection
@push('page_scripts')
<script>
function storeBrokers() {
localStorage.setItem('brokers', '{!! json_encode(array_map(function($broker) {
$arr = json_decode(json_encode($broker), true);
array_walk_recursive($arr, function(&$val, $key) {
if ($val === null) {
$val = '';
}
});
$arr['contracts'] = $broker->contracts();
return $arr;
}, $brokers)) !!}')
}
const brokersHandler = {
ids: {
buttons: {
add: 'add_button',
edit: 'edit_button',
remove: 'remove_button'
},
modals: {
add: '',
edit: ''
},
forms: {
add: '',
edit: ''
}
},
modals: {
add: null,
edit: null
},
events() {
return {
add: clickEvent => {
clickEvent.preventDefault()
brokersHandler.actions().add()
},
edit: clickEvent => {
clickEvent.preventDefault()
const broker_rut = parseInt(clickEvent.currentTarget.dataset.index)
brokersHandler.actions().edit(broker_rut)
},
delete: clickEvent => {
clickEvent.preventDefault()
const broker_rut = clickEvent.currentTarget.dataset.index
brokersHandler.actions().delete(broker_rut)
}
}
},
buttonWatch() {
document.getElementById(brokersHandler.ids.buttons.add).addEventListener('click', brokersHandler.events().add)
Array.from(document.getElementsByClassName(brokersHandler.ids.buttons.edit)).forEach(button => {
button.addEventListener('click', brokersHandler.events().edit)
})
Array.from(document.getElementsByClassName(brokersHandler.ids.buttons.remove)).forEach(button => {
button.addEventListener('click', brokersHandler.events().delete)
})
},
actions() {
return {
add: () => {
this.modals.add.show()
},
edit: broker_rut => {
const localData = JSON.parse(localStorage.getItem('brokers'))
const broker = localData.find(broker => broker.rut === broker_rut)
const data = {
rut: broker_rut,
name: broker.name,
legal_name: broker.data?.legal_name || '',
contact: broker.data?.representative?.name || '',
email: broker.data?.representative?.email || '',
phone: broker.data?.representative?.phone || '',
address: broker.data?.representative?.address || '',
contracts: broker.contracts
}
this.modals.edit.load(data)
},
delete: broker_rut => {
brokersHandler.execute().delete(broker_rut)
}
}
},
execute() {
return {
add: data => {
const url = '{{$urls->api}}/proyectos/brokers/add'
const method = 'post'
const body = new FormData()
body.append('brokers[]', JSON.stringify(data))
return APIClient.fetch(url, {method, body}).then(response => response.json()).then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo agregar operador.')
return
}
window.location.reload()
})
},
edit: data => {
const url = '{{$urls->api}}/proyectos/brokers/edit'
const method = 'post'
const body = new FormData()
body.append('brokers[]', JSON.stringify(data))
return APIClient.fetch(url, {method, body}).then(response => response.json()).then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo editar operador.')
return
}
window.location.reload()
})
},
delete: broker_rut => {
const url = '{{$urls->api}}/proyectos/broker/' + broker_rut
const method = 'delete'
return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
if (!json.success) {
console.error(json.errors)
alert('No se pudo eliminar operador.')
return
}
window.location.reload()
})
}
}
},
setup(ids) {
brokersHandler.ids = ids
brokersHandler.buttonWatch()
this.modals.add = new AddModal(brokersHandler)
this.modals.edit = new EditModal(brokersHandler)
}
}
$(document).ready(() => {
storeBrokers()
brokersHandler.setup({
buttons: {
add: 'add_button',
edit: 'edit_button',
remove: 'remove_button',
},
})
})
</script>
@endpush

View File

@ -0,0 +1,115 @@
<div class="ui modal" id="add_broker_modal">
<div class="header">
Agregar Operador
</div>
<div class="content">
<form class="ui form" id="add_broker_form">
<div class="fields">
<div class="field">
<label>RUT</label>
<div class="ui right labeled input">
<input type="text" name="rut" placeholder="RUT" maxlength="10" required />
<div class="ui basic label">-<span id="digit"></span></div>
</div>
</div>
</div>
<div class="fields">
<div class="field">
<label>Nombre</label>
<input type="text" name="name" placeholder="Nombre" required />
</div>
<div class="six wide field">
<label>Razón Social</label>
<input type="text" name="legal_name" placeholder="Razón Social" required />
</div>
</div>
<div class="fields">
<div class="field">
<label>Contacto</label>
<input type="text" name="contact" placeholder="Contacto" />
</div>
</div>
<div class="fields">
<div class="field">
<label>Correo</label>
<input type="email" name="email" placeholder="Correo" />
</div>
<div class="field">
<label>Teléfono</label>
<input type="text" name="phone" placeholder="Teléfono" />
</div>
</div>
</form>
</div>
<div class="actions">
<div class="ui deny button">
Cancelar
</div>
<div class="ui positive right labeled icon button">
Agregar
<i class="checkmark icon"></i>
</div>
</div>
</div>
@include('layout.body.scripts.rut')
@push('page_scripts')
<script>
class AddModal {
ids
modal
handler
constructor(handler) {
this.handler = handler
this.ids = {
modal: 'add_broker_modal',
form: 'add_broker_form',
digit: 'digit'
}
this.modal = $(`#${this.ids.modal}`)
this.modal.modal({
onApprove: () => {
const form = document.getElementById(this.ids.form)
const data = {
rut: form.querySelector('[name="rut"]').value.replace(/\D/g, ''),
digit: Rut.digitoVerificador(form.querySelector('[name="rut"]').value),
name: form.querySelector('[name="name"]').value,
legal_name: form.querySelector('[name="legal_name"]').value,
contact: form.querySelector('[name="contact"]').value || '',
email: form.querySelector('[name="email"]').value || '',
phone: form.querySelector('[name="phone"]').value || ''
}
this.handler.execute().add(data)
}
})
this.modal.modal('hide')
const value = document.querySelector(`#${this.ids.form} input[name="rut"]`).value
this.update().digit(value)
this.watch().rut()
}
update() {
return {
digit: value => {
if (value.length > 3) {
document.getElementById(this.ids.digit).textContent = Rut.digitoVerificador(value)
}
}
}
}
watch() {
return {
rut: () => {
document.querySelector(`#${this.ids.form} input[name="rut"]`).addEventListener('input', event => {
const value = event.currentTarget.value
this.update().digit(value)
})
}
}
}
show() {
this.modal.modal('show')
}
}
</script>
@endpush

Some files were not shown because too many files have changed in this diff Show More